【Linux】:进程间通信和日志模拟

进程间通信

  • 一.基本概念
  • 二.简单的通信-管道(匿名管道)
    • 1.建立通信信道
    • 2.通信接口
  • 三.命名管道
  • 三.模拟命名管道通信(加上日志)
    • 1.完整代码
    • 2.基本使用

一.基本概念

是什么

两个或多个进程实现数据层面的交互。

因为进程独立性的存在,导致进程间的通信成本比较高。

为什么

因为我们有多进程协同的需求。

怎么办

a.进程间通信的本质:必须让不同的进程看到同一份"资源"。
b.“资源”?特定形式的内存空间。
c.这个"资源"谁提供?一般是操作系统。
d.我们进程访问这个空间,进行通信,本质就是访问操作系统!进程代表的就是用户,“资源”从创建,使用(一般),释放―–需要系统调用接口!一般操作系统会有一个独立的通信模块-隶属于文件系统-IPC通信模块。

二.简单的通信-管道(匿名管道)

管道是Unix中最古老的进程间通信的形式。 我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”。

在这里插入图片描述

1.建立通信信道

管道是一个文件-内存级文件。

1.管道文件与一般文件不同,一般文件存在于磁盘里,管道文件存在于内存里。也就是说管道文件不需要将修改内容从内存刷新缓冲区到磁盘,这是它的特点。

2.一般管道文件只能具有血缘关系的进程间通信。因为只有具有血缘关系才能继承同一份files_struct。

3.一个父进程在创建管道文件时不能只是以读或者写的方式,必须两者都有。操作系统会把这个文件打开两次,分别用来读和写。但操作系统实际上只想让两个进程进行单向通信,因为如果一个进程又在读又在写,很容易会造成数据混淆,为了避免麻烦,规定只能一个进程写,另一个进程读。

在这里插入图片描述

这个文件不需要有名字,inode…让操作系统区分。所以这种文件也被称为匿名管道。

2.通信接口

在这里插入图片描述

pipe的作用就是帮助我们以读和写打开文件。它的参数是一个输出型参数,它会把分别以读和写的文件的文件描述符通过参数带出,供用户使用。pipefd[0]一般用于读,pipefd[1]一般用于写。

模拟

makefile

testPipe:TestPipe.cppg++ -o $@ $^ -std=c++11
.PHONY:clean
clean:rm -f testPipe

TestPipe.cpp(一个简单的通信,子进程向父进程里写信息)

#include<stdio.h>
#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<string>
#include<cstdio>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>using namespace std;
#define N 2
#define NUM 1024//子进程
void Write(int wfd)
{//任意写几个数据测试string s="hello,i am a child";pid_t id=getpid();int num=0;char buffer[NUM];while(1){snprintf(buffer,sizeof(buffer),"%s-%d-%d\n",s.c_str(),id,num++);//将数据都变成字符存在buffer里//把数据写入管道write(wfd,buffer,strlen(buffer));sleep(1);}
}//父进程
void Read(int rfd)
{char buffer[NUM]={0};while(1){ssize_t n=read(rfd,buffer,sizeof(buffer));if(n>0){cout<<buffer<<endl;}else if(n==0) break;}}int main()
{int pipefd[N]={0};//创建管道int n=pipe(pipefd);//判断是否创建成功if(n<0) return 1;//创建子进程pid_t id=fork();if(id<0) return 2;if(id==0){//子进程//关闭读功能close(pipefd[0]);//IPC codeWrite(pipefd[1]);//退出close(pipefd[1]);exit(0);}//父进程//关闭写功能close(pipefd[1]);//IPC codeRead(pipefd[0]);//退出//回收子进程pid_t rid=waitpid(id,nullptr,0);if(rid<0) return 3;close(pipefd[0]);return 0;
}

在这里插入图片描述

管道的4中情况:
1.读写端正常,管道如果为空,读端就要阻塞 2读写端正常,管道如果被写满,写端就要阻塞 3.读端正常读,写端关闭,读端就会读到0,表明读到了文件(pipe)结尾,不会被阻塞
4,写端正常写入,读端被关闭。操作系统就要杀掉正在写入的进程。如何干掉?通过信号杀掉。

