Linux进程间通信之管道

进程间通信介绍:

进程间通信的概念:

进程间通信简称IPC(Interprocess communication),进程间通信就是在不同进程之间传播或交换信息。

进程间通信的目的:

数据传输: 一个进程需要将它的数据发送给另一个进程。
资源共享: 多个进程之间共享同样的资源。
通知事件: 一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件,比如进程终止时需要通知其父进程。
进程控制: 有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。

进程间通信的本质:

进程间通信的本质就是让不同的进程看到同一份资源。

进程间通信的发展:

管道
System V进程间通信
POSIX进程间通信

进程间通信的分类: 

管道

  • 匿名管道
  • 命名管道

System V IPC

  • System V 消息队列
  • System V 共享内存
  • System V 信号量

POSIX IPC

  • 消息队列
  • 共享内存
  • 信号量
  • 互斥量
  • 条件变量
  • 读写锁

管道:

认识管道:

由于进程间具有独立性,想要实现进程间通信非常困难,想要实现进程间通信就必须借助第三方资源,让两个需要通信的进程都可访问这个第三方资源,早期管道就是这样的第三方资源来实现进程间通信。

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

演示:

先来介绍两个命令:

1.who

who指令可以用来显示当前云服务器登录的用户数,一行显示一个用户。

如图所示现在有2个用户。 

 2.wc

wc指令可以查指定文件的计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据

wc加上-l指令,计算指定文件的行数。

将上述两个命令通过管道连接,就可以更准确地查出当前云服务器的登录用户:

who进程将数据写入管道,wc从管道中读取到数据,-l指令计算数据的行数,从而得出当前云服务器的登录数。 

匿名管道:

匿名管道性质: 

匿名管道仅支持父子间进程通信。

当我们创建一个进程,在linux系统中它被如下图进行管理:

我们再通过这个进程创建一个子进程,子进程继承父进程的代码和数据:

 没错,此时我们的父子进程能看到同一份资源,我们可以模拟一下通信,父进程往缓冲区写入,子进程往缓冲区读取,早期的工程师发现了这种现象,并且认为这是一种很好的进程间通信的方法,就在这种方法的基础上进行了一下改动,创造了管道。

注意:

我们在进程间通信时,是没必要对磁盘中的文件进行操作的,所以我们的管道没必要与磁盘中的文件产生关联。

文件级缓冲区是由操作系统来维护的,所以当父进程对其写入时,是不会发生写时拷贝的。

pipe函数:

int pipe(int pipefd[2]);

 pipe函数的参数是一个输出型参数,数组pipefd中的两个元素分别用来返回管道读端和写端的文件描述符:

数组元素含义
pipefd[0]管道读端文件描述符
pipefd[1]管道写端文件描述符

 匿名管道的使用:

注意下图中的fd均指pipefd。

1.父进程用pipe函数创建管道。

2.父进程通过fork函数创建子进程。

3.假设我们让子进程写,父进程读,所以我们要关闭不用的文件描述符,父进程关闭写端,子进程关闭读端。

 我们再站在文件描述符的角度深入理解:

匿名管道测试: 

现在用下述代码测试匿名管道,父进程进行一直读取,子进程进行一直写入:

#include <iostream>
#include <cerrno>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>const int size = 1024;//子进程进行写入
void SubProcessWrite(int wrd)
{std::string message = "father,i am your childen process! ";while(true){sleep(1);std::cout<<"childen begin write........."<<std::endl;static int cent = 0;pid_t id = getpid();//拼接消息std::string info = message;info += "my pid is ";info += std::to_string(id);info += ", cent: ";info += std::to_string(cent);//写入write(wrd,info.c_str(),info.size());cent++;}
}
//父进程进行读取
void FatherProcessReader(int rfd)
{char inbuffer[size];while(true){std::cout<<"father begin read,message:"<<std::endl;ssize_t n = read(rfd,inbuffer,sizeof(inbuffer) - 1);//读取消息if(n > 0){inbuffer[n] = 0;//语言限制,在字符串最后加\0std::cout<<inbuffer<<std::endl;//打印消息}}
}
int main()
{int pipefd[2];int n = pipe(pipefd);//管道创建成功,返回0if(n != 0)//管道创建失败{std::cerr<<"errno "<<errno<<"cerrstring: "<<strerror(errno)<<std::endl;}std::cout<<"读端->pipefd[0]"<<pipefd[0]<<"写端->pipefd[1]"<<pipefd[1]<<std::endl;sleep(1);pid_t id = fork();//创建子进程if(id == 0){//子进程进行写入std::cout<<"子进程关闭不需要的fd了,准备写消息了"<<std::endl;close(pipefd[0]);//关闭读端SubProcessWrite(pipefd[1]);//子进程写close(pipefd[1]);//任务完成关闭写端exit(0);}//父进程std::cout<<"父进程关闭不需要的fd了,准备读消息了"<<std::endl;close(pipefd[1]);//关闭写端FatherProcessReader(pipefd[0]);//父进程读close(pipefd[0]);//任务完成关闭读端pid_t rid = waitpid(id,NULL,0);//父进程等待子进程,并回收return 0;
}

来看看运行结果:

 管道的4种情况:

1.写端进程不写,读端进程一直读,那么此时会因为管道里面没有数据可读,对应的读端进程会被挂起,直到管道里面有数据后,读端进程才会被唤醒。


2.读端进程不读,写端进程一直写,那么当管道被写满后,对应的写端进程会被挂起,直到管道当中的数据被读端进程读取后,写端进程才会被唤醒。


3.写端进程将数据写完后将写端关闭,那么读端进程将管道当中的数据读完后,就会继续执行该进程之后的代码逻辑,而不会被挂起。


4.读端进程将读端关闭,而写端进程还在一直向管道写入数据,那么操作系统会将写端进程杀掉。

管道的大小:

管道是有容量的,当管道被写满了,写端将会阻塞或者失败,查询管道大小的方法有如下:

ulimit -a指令,查看当前资源限制。

从上图可以算出管道的大小为512*8 = 4096字节。 

命名管道:

刚才介绍的匿名管道,只可用于父子进程间通信,如果两个毫不相干的进程要实现通信该怎么办呢?接下来就需要介绍一下命名管道了。

mkfifo函数:

mkfifo函数用于创建一个命名管道。

mkfifo的第一个参数表示要创建的命令管道文件,如果不带路径默认再当前文件夹下。

mkfifo的第二个参数表示管道的文件权限。

例如文件权限设置为0666,则理论创建的管道权限为

 但实际文件权限还会受文件默认掩码umask影响,默认的umask是0002,我们实际的文件权限会先0666&(~umask),所以实际管道权限为0664:

mkfifo的返回值: 

管道创建成功返回0。

创建管道失败返回-1,错误码被设置。 

用命名管道实现serve&client通信

serve管理管道负责创建,销毁和读取消息,client负责往管道中写入消息:

serve.cc:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>const std::string comm_name = "./myfifo";int main()
{//服务端创建命名管道int res = mkfifo(comm_name.c_str(),0666);if(res != 0)//创建失败{perror("mkfifo");}//serve端打开管道int fd = open(comm_name.c_str(),O_RDONLY);if(fd < 0){std::cout<<"open file"<<errno<<std::endl;}//serve接受消息并打印char buffer[1024];while(true){std::cout<<"server begin read:"<<std::endl;ssize_t n = read(fd,buffer,sizeof(buffer)-1);if(n > 0)//读取成功{buffer[n] = 0;std::cout<<buffer<<std::endl;}else if( n == 0){std::cout<<"read done"<<std::endl;break;}else{std::cout<<"read fail"<<errno<<std::endl;break;}}int n = unlink(comm_name.c_str());if(n != 0){perror("unlink");}return 0;
}

client.cc:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>const std::string comm_name = "./myfifo";int main()
{//client以写打开管道int fd = open(comm_name.c_str(),O_WRONLY);if(fd < 0){std::cout<<"open fail"<<errno<<std::endl;}int cent = 100;sleep(5);while(cent--){sleep(1);std::cout<<"client begin write"<<std::endl;//消息拼接std::string message = "i sent a message ,cnet: ";message += std::to_string(cent);//写入消息ssize_t n = write(fd,message.c_str(),sizeof(message));}return 0;
}

来看看运行结果:

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

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

相关文章

开源WebGIS全流程常用技术栈

1 数据生产 1.1 uDig uDig&#xff08;http://udig.refractions.net/&#xff09;是一个基于Java开源的桌面应用框架&#xff0c;它构建在Eclipse RCP和GeoTools&#xff08;一个开源的Java GIS包)上。可以进行shp格式地图文件的编辑和查看&#xff1b;是一个开源空间数据查看…

​在哪些场景下,使用SOCKS5代理会特别有用?(socks5代理ip)​

SOCKS5代理作为网络协议转换的利器&#xff0c;其独特功能在众多实际场景中展现出了极大的价值。以下是几个特定场景&#xff0c;其中SOCKS5代理的使用将变得尤为重要&#xff1a; 一、网络安全与隐私访问 1.高级渗透测试&#xff1a;在网络安全领域&#xff0c;渗透测试人员…

MS21112S单通道 LVDS 差分线路接收器

MS21112S 是一款单通道低压差分信号 (LVDS) 线 路接收器。在输入共模电压范围内&#xff0c;差分接收器可以 将 100mV 的差分输入电压转换成有效的逻辑输出。 该芯片可应用于 100Ω 的受控阻抗介质上&#xff0c;进行点对 点基带数据传输。传输介质可以是印刷电路板、…

配音方面目前可以用AIGC替代吗?( 计育韬老师高校公益巡讲答疑实录2024)

这是计育韬老师第 8 次开展面向全国高校的新媒体技术公益巡讲活动了。而在每场讲座尾声&#xff0c;互动答疑环节往往反映了高校师生当前最普遍的运营困境&#xff0c;特此计老师在现场即兴答疑之外&#xff0c;会尽量选择有较高价值的提问进行文字答疑梳理。 *本轮巡讲主题除了…

360误删掉的文件怎么恢复?3种文件找回办法!

360是一款电脑安全辅助软件&#xff0c;可以用它来清理垃圾、查杀病毒、修复系统等。然而&#xff0c;有时文件可能会被360误认为是垃圾而自动清理&#xff0c;造成重要文件丢失&#xff0c;那么360删掉的文件怎么恢复&#xff1f;下面&#xff0c;让我们一起来看看如何恢复文件…

三维点云拟合平面推导及源代码C++

1、背景介绍 实际中,很多人工构造物是由平面结构构造而成,如下图所示,为一典型的由多个平面组成的人工构筑物。因此,根据离散点拟合成平面,获取拟合平面方程,是点云数据处理中非常常见的数据处理操作。 2、平面拟合参数推导 基于若离散点,估算平面方程过程如下: 3、程序…

电子设计教学新篇章:SmartEDA引领学校教学升级风潮

在数字化时代的浪潮中&#xff0c;电子设计教学领域正迎来一场革命性的变革。SmartEDA&#xff0c;作为电子设计课程的新宠&#xff0c;以其高效、智能的特性&#xff0c;正成为学校教学升级的重要推手。它不仅极大地提升了电子设计的效率&#xff0c;还为学生们带来了更为深入…

ChatGPT-4o提示词的九大酷炫用法,你知道几个?

ChatGPT-4o提示词的九大酷炫用法&#xff0c;你知道几个&#xff1f;&#x1f680; 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典…

xstream运用,JAVA对象转xml,xml转JAVA对象

目录 xstream 优点&#xff1a; 缺点&#xff1a; XStream的应用场景 用到的依赖 代码实现 xml标签对应的实体类 Header Package Request Response TradeInfo 工具类 XmlUtils 执行结果 xstream XStream是一个Java类库&#xff0c;主要用于将对象序列化为XML&#xf…

IPv4 和 IPv6 是什么意思?它们之间的区别都有哪些?

什么是 IPv4 和 IPv6 什么是 IPv4 和 IPv6 呢&#xff1f;下面我们就来了解一下。 IPv4 就是互联网协议第 4 版&#xff0c;是目前广泛使用的网络协议版本。它由互联网工程任务组&#xff08;IETF&#xff09;在 1981 年开发完成。IPv4 使用 32 位地址&#xff0c;允许大约 4…

推荐系统三十六式学习笔记:原理篇.近邻推荐07|人以群分,你是什么人就看到什么世界

目录 协同过滤基于用户的协同过滤背后的思想原理实践1、构造矩阵2、相似度计算3、推荐计算4、一些改进 应用场景&#xff1a;总结 谈及推荐系统&#xff0c;不得不说大名鼎鼎的协同过滤。协同过滤的重点在于协同&#xff0c;所谓协同&#xff0c;也就是群体互帮互助&#xff0c…

初级软件测试快速入门

文章目录 初级软件测试-测试用例、缺陷报告的认识与使用软件测试简介测试分类模型质量模型测试模型 用例编写的八大要素用例设计方法缺陷 初级软件测试-测试用例、缺陷报告的认识与使用 软件测试简介 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 主流技能 …

《数学学习与研究》杂志是什么级别?知网收录吗?评职认可吗?

《数学学习与研究》杂志是什么级别&#xff1f;知网收录吗&#xff1f;评职认可吗&#xff1f; 《数学学习与研究》是由东北师范大学主管&#xff0c;吉林省数学会与东北师范大学出版社联合主办的省级优秀数学类期刊杂志。该杂志为半月刊&#xff0c;国际标准刊号为 ISSN1007-…

图解通用网络IO底层原理、Socket、epoll、用户态内核态······

LInux 操作系统中断 什么是系统中断 这个没啥可说的&#xff0c;大家都知道&#xff1b; CPU 在执行任务途中接收到中断请求&#xff0c;需要保存现场后去处理中断请求&#xff01;保存现场称为中断处理程序&#xff01;处理中断请求也就是唤醒对应的任务进程来持有CPU进行需要…

《大宅门》特别活动走进李良济,开启探寻中医药文化之旅!

《大宅门》话剧将于6月14-16日在苏州湾大剧院上演&#xff0c;为了让大家了解到中医药知识&#xff0c;6月2日&#xff0c;李良济携手苏州湾大剧院举办《大宅门》特别活动“探寻中医药文化之旅”&#xff01; 6月2日下午&#xff0c;大家一起走进李良济&#xff0c;深度了解传统…

小白必学!场外期权的交易模式

场外期权的交易模式 随着金融市场的深化与创新&#xff0c;场外期权交易作为一种灵活多样的金融衍生品交易方式&#xff0c;正逐渐成为投资者关注的焦点。场外期权&#xff0c;顾名思义&#xff0c;是在非交易所市场进行的期权交易&#xff0c;与交易所期权有着显著的区别。那…

Promed Bioscience—高纯度胶原蛋白

Promed Bioscience——高纯度胶原蛋白供应商 专于研发&#xff0c;忠于质量&#xff0c;创新驱动 AXXORA 作为Enzo life sciences公司的子公司&#xff0c;是欧美最大的生命科学研究信息、服务、销售电子一站式服务平台之一&#xff0c;AXXORA精选欧洲四十多家优秀的生命科学研…

Mac 使用Docker安装Elasticsearch、Kibana 、ik分词器、head

安装ElasticSearch 通过docker安装es docker pull elasticsearch:7.8.1 在本地创建elasticsearch.yml文件 mkdir /Users/ky/Documents/learn/es/elasticsearch.yml 编辑yml文件内容 http: host: 0.0.0.0 xpack.security.enabled: false xpack.security.enrollment.enabled: t…

JAVA-LeetCode 热题-第24题:两两交换链表中的节点

思路&#xff1a; 定义三个指针&#xff0c;其中一个临时指针&#xff0c;进行交换两个节点的值&#xff0c;重新给临时指针赋值&#xff0c;移动链表 class Solution {public ListNode swapPairs(ListNode head) {ListNode pre new ListNode(0,head);ListNode temp pre;wh…