进程间的通信方式——pipe(管道)

from:https://blog.csdn.net/skyroben/article/details/71513385

1.进程间通信

   每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。
  • 1
  • 2

这里写图片描述

不同进程间的通信本质:进程之间可以看到一份公共资源

而提供这份资源的形式或者提供者不同,造成了通信方式不同,而 pipe就是提供这份公共资源的形式的一种。

2.匿名管道

2.1管道的创建

   管道是由调用pipe函数来创建
  • 1
  • 2
#include <unistd.h>
int pipe (int fd[2]);//返回:成功返回0,出错返回-1     
  • 1
  • 2
  • 3
 fd参数返回两个文件描述符,fd[0]指向管道的读端,fd[1]指向管道的写端。fd[1]的输出是fd[0]的输入。
  • 1
  • 2

2.2管道如何实现进程间的通信

(1)父进程创建管道,得到两个⽂件描述符指向管道的两端

(2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。

(3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管道写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。 
这里写图片描述

2.3如和用代码实现管道通信

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <string.h>  
  4. #include <errno.h>  
  5. int main()  
  6. {  
  7.     int fd[2];  
  8.     int ret = pipe(fd);  
  9.     if (ret == -1)  
  10.     {  
  11.         perror(”pipe error\n”);  
  12.         return 1;  
  13.     }  
  14.     pid_t id = fork();  
  15.     if (id == 0)  
  16.     {//child  
  17.         int i = 0;  
  18.         close(fd[0]);  
  19.         char *child = “I am  child!”;  
  20.         while (i<5)  
  21.         {  
  22.             write(fd[1], child, strlen(child) + 1);  
  23.             sleep(2);  
  24.             i++;  
  25.         }  
  26.     }  
  27.     else if (id>0)  
  28.     {//father  
  29.         close(fd[1]);  
  30.         char msg[100];  
  31.         int j = 0;  
  32.         while (j<5)  
  33.         {  
  34.             memset(msg,’\0’,sizeof(msg));  
  35.             ssize_t s = read(fd[0], msg, sizeof(msg));  
  36.             if (s>0)  
  37.             {  
  38.                 msg[s - 1] = ’\0’;  
  39.             }  
  40.             printf(”%s\n”, msg);  
  41.             j++;  
  42.         }  
  43.     }  
  44.     else  
  45.     {//error  
  46.         perror(”fork error\n”);  
  47.         return 2;  
  48.     }  
  49.     return  0;  
  50. }  

运行结果:

每隔2秒打印一次I am child!        并且打印了五次。
  • 1
  • 2

这里写图片描述

2.4管道读取数据的四种的情况

(1)读端不读,写端一直写 
这里写图片描述
(2)写端不写,但是读端一直读 
这里写图片描述

(3)读端一直读,且fd[0]保持打开,而写端写了一部分数据不写了,并且关闭fd[1]。 
这里写图片描述

如果一个管道读端一直在读数据,而管道写端的引⽤计数⼤于0决定管道是否会堵塞,引用计数大于0,只读不写会导致管道堵塞。

(4)读端读了一部分数据,不读了且关闭fd[0],写端一直在写且f[1]还保持打开状态。

这里写图片描述

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <unistd.h>  
  3. #include <string.h>  
  4. #include <errno.h>  
  5. int main()  
  6. {  
  7.     int fd[2];  
  8.     int ret = pipe(fd);  
  9.     if (ret == -1)  
  10.     {  
  11.         perror(”pipe error\n”);  
  12.         return 1;  
  13.     }  
  14.     pid_t id = fork();  
  15.     if (id == 0)  
  16.     {//child  
  17.         int i = 0;  
  18.         close(fd[0]);  
  19.         char *child = “I am  child!”;  
  20.         while (i<10)  
  21.         {  
  22.             write(fd[1], child, strlen(child) + 1);  
  23.             sleep(2);  
  24.             i++;  
  25.         }  
  26.     }  
  27.     else if (id>0)  
  28.     {//father  
  29.         close(fd[1]);  
  30.         char msg[100];  
  31.         int status = 0;  
  32.         int j = 0;  
  33.         while (j<5)  
  34.         {  
  35.             memset(msg, ’\0’sizeof(msg));  
  36.             ssize_t s = read(fd[0], msg, sizeof(msg));  
  37.             if (s>0)  
  38.             {  
  39.                 msg[s - 1] = ’\0’;  
  40.             }  
  41.             printf(”%s  %d\n”, msg, j);  
  42.             j++;  
  43.         }  
  44.         //写方还在继续,而读方已经关闭它的读端  
  45.         close(fd[0]);  
  46.         pid_t ret = waitpid(id, &status, 0);  
  47.         printf(”exitsingle(%d),exit(%d)\n”, status & 0xff, (status >> 8) & 0xff);  
  48.         //低八位存放该子进程退出时是否收到信号  
  49.         //此低八位子进程正常退出时,退出码是多少  
  50.     }  
  51.     else  
  52.     {//error  
  53.         perror(”fork error\n”);  
  54.         return 2;  
  55.     }  
  56.     return  0;  
  57. }  

运行结果:

这里写图片描述

使用kill -l 查看13号信号,可以知道13号信号代表SIGPIPE。

总结: 
如果一个管道的写端一直在写,而读端的引⽤计数是否⼤于0决定管道是否会堵塞,引用计数大于0,只写不读再次调用write会导致管道堵塞; 
如果一个管道的读端一直在读,而写端的引⽤计数是否⼤于0决定管道是否会堵塞,引用计数大于0,只读不写再次调用read会导致管道堵塞; 
而当他们的引用计数等于0时,只写不读会导致写端的进程收到一个SIGPIPE信号,导致进程终止,只写不读会导致read返回0,就像读到⽂件末尾⼀样。

2.5管道特点

1.管道只允许具有血缘关系的进程间通信,如父子进程间的通信。2.管道只允许单向通信。3.管道内部保证同步机制,从而保证访问数据的一致性。4.面向字节流5.管道随进程,进程在管道在,进程消失管道对应的端口也关闭,两个进程都消失管道也消失。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.6管道容量大小

测试管道容量大小只需要将写端一直写,读端不读且不关闭fd[0],即可。 
测试代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main()
{int fd[2];int ret = pipe(fd);if (ret == -1){perror("pipe error\n");return 1;}pid_t id = fork();if (id == 0){//childint i = 0;close(fd[0]);char *child = "I am  child!";while (i++){write(fd[1], child, strlen(child) + 1);printf("pipe capacity: %d\n", i*(strlen(child) + 1));}close(fd[1]);}else if (id>0){//fatherclose(fd[1]);waitpid(id, NULL, 0);}else{//errorperror("fork error\n");return 2;}return  0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

可以看到写到65520之后管道堵塞了,而65520即为64K大小即为管道的容量。 
这里写图片描述

进程间通信方式———信号量(Semaphore) 
http://blog.csdn.net/skyroben/article/details/72513985

进程间通信方式———消息队列 
http://blog.csdn.net/skyroben/article/details/72520501

进程间通信方式——共享内存 
http://blog.csdn.net/skyroben/article/details/72625028

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/skyroben/article/details/71513385

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

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

相关文章

highcharts 显示网格

2019独角兽企业重金招聘Python工程师标准>>> xAxis: { gridLineColor: #197F07, gridLineWidth: 1 }, yAxis: { gridLineColor: #197F07, gridLineWidth: 2 }, 转载于:https://my.oschina.net/LingBlog/blog/697885

Cheat—— 给Linux初学者和管理员一个终极命令行备忘单

编译自&#xff1a;http://www.tecmint.com/cheat-command-line-cheat-sheet-for-linux-users/作者&#xff1a; Avishek Kumar原创&#xff1a;LCTT https://linux.cn/article-3760-1.html译者&#xff1a; su-kaiyao原文稍有改动 当你不确定你所运行的命令&#xff0c;尤其是…

云数据库·ApsaraDB 产品6月刊

【重点关注】RDS发布新规格 RDS于5月下旬发布新产品规格&#xff0c;新规格对齐ECS配置:1.连接数大幅提升 互联网型的应用特点是发展快速&#xff0c;在云上应用层会基于VM进行横向扩展&#xff0c;对数据库的要求除了资…

Qt Console Application 与 Qt GUI Application互转

在桌面开发中&#xff0c;总的来说&#xff0c;包含两种类型的应用程序&#xff1a;无界面的Console程序和有界面的GUI程序。Qt也不例外&#xff0c;包含Qt Console Application和Qt GUI Application。一、Qt Console Application在VS2015中创建一个Qt Console Application&…

Create Volume 操作(Part I) - 每天5分钟玩转 OpenStack(50)

2019独角兽企业重金招聘Python工程师标准>>> 前面已经学习了 Cinder 的架构和相关组件&#xff0c;从本节我们开始详细分析 Cinder 的各种操作&#xff0c;首先讨论 Cinder 如何创建 volume。 Create 操作流程如下&#xff1a; 客户&#xff08;可以是 OpenStack 最…

【VMCloud云平台】拥抱Docker(六)关于DockerFile(1)

之前我们说过通过Docker pull来下载Images创建容器&#xff0c;这一次我们来聊下如何通过DockerFile创建Images再创建容器&#xff0c;Dockerfile也是Docker中的重点&#xff0c;使用DockerFile能够更加便捷轻量的存储标准化环境&#xff0c;也是环境管理的重要手段&#xff0c…

Windows系统编程之进程间通信

Windows系统编程之进程间通信作者&#xff1a;北极星2003来源&#xff1a;看雪论坛&#xff08;www.pediy.com&#xff09;Windows 的IPC&#xff08;进程间通信&#xff09;机制主要是异步管道和命名管道。&#xff08;至于其他的IPC方式&#xff0c;例如内存映射、邮槽等这里…

20分钟快速了解Redis

Redis可以说是目前最火爆的NoSQL数据库&#xff01; 过去几年&#xff0c;Memcached很盛行&#xff0c;现在有很多公司已将Memcached替换成了Redis。当然&#xff0c;很多人替换并不清楚为什么&#xff0c;只是感觉不想让主流抛弃&#xff0c;这也充分反映了目前Redis的强势。 …

进程通信例子

from&#xff1a;https://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.beginoutputreadline(vvs.80).aspx?cs-save-lang1&cs-langcsharp#code-snippet-4备注可同步或异步读取 StandardOutput 流。Read、ReadLine 和 ReadToEnd 等方法对进程的输出流执行…

IDEA15 下运行Scala遇到问题以及解决办法

为了让Scala运行起来还是很麻烦&#xff0c;为了大家方便&#xff0c;还是记录下来&#xff1a; 1、首先我下载的是IDEA的社区版本&#xff0c;版本号为15. 2、下载安装scala插件&#xff1a; 2.1 进入设置菜单。 2.2 点击安装JetBrains plugin 2.3 输入scala查询插件&#xff…

使用try-with-resources替代try finally释放资源

2019独角兽企业重金招聘Python工程师标准>>> 1、旧社会 Java里&#xff0c;对于文件操作IO流、数据库连接等开销非常昂贵的资源&#xff0c;用完之后必须及时通过close方法将其关闭&#xff0c;否则资源会一直处于打开状态&#xff0c;直至程序停止&#xff0c;增加…

平板电脑离寿终正寝还有多远?

近期有评论称&#xff0c;因为大尺寸智能手机越来越普及&#xff0c;小尺寸平板正遭受着越来越严重的冲击&#xff0c;在这样的背景下&#xff0c;平板厂商也纷纷转攻超大尺寸平板市场&#xff0c;以此避开大尺寸智能手机的竞争&#xff0c;只是。这样的策略转变是否能扭转平板…

Swift 与 JSON 数据

转载自&#xff1a; http://www.cnblogs.com/theswiftworld/p/4660177.html 我们大家平时在开发 App 的时候&#xff0c;相信接触最多的就是 JSON 数据了。只要你的 App 有读取网络数据的功能&#xff0c;你就免不了要与 JSON 打交道。比如你做一个新闻 App&#xff0c;你要读取…

TeamViewer - 最好用强大的免费跨平台远程桌面控制软件 (支持电脑和手机)

from&#xff1a;很早以前 LYcHEE 就提到过&#xff0c;家中的潮人爷爷奶奶每天摆弄着电脑&#xff0c;看看新闻发发邮件&#xff0c;安享晚年生活。只是意料之中的&#xff0c;电脑上莫名出现各种问题&#xff1f;不翼而飞的图标&#xff1f;照片又忘记怎么导出了&#xff1f;…

【设计模式】7、桥接模式

桥接模式就是对一个类的方法进行抽象化&#xff0c;吧不相关的因素提取出来&#xff0c;发展出第二个类 1 package com.shejimoshi.structural.Bridge;2 3 4 /**5 * 功能&#xff1a;桥接模式使用6 * 意图&#xff1a;将抽象部分与它的实现部分分离&#xff0c;使他们都…

TeamViewer免费版和付费版有什么不同

提到远程控制软件 TeamViewer无疑是目前业内知名度比较高的一款&#xff0c;所以说到远程控制软件可能大部分人首先想到的就是TeamViewer。在使用功能上&#xff0c;它支持远程桌面控制、文件传输、远程计算机锁定、视频会话、主控方和被控方身份互换&#xff0c;远程管理无人执…

【代码笔记】iOS-翻书效果的实现

代码&#xff1a; RootViewController.m #import "RootViewController.h"interface RootViewController ()endimplementation RootViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {self [super initWithNibName:…

Halcon—Tuple中符号的含义

2014年08月08日 21:20:30阅读数&#xff1a;5429实例一&#xff08;3d_coordinates.hdev&#xff09;&#xff1a;for I : 1 to NumImages by 1read_image (Image, calib/calib-3d-coord-I$02d)——C:\Program Files\MVTec\HALCON-10.0\images\的calib文件夹中开头是calib-3d-c…

Halcon学习笔记(三)---数据类型

Halcon学习笔记&#xff08;三&#xff09;---数据类型halcon只能在单独行进行注释&#xff0c;不能在语句后面进行注释。1、tuple(元组&#xff0c;重数)赋值符号“&#xff1a;”tuple算子&#xff1a;&#xff08;1&#xff09;变量定义与加减乘除运算代码如下&#xff1a;*…

论文笔记之:RATM: RECURRENT ATTENTIVE TRACKING MODEL

RATM: RECURRENT ATTENTIVE TRACKING MODEL ICLR 2016 本文主要内容是 结合 RNN 和 attention model 用来做目标跟踪。 其中模型的组成主要是&#xff1a; 1. an attention model 主要用来从输入图像中提取 patch&#xff1b; 2. RNN 用来预测 attention 参数&#xff0c;即&am…