管道的特征:
1.具有血缘关系的进程进行进程间通信。
2.管道只能单向通信。
3.父子进程是会进程协同的,同步与互斥的—保护管道文件的数据安全 4.管道是面向字节流的。
5.管道是基于文件的,而文件的生命周期是随进程的!

三.命名管道

很明显上面的匿名管道只使用于具有血缘关系的通信是远远不够的,为了解决这个问题,又有了命名管道的概念。

如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件。

makefile

在这里插入图片描述

创建一个命名管道命名为myfifo

在这里插入图片描述

三.模拟命名管道通信(加上日志)

1.完整代码

日志(log.hpp)

#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>#define SIZE 1024#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4#define Screen 1
#define Onefile 2
#define Classfile 3#define LogFile "log.txt"class Log
{
public:Log(){//初始化打印方式和路径printMethod=Screen;path="./log/";}~Log(){}//改变打印方式void Enable(int methed){printMethod=methed;}//把整形转换成字符串std::string levelToString(int level){switch (level){case Info:return "Info";case Debug:return "Debug";case Warning:return "Warning";case Error:return "Error";case Fatal:return "Fatal";default:return "None";}}void printOneFile(const std::string &logname, const std::string &logtxt){std::string _logname=path+logname;//连接文件路径int fd=open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);//打开文件if (fd < 0) return;//向文件里写入write(fd, logtxt.c_str(), logtxt.size());close(fd); }void printClassFile(int level,const std::string &logtxt){std::string filename=LogFile+'.'+levelToString(level);//拼接路径printOneFile(filename,logtxt);}void printLog(int level,const std::string &logtxt){//选择打印方式switch (printMethod){case Screen://向屏幕打印std::cout << logtxt << std::endl;break;case Onefile://向一个文件里打印printOneFile(LogFile, logtxt);break;case Classfile://向多个文件里打印printClassFile(level, logtxt);break;default:break;}}//重载括号,让其能像log s; s(...)一样使用void operator()(int level,const char*format, ...){//首先将时间加入日志time_t t=time(nullptr);struct tm*ctime=localtime(&t);char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,ctime->tm_hour, ctime->tm_min, ctime->tm_sec);//接着将用户输入部分加入//处理可变参数va_list s;va_start(s,format);char rightbuffer[SIZE];vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);//将两个部分合并char logtxt[2*SIZE];snprintf(logtxt,sizeof(logtxt),"%s %s\n",leftbuffer,rightbuffer);//打印到对应位置printLog(level, logtxt);}
private:int printMethod;std::string path;
};

创建管道(comm.hpp)

#pragma once#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>#define FIFO_FILE "./myfifo"
#define MODE 0664enum
{FIFO_CREATE_ERR = 1,FIFO_DELETE_ERR,FIFO_OPEN_ERR
};class Init
{
public:Init(){// 创建管道int n = mkfifo(FIFO_FILE, MODE);if (n == -1){perror("mkfifo");exit(FIFO_CREATE_ERR);}}~Init(){int m = unlink(FIFO_FILE);if (m == -1){perror("unlink");exit(FIFO_DELETE_ERR);}}
};

管道通信读取方(server.cc)

#include "comm.hpp"
#include "log.hpp"using namespace std;// 管理管道文件
int main()
{Init init;Log log;// log.Enable(Onefile);log.Enable(Onefile);// 打开管道int fd = open(FIFO_FILE, O_RDONLY); // 等待写入方打开之后,自己才会打开文件,向后执行, open 阻塞了!if (fd < 0){log(Fatal, "error string: %s, error code: %d", strerror(errno), errno);exit(FIFO_OPEN_ERR);}log(Info, "server open file done, error string: %s, error code: %d", strerror(errno), errno);log(Warning, "server open file done, error string: %s, error code: %d", strerror(errno), errno);log(Fatal, "server open file done, error string: %s, error code: %d", strerror(errno), errno);log(Debug, "server open file done, error string: %s, error code: %d", strerror(errno), errno);// 开始通信while (true){char buffer[1024] = {0};int x = read(fd, buffer, sizeof(buffer));if (x > 0){buffer[x] = 0;cout << "client say# " << buffer << endl;}else if (x == 0){log(Debug, "client quit, me too!, error string: %s, error code: %d", strerror(errno), errno);break;}elsebreak;}close(fd);return 0;
}

管道通信写入方(client.cc)

#include <iostream>
#include "comm.hpp"using namespace std;int main()
{int fd = open(FIFO_FILE, O_WRONLY);if(fd < 0){perror("open");exit(FIFO_OPEN_ERR);}cout << "client open file done" << endl;string line;while(true){cout << "Please Enter@ ";getline(cin, line);write(fd, line.c_str(), line.size());}close(fd);return 0;
}

makefile

.PHONY:all
all:server clientserver:server.ccg++ -o $@ $^ -g -std=c++11mkdir log
client:client.ccg++ -o $@ $^ -g -std=c++11.PHONY:clean
clean:rm -f server clientrm -r log

2.基本使用

上面代码是向log.txt文件里写入。我们首先运行读文件,再运行写文件。任意通信,然后关闭进程,再打开log.txt,就可以看到日志已经写入。

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153862.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广度优先算法(BFS)

广度优先算法&#xff08;Breadth-First Search&#xff09;是在图和树领域的搜索方法&#xff0c;其核心思想是从一个起始点开始&#xff0c;访问其所有的临近节点&#xff0c;然后再按照相同的方式访问这些临近节点的节点&#xff0c;这种访问方式类似涟漪泛起&#xff0c;一…

HINSTANCE是什么?

HINSTANCE 就是 HMODULE&#xff1a;

队列OJ--循环队列

目录 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#xff1a; ​编辑 代码实现&#xff1a; 完整代码&#xff1a; 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#x…

jenkins传参给robotframework

在做自动化的时候&#xff0c;需要使用jenkins传参给rf&#xff0c;rf根据传来的变量运行&#xff0c;在将变量传递给py脚本文件。特此记录。 一、配置jenkins 构建的命令使用如下格式即可&#xff08;注意空格&#xff09;&#xff1a; cd D:\xxx\test call pybot --variabl…

砖家测评:腾讯云标准型S5服务器和s6性能差异和租用价格

腾讯云服务器CVM标准型S5和S6有什么区别&#xff1f;都是标准型云服务器&#xff0c;标准型S5是次新一代云服务器规格&#xff0c;标准型S6是最新一代的云服务器&#xff0c;S6实例的CPU处理器主频性能要高于S5实例&#xff0c;同CPU内存配置下的标准型S6实例要比S5实例性能更好…

视频剪辑技巧:批量剪辑新篇章,AI智剪来领航

随着数字媒体的飞速发展&#xff0c;视频剪辑已经成为一项重要的工作。在繁忙的工作中&#xff0c;如何高效、准确地完成批量剪辑是一项具有挑战性的任务。近年来&#xff0c;AI智剪的出现为视频剪辑工作带来了新的解决方案&#xff0c;引领着批量剪辑的新篇章。在AI智剪的帮助…

为了摆脱 Android ,亚马逊开发基于Linux的操作系统

导读亚马逊一直在开发一种新的操作系统 —— 内部代号为 “Vega”&#xff0c;以便在 Fire TV、智能显示器和其他联网设备上取代 Android 系统。 亚马逊一直在开发一种新的操作系统 —— 内部代号为 “Vega”&#xff0c;以便在 Fire TV、智能显示器和其他联网设备上取代 Andr…

终于有人把数据资产入表知识地图总结出来了,轻松看懂

在当前数字化的浪潮下&#xff0c;数据已经成为劳动、土地、知识、技术以后的第五大生产要素&#xff0c;“数据就是资源”已成为共识。如今数据资产“入表”已成定局&#xff0c;数据资产化迫在眉睫。 2023年8月21日&#xff0c;财政部正式印发《企业数据资源相关会计处理暂行…

什么样的企业可以使用免费版的CRM?

市面上大部分的免费CRM不需要付费即可使用&#xff0c;但是对于使用人数和功能进行了部分限制。下面我们就来说说&#xff0c;免费CRM的适用对象是谁&#xff1f; 1、初创/小微企业 这种小微企业没有太多的资金&#xff0c;也没有复杂的客户管理需求&#xff0c;仅仅需要一款…

生产环境_移动目标轨迹压缩应用和算法处理-Douglas-Peucker轨迹压缩算法

场景&#xff1a; 我目前设计到的场景是&#xff1a;以路面上行驶的汽车为例&#xff0c;即在地图应用中&#xff0c;对GPS轨迹数据进行压缩&#xff0c;减少数据传输和存储开销&#xff0c;因为轨迹点太频繁了&#xff0c;占用空间太大&#xff0c;运行节点太慢了&#xff0c…

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现)

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现) 0、功能展示1、项目原理介绍2、数据集采集脚本3、将采集到的动作数据集利用mediapipe库检测手部关键点信息,转换成数据信息保存到本地4、训练一个效果一般的随机森林分类器5、使用Kreas训练一个效果好点的全连…

