管道通信

匿名管道

创建匿名管道

int pipe(int pipefd[2]);
pipefd[0] : 表示读管道
pipefd[1] : 表示写管道
返回 0表示成功,非零表示创建失败。

代码事例

//匿名管道
int main()
{int fds[2];int len;char buf[100]={};if(pipe(fds)==-1) //创建管道perror("pipe"),exit(1);while(fgets(buf,100,stdin)){   len = strlen(buf);if(write(fds[1],buf,len)==-1) //把内容写进管道perror("write"),exit(1);memset(buf,0x00,sizeof(char)*100);if(read(fds[0],buf,len)==-1) //从管道里面读取内容到数组中perror("read"),exit(1);if(write(1,buf,len)==-1) //把从管道里读出的内容写到标准输出perror("write"),exit(1);}   return 0;
}

结果展示

日常运用事例
who | wc -l
这样的事例我们经常用到,用管道连接命令会令你得心应手。

图片解析

利用管道进行父子进程通信

图片解析原理

代码示例:

//父子进程通信
int main()
{char buf[1024]="change world!\n";int fds[2];if(pipe(fds)==-1)perror("pipe"),exit(1);pid_t pid = fork(); //创建匿名管道if(pid==0){close(fds[0]); //关闭管道读描述符if(write(fds[1],buf,1024)==-1) //写进管道perror("write"),exit(1);close(fds[1]); exit(1);}else{memset(buf,0x00,1024);close(fds[1]); //关闭管道写描述符if(read(fds[0],buf,1024)==-1) //从管道读内容perror("read"),exit(1);if(write(1,buf,1024)==-1)perror("write"),exit(1);close(fds[0]);exit(1);}return 0;
}            

结果

详细过程图解

管道读写规则

当没有数据可读时

  • O_NONBLOCK disable:read调用阻塞,即进程暂停执行,.一直等到有数据来到为止。
  • O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。

当管道满的时候

  • O_NONBLOCK disable: write调用阻塞,直到有进程读.走数据
  • O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
  • 如果所有管道写端对应的文件描述符被关闭,则read返回0
  • 如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE,进而可能导致write进程退出
  • 当要写.入的数据量不.大于PIPE_BUF时,linux将保证写.入的原.子性。
  • 当要写.入的数据量.大于PIPE_BUF时,linux将不再保证写.入的原.子性。

管道特点

  • 只能⽤用于具有共同祖先的进程(具有亲缘关系的进程)之间进⾏行通信;通常,一个管道由一个进程创建,然后该进程调⽤用fork,此后⽗父、⼦子进程之间就可应⽤用该管道。
  • 管道提供流式服务
  • 一般⽽而⾔言,进程退出,管道释放,所以管道的⽣生命周期随进程
  • 一般⽽而⾔言,内核会对管道操作进⾏行同步与互斥管道是半双⼯工的,数据只能向⼀一个⽅方向流动;需要双⽅方通信时,需要建⽴立起两个管道

    命名管道

    我们刚刚可以用匿名管道在父子进程之间通信,那如果是两个不想光的进程之间该如何通信呢?

创建命名管道

在命令行可以直接创建mkfifo filename

也可以在程序内部创建,相关函数
int mkfifo(const char *pathname, mode_t mode);

代码示例:

int main()
{mkfifo("my.p",0644);return 0;
}

无关进程之间通信代码示例

从标准输入读入内容进管道

#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{mkfifo("my.p",0664);int outfd = open("my.p",O_WRONLY);if(outfd==-1)perror("open my.txt"),exit(1);char buf[1024]={};int n = 0;while(fgets(buf,1024,stdin)){   write(outfd,buf,1024);memset(buf,0x00,1024);}  close(outfd);

从管道中读内容,标准输出输出

#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>int main()
{int infd = open("my.p",O_RDONLY);if(infd==-1)perror("open my.p"),exit(1);char buf[1024]={};int n = 0;while((n = read(infd,buf,1024))>0){write(1,buf,n);memset(buf,0x00,1024);}close(infd);                                                                                                         unlink("my.p"); //删除管道return 0;
}

运行结果:

这里就利用管道实现了两个无关进程之间的通信。

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

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

转载于:https://www.cnblogs.com/zhonglongbo/p/8976730.html

