【linux进程间通信(一)】匿名管道和命名管道

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:Linux从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学更多操作系统知识
  🔝🔝


在这里插入图片描述

进程间通信

  • 1. 前言
  • 2. 进程间通信的方法
  • 3. 管道的简单介绍
  • 4. 匿名管道
  • 5. 命名管道
  • 6. 总结以及拓展

1. 前言

众所周知,进程运行是具有独立性的,
想要进程间进行通信就要打破这种
独立性,而进程间通信的本质其实是
让不同的进程看见同一份资源!

本章重点:

本篇文章会介绍进程间通信中常见
的几种方式,并且着重讲解匿名管道
和命名管道的这两种通信手段的原理
和代码的实现.


2. 进程间通信的方法

首先通信种类分为三大类:

  • 管道
  • system V
  • POSIX

在这里插入图片描述
当然网络通信的本质其实也是进程
间的通信,但是本篇文章的重点是
利用管道通信!!!


3. 管道的简单介绍

首先要回答什么是管道,在学习
Linux指令时我们使用过竖划线 |
也就是管道,把从一个进程连接
到另一个进程的数据流称为“管道”

在这里插入图片描述

在管道通信中,管道的本质其实就是
一个被系统打开的文件,然而用管道
进行通信的本质就是让不同的进程
看见相同的资源(文件)

并且管道是单向通信的,即一个进程
不能同时从一个管道中读取和写入,
读取和写入要对应两个不同的管道!


4. 匿名管道

在这里插入图片描述

对于匿名管道来说,通常用于父子
进程之间的通信,在父进程使用
pipe创建好管道后,再使用fork创建
子进程,此时子进程会将父进程的
文件描述符表给拷贝过来,也就天然
的拥有这两个管道文件了!

在这里插入图片描述
并且此时我们会面临两个问题:

  1. 读取方将文件关闭了会发送什么?
  2. 读取方在文件中没有数据时会干什么?
  • 读端关闭后,写端进程会终止
  • 当管道无数据时读端会阻塞

有了上面的经验后,现在可以编码验证一下:

int main()
{//创建管道int pipefd[2]={0}; //0下标表示读取端,1下标表示写入端int n = pipe(pipefd);assert(n!=-1);(void)n;
#ifdef DEBUG//条件编译cout<<"[0]: "<<pipefd[0]<<" "<<"[1]: "<<pipefd[1]<<endl;
#endif//创建子进程pid_t id = fork();assert(id!=-1);if(id==0)//子进程, 构建单向通信{close(pipefd[1]);char buffer[1024];while(1){ssize_t s = read(pipefd[0],buffer,sizeof(buffer)-1);if(s>0){buffer[s]=0;cout<<"father# "<<buffer<<endl;}else//read的返回值等于0代表父进程的管道文件已经close了{cout<<"写入结束,子进程退出";break;}}exit(0);}//父进程写入,子进程读取close(pipefd[0]);string str = "我在给子进程发信息";int count=0;char send_buffer[1024];while(count<=5){//构建一个变化的字符串snprintf(send_buffer, sizeof(send_buffer),"%s[%d]: %d",str.c_str(),getpid(),count++);//往缓冲区里写入数据//写入到管道中write(pipefd[1],send_buffer,sizeof(send_buffer));sleep(1);}close(pipefd[1]);pid_t ret = waitpid(id,NULL,0);assert(ret > 0);return 0;
}

总结管道的特点:

  • 管道常用于父子进程间的通信
  • 管道是面向字节流的服务
  • 管道是基于文件的,管道的生命周期随进程
  • 管道是单向通信的
  • 写快读慢,写满管道后不能再写了
  • 写慢读快,管道没有数据时,读端要等待
  • 写端关闭,读端会读到0,标识结束
  • 读端关闭,写端继续写会终止进程

5. 命名管道

匿名管道的一个限制就是必须是在
有血缘关系的进程间才能通信,使用
命名管道可以解决这个问题

在这里插入图片描述

匿名管道和命名管道的区别:

  • 匿名管道由pipe函数创建并打开。
  • 命名管道由mkfifo函数创建,打开用open
  • FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。

命名管道的打开规则:

  • 如果当前打开操作是为读而打开FIFO时
  1. O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
  2. O_NONBLOCK enable:立刻返回成功
  • 如果当前打开操作是为写而打开FIFO时
  1. O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
  2. O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

命名管道简单通信:

读端代码:

#define SIZE 1024
#define MODE 0666
string ipcpath = "./fifo.ipc";
static void getmessage(int fd)
{//编写通信代码char buffer[SIZE];while(1){memset(buffer,'\0',sizeof(buffer));ssize_t s = read(fd,buffer,sizeof(buffer)-1);if(s>0)//读取成功{cout<<"["<<getpid()<<"] "<<"client say: "<<buffer<<endl;}else if(s==0)//写端关闭,并且读到end{cerr<<"["<<getpid()<<"]"<<"read end"<<endl;break;}else//读取失败{perror("read");break;}}
}
int main()
{//创建管道文件int n = mkfifo(ipcpath.c_str(),MODE);if(n<0){perror("mkfifo");exit(1);}//文件操作int fd = open(ipcpath.c_str(),O_RDONLY);//这里必须等待client进程将此管道文件打开后才能执行下面的代码if(fd<0){perror("open");exit(2);}for(int i=0;i<4;i++){int id = fork();if(id==0){getmessage(fd);exit(0);}}close(fd);return 0;
}

写端代码:

#define SIZE 1024
#define MODE 0666
string ipcpath = "./fifo.ipc";
int main()
{//client不用自己创建管道文件,只需获取文件即可int fd = open(ipcpath.c_str(),O_WRONLY);if(fd<0){perror("open");exit(1);}//通信过程string buffer;while(1){cout<<"please Enter message: ";getline(cin,buffer);write(fd,buffer.c_str(),buffer.size());}close(fd);return 0;
}

6. 总结以及拓展

虽然匿名管道和命名管道已经包含了
对于有血缘关系和无血缘关系的进程
的通信,但是毕竟调用read和write这些
系统调用接口会不断的在用户态和内核
态进行切换,比较消耗资源,所以管道不是
最好的!

拓展: 为什么读端关闭后,写端进程会终止?

这是因为当读端关闭后,写端再使用
write操作会产生SIGPIPE信号,此进
程收到此信号进而会终止进程,可以
使用捕捉信号的方式验证这一结论


🔎 下期预告:共享内存通信方式 🔍

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

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

相关文章

微软与沃达丰签订10年合作,提供Copilot等生成式AI服务

1月16日&#xff0c;微软在官网宣布&#xff0c;与全球最大电信公司之一沃达丰&#xff08;Vodafone&#xff09;签订10年合作协议&#xff0c;将为3亿多企业、消费者提供生成式AI、云和数字服务等。 通过此次合作&#xff0c;沃达丰将利用微软的Copilot等生成式AI来改变客户、…

VScode远程开发

VScode远程开发 在SSH远程连接一文中&#xff0c;我么介绍了如何使用ssh远程连接Jetson nano端&#xff0c;但是也存在诸多不便&#xff0c;比如:编辑文件内容时&#xff0c;需要使用vi编辑器&#xff0c;且在一个终端内&#xff0c;无法同时编辑多个文件。本节将介绍一较为实用…

C语言:预处理详解

创作不易&#xff0c;来个三连呗&#xff01; 一、预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编…

【Alibaba工具型技术系列】「EasyExcel技术专题」摒除OOM!让你的Excel操作变得更加优雅和安全

摒除OOM&#xff01;让你的Excel操作变得更加优雅和安全 前提概要存在隐患问题解决方案更优秀的选择 EasyExcel的介绍说明技术原理对比POIEasyExcel技术原理图节省内存的开销 Maven仓库依赖基础API介绍&#xff08;参考官方文档&#xff09;实战案例读取Excel实现Demo数据模型D…

跨域原理和解决方案

前置知识 什么是跨域 主要是由于浏览器的同源策略引起的&#xff0c;同源策略是浏览器的安全机制&#xff0c;当 协议&#xff0c;域名&#xff0c;端口 三者有一个不同&#xff0c;浏览器就禁止访问资源。 比如&#xff1a;http://www.company.com:80 http://www.company.…

绝地求生【违规处罚工作公示】1月8日-1月14日

1月8日至1月14日期间&#xff0c;共计对174,636个违规账号进行了封禁&#xff0c;其中164,757个账号因使用外挂被永久封禁。 若您游戏中遇到违规行为&#xff0c;建议您优先在游戏内进行举报&#xff1b; 另外您也可以在官方微信公众号【PUBG国际版】中点击“ 服务中心 - 举报…

【启扬方案】基于RK3568核心板的工业示教器解决方案

机器人作为现代制造业中的重要一环&#xff0c;在生产效率、产品质量和劳动安全等方面带来了巨大的提升&#xff0c;给企业带来了巨大的竞争优势。但机器人的应用存在开发难、安全性差等问题。“示教器”可用丰富的组件解决机器人开发难的问题&#xff0c;且自带的监控功能可提…

[HTML]Web前端开发技术14(HTML5、CSS3、JavaScript )鼠标经过图片显示大图 网页标题:表格标签的综合应用——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

压缩编码之不同缩放参数对重建图像质量的影响的python实现——JPEG变换编码不同压缩率的模拟

原理 JPEG&#xff08;Joint Photographic Experts Group&#xff09;是一种常用的图像压缩标准&#xff0c;它通过采用离散余弦变换&#xff08;DCT&#xff09;和量化来实现图像的压缩。 离散余弦变换&#xff08;DCT&#xff09;&#xff1a; JPEG首先将图像分割成8x8的块…

阿里云国际虚拟数字人服务如何助力企业出海?

随着越来越多的中国企业开始走向全球&#xff0c;越来越多的电商&#xff0c;选择开始走向全球化&#xff0c;对于电商来说&#xff0c;走向全球化的电商直播&#xff0c;所面临语言的问题&#xff0c;随而出现。小语种主播相较于英语主播更不好招聘&#xff0c;在一线城市招聘…

使用 Python 第三方库 xlwt 写入数据到 Excel 工作表

1. 安装 xlwt 库 Python 写入数据到 Excel 工作簿中可以使用第三方库 xlwt. xlwt 拆分下来看就是 excel 和 write 的简化拼接&#xff0c;意思就是写数据到 Excel. 这个第三方库的 pip 安装命令如下所示&#xff1a; pip install xlwt -i https://mirrors.aliyun.com/pypi/si…

PyTorch 中的距离函数深度解析:掌握向量间的距离和相似度计算

目录 Pytorch中Distance functions详解 pairwise_distance 用途 用法 参数 数学理论公式 示例代码 cosine_similarity 用途 用法 参数 数学理论 示例代码 输出结果 pdist 用途 用法 参数 数学理论 示例代码 总结 Pytorch中Distance functions详解 pair…