提高软件测试覆盖率的5个重点

软件测试覆盖率是软件测试中的一个重要指标&#xff0c;它有利于保障软件质量、提高软件可靠性和可维护性。软件测试覆盖率能够发现并修复代码缺陷&#xff0c;确保代码的正确性&#xff0c;提高软件的稳定性&#xff0c;降低成本和风险。 因此进一步提高软件测试覆盖率对于软件…

Oauth2认证及Spring Security Oauth2授权码模式

Oauth2认证 Oauth2简介 简介 第三方认证技术方案最主要是解决认证协议的通用标准问题&#xff0c;因为要实现跨系统认证&#xff0c;各系统之间要遵循一定的接口协议。 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时&#xff0c;任何第三方都可以使…

ICCV 23丨3D-VisTA:用于 3D 视觉和文本对齐的预训练Transformer

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2308.04352 开源代码&#xff1a;http://3d-vista.github.io 摘要&#xff1a; 3D视觉语言标定&#xff08;3D-VL&#xff09;是一个新兴领域&#xff0c;旨在将…

centos7安装mysql8

打开Mysql下载页面 https://downloads.mysql.com/archives/community/ 选择版本号&#xff1a; centos选择Red Hat版本&#xff0c;复制地址 复制地址后&#xff0c;链接ssh&#xff0c;添加储存库 yum install 粘贴地址&#xff1b; yum install https://downloads.mysql…