利用管道实现进程间通信相关推荐

  1. Linux学习之系统编程篇:利用管道进行进程间通信

    这里我们先补充一个小知识: 父子进程使用 pipe 进行通信时fork 和 pipe 先后的顺序是先 pipe,后 fork,因为父进程先创建管道,再 fork 创建子进程,这样才能是父子进程共享一块 ...

  2. [转载]使用命名管道实现进程间通信

    使用命名管道实现进程间通信 来源 : VChelp 4.5 进程间通信 在Win32下提供的进程间通信方式有以下几种: 剪贴板Clipboard:在16位时代常使用的方式,CWnd类中提供了支持. C ...

  3. 管道实现进程间通信之命名管道

    进程间通信管道篇之命名管道 文章目录 1.1命名管道 1.2命名管道的创建 1.3命名管道和匿名管道的区别 代码演示(用命名管道实现进程间通信) 2.1 通过进程间通信将客户端发送的字符串转化为命令让 ...

  4. 利用管道实现进程间同步

    进程间同步是指进程的运行有先后顺序,如A进程等待B进程执行完某个动作A进程才能继续往下运行.进程间通信的方法都可以用来同步,只是操作是否方便的一个问题.复习了UNIX高级编程,觉得POSIX的信号量是 ...

  5. python利用管道popen调用.exe进行交互

    python是典型的胶水语言,可以来做粘合复杂程序的应用,在终端上可以随意地组合他和其它程序,作为一个中间处理模块. python可以利用subprocess这个模块来产生子进程,并连接到子进程的标准 ...

  6. java 线程类 通信_Java 中利用管道实现线程间的通讯

    在Java 语言中,提供了各种各样的输入输出流(stream),使我们能够很方便的对数据进行操作,其中,管道(pipe)流是一种特殊的流,用于在不同线程(threads)间直接传送数据.一个线程发送数 ...

  7. 【Linux】管道实现进程间通信

    一. 进程间通信(IPC) 我们知道进程之间都是相互独立的,任何一个进程的全局变量在另一个进程中是看不到的,如果进程之间需要交换数据就要通过内核.进程间通信(InterProcess Communic ...

  8. 利用管道检测技术成果对城市地下空洞进行筛查分析的探讨

    近年来,由于地下管线老化.破损等原因导致城路道路产生空洞塌陷的事故频发,严重威胁公众的生命财产安全.全国各大城市的管理者都在积极努力的开展各项工作,寻找解决办法.深圳市从2019年起全面开展主要道路地 ...

  9. [原创]利用WM_COPYDATA实现进程间通信

    进程间通信的方法有多种,其中,对于少量数据可以用WM_COPYDATA方便的实现通信(如果对于大量数据的话,由于SendMessage是阻塞的,只有接收方响应了消息,SendMessage才能返回,否 ...

最新文章

  1. SHOI2008仙人掌图(tarjan+dp)
  2. 关于linux下目录树的查看TEEE命令
  3. oracle+sid+未清除,管理信息化ORACLEoracle+DBA手册.pdf
  4. C语言学习之用*打印菱形
  5. C与C++在形参的一点小区别
  6. JAVA通信编程(二)——如何读取java的properties配置文件(插播)
  7. java.lang.UnsatisfiedLinkError: D:\Program Files\apache-tomcat-9.0.30\bin
  8. 于连生性聪颖的飞鸽传书
  9. AMD: Developer Guides, Manuals ISA Documents
  10. 快捷关闭win8中的应用页面---解决方法
  11. Flask - 基础
  12. 2019ASC世界大学生超算竞赛预赛结果出炉:20校晋级,北航第一
  13. 用MyEclipse JPA创建项目(四)
  14. python读取图片转cvs_python将图片转换为csv
  15. VMware虚拟机安装Win10
  16. mysql my.cnf位置_我如何找到MySQL my.cnf位置
  17. 曾经跨过山和大海的百度AI技术汇,跨进北工大!
  18. 多智能体强化学习【Windows\Ubuntu 安装星际争霸Ⅱ】
  19. matplotlib learning-----案例:对比电影的票房收入(3)
  20. python2.7 error: Microsoft Visual C++ 9.0 is required. Get it from http://aka.ms/vcpython27

热门文章

  1. 构造函数和析构函数能否声明为虚函数?
  2. js在控件原有的事件方法中加入自己的方法
  3. [转]Listview的onItemClickListener无法响应的解决方法
  4. 我在学习技术的过程遇到的不会的单词(不断完善)
  5. 02丨基础篇:到底应该怎么理解“平均负载”?
  6. 5 CrawlSpider操作
  7. mysql兼容性高吗_MySQL与标准的兼容性
  8. AliCloudDenoise 语音增强算法:助力实时会议系统进入超清音质时代
  9. JAVA应用开发MQ实战最佳实践——Series2:消息队列RocketMQ性能测试案例
  10. 火了 2 年的服务网格究竟给微服务带来了什么?