人工智能基础_机器学习044_使用逻辑回归模型计算逻辑回归概率_以及_逻辑回归代码实现与手动计算概率对比---人工智能工作笔记0084

上面我们已经把逻辑回归的公式,以及,公式对应的图形都画画出来了,然后我们再来看看 如何用代码实现 可以看到上面是代码,咱们自己去写一下 import numpy as np from sklearn.linear_model import LogistieRegression from sklearn import datasets # 训练数据和测试数据拆分…

人工智能时代下的程序员核心竞争力:构建专属护城河

选题建议&#xff1a;《人工智能时代下的程序员核心竞争力&#xff1a;构建你的护城河》 大纲&#xff1a; I. 引言 A. 人工智能时代的发展趋势B. 程序员面临的挑战与机遇 I. 引言 A. 人工智能时代的发展趋势 随着科技的飞速进步&#xff0c;我们已经踏入了一个日新月异的人工…

Leetcode—2216.美化数组的最少删除数【中等】

2023每日刷题&#xff08;三十六&#xff09; Leetcode—2216.美化数组的最少删除数 实现代码 int minDeletion(int* nums, int numsSize) {int last nums[0], flag 1, ans 0;for(int i 1; i < numsSize; i) {if(flag) { // 前一个下标为偶数if(nums[i] last) {…

Linux C 线程

线程 概述线程和进程的异同如何选择使用进程还是线程 函数获取进程自身ID  pthread_self创建线程  pthread_create退出线程  pthread_exit线程等待  pthread_join 四种线程模型1 &#xff09;单线程2 &#xff09;单线程3 &#xff09;双线程4 &#xff09;三线程 概述…

【HarmonyOS】低代码平台组件拖拽使用技巧之列表

【关键字】 HarmonyOS、低代码平台、组件拖拽、列表、列表项 1、写在前面 我们在日常开发中使用最多的组件可能就是列表组件了&#xff0c;现在几乎所有的应用都离不开列表&#xff0c;那么今天我们就来介绍一下如何利用低代码平台来实现列表的展示&#xff0c;列表实际上也是…