管道是单向的、先进先出的,它把一个进程的输出和还有一个进程的输入连接在一起。一个进程(写进程)在管道的尾部写入数据,还有一个进程(读进程)从管道的头部读出数据。数据被一个进程读出后,将被从管道中删除,其它读进程将不能再读到这些数据。管道提供了简单的流控制机制,进程试图读空管道时,进程将堵塞。相同,管道已经满时,进程再试图向管道写入数据。进程将堵塞。

管道包含无名管道和有名管道两种。无名管道仅仅能用于父进程和子进程间的通信,而有名管道能够用于同一系统中的随意两个进程间的通信。

  • 无名管道由pipe()函数创建
  1. int pipe(int pipefd[2]);
  2. #当一个无名管道建立时,它会创建两个文件描写叙述符:
  3. #pipefd[0] 用于读管道,
  4. #pipefd[1] 用于写管道。
  5. #pipe()函数创建的管道默认是打开的.

演示样例程序:

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <stdlib.h>
  9. int main(int argc, char** argv){
  10. int pipe_fd[2];
  11. pid_t pid;
  12. if( pipe(pipe_fd) == -1){
  13. fprintf(stderr, "%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  14. exit(-1);
  15. }
  16. if(( pid = fork()) == 0){
  17. close(pipe_fd[0]);
  18. write(pipe_fd[1],"hello ",6);
  19. write(pipe_fd[1]," world",7);
  20. printf("Child process write done!\n");
  21. close(pipe_fd[1]);
  22. exit(0);
  23. }else if( pid > 0){
  24. close(pipe_fd[1]);
  25. sleep(3);
  26. char buf[20];
  27. memset(buf,0,20);
  28. read(pipe_fd[0],buf,20);
  29. printf("Parent process in : %s\n",buf);
  30. close(pipe_fd[0]);
  31. }
  32. return 0;
  33. }
  34. #对于无名管道的读、写、关闭操作,与普通文件的操作是一样的。
  • 有名管道的创建有两种方式

    1、使用shell命令,格式例如以下:
  1. mkfifo [OPTION] FILENAME

2、在程序中调用mkfifo()函数

  1. int mkfifo(const char *pathname, mode_t mode);

mkfifo()函数会根据參数 pathname 建立特殊的FIFO文件(有名管道),该文件必须不存在,而參数mode为该文件的权限。

mkfifo()建立的FIFO文件其它进程都能够用读写一般的文件方式存取。mkfifo()建立的FIFO文件默认是关闭的,当使用open()函数打开文件时须要注意和普通文件的差别:

1、不能以O_RDWR模式打开FIFO文件进行读写操作。这样做的行为是没有定义的。由于管道是单向的,假设须要在程序之间双向传递数据,使用一对有名管道就可以。

2、对标志位的 O_NONBLOCK 标志的使用方法。

O_RDONLY、O_WRONLY和O_NONBLOCK标志共同拥有四种合法的组合方式:

flags=O_RDONLY:open将会调用堵塞。除非有另外一个进程以写的方式打开同一个FIFO。否则一直等待。

flags=O_WRONLY:open将会调用堵塞。除非有另外一个进程以读的方式打开同一个FIFO。否则一直等待。

flags=O_RDONLY|O_NONBLOCK:假设此时没有其它进程以写的方式打开FIFO,此时open也会成功返回,此时FIFO被读打开,而不会返回错误。

flags=O_WRONLY|O_NONBLOCK:马上返回。假设此时没有其它进程以读的方式打开,open会失败打开。此时FIFO没有被打开。返回-1。

演示样例程序:

  1. #fifo_read.c
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #define FIFO_FILE "/tmp/myfifo"
  10. int main(int argc, char *argv[]){
  11. int fd ;
  12. char buf[128];
  13. if(access(FIFO_FILE,F_OK) != 0){
  14. if(mkfifo(FIFO_FILE, 0644) == -1){
  15. fprintf(stderr,"%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  16. return -1;
  17. }
  18. }
  19. if( (fd = open(FIFO_FILE,O_RDONLY | O_NONBLOCK)) == -1){
  20. fprintf(stderr,"%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  21. return -1;
  22. }
  23. while(1){
  24. memset(buf,0,sizeof(buf));
  25. if(read(fd,buf,sizeof(buf)) == -1){
  26. fprintf(stderr,"%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  27. return -1;
  28. }
  29. sleep(1);
  30. printf("read is %s !\n",buf);
  31. }
  32. unlink(FIFO_FILE);
  33. return 0;
  34. }
  1. # fifo_write.c
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. #define FIFO_FILE "/tmp/myfifo"
  10. int main(int argc, char *argv[]){
  11. int fd ;
  12. if( (fd = open(FIFO_FILE,O_WRONLY | O_NONBLOCK)) == -1){
  13. fprintf(stderr,"%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  14. return -1;
  15. }
  16. if (write(fd,"Hello world",12) == -1){
  17. fprintf(stderr,"%s\t%s\t%d\n",strerror(errno), __FILE__,__LINE__);
  18. return -1;
  19. }
  20. return 0;
  21. }

Linux 进程通信之管道的更多相关文章

  1. Linux进程通信----匿名管道

    Linux进程通信中最为简单的方式是匿名管道 匿名管道的创建需要用到pipe函数,pipe函数参数为一个数组表示的文件描述字.这个数组有两个文件描 述字,第一个是用于读数据的文件描述符第二个是用于写数 ...

  2. linux进程通信之管道

    1.介绍: 1)同一主机: unix进程通信方式:无名管道,有名管道,信号 system v方式:信号量,消息队列,共享内存 2)网络通信:Socket,RPC 2.管道: 无名管道(PIPE):使用 ...

  3. linux 进程通信之 管道和FIFO

    进程间通信:IPC概念 IPC:Interprocess Communication,通过内核提供的缓冲区进行数据交换的机制. IPC通信的方式: pipe:管道(最简单) fifo:有名管道 mma ...

  4. Linux学习笔记(13)-进程通信|命名管道

    匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...

  5. linux 进程通信 管道

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

  6. Linux下进程通信之管道

    每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把 ...

  7. Linux进程通信之匿名管道

    进程间的通信方式 进程间的通信方式包括,管道.共享内存.信号.信号量.消息队列.套接字. 进程间通信的目的 进程间通信的主要目的是:数据传输.数据共享.事件通知.资源共享.进程控制等. 进程间通信之管 ...

  8. linux下的进程通信之管道与FIFO

    概念:管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条.管道的一端连接一个进程的输出.这个进程会向管道中放入信息.管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息. 优点:不需 ...

  9. 进程通信类型 管道是Linux支持的最初Unix IPC形式之一

    管道 Linux环境进程间通信(一) https://www.ibm.com/developerworks/cn/linux/l-ipc/part1/index.html 管道及有名管道 郑彦兴200 ...

随机推荐

  1. vue11 vue实例方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. FPGA设计中的电源管理(转载)

    过去,FPGA设计者主要关心时序和面积使用率问题.但随着FPGA不断取代ASSP和ASIC器件,设计者们现正期望能够开发低功耗设计,在设计流程早期就能对功耗进行正确估算,以及管理和对与FPGA相关的各 ...

  3. Docker之基础篇

    小白学Docker之基础篇   系列文章: 小白学Docker之基础篇 小白学Docker之Compose 小白学Docker之Swarm PS: 以下是个人作为新手小白学习docker的笔记总结 1 ...

  4. Network Stack

    Network Stack 目录 1 Overview 2 Code Layout 3 Anatomy of a Network Request (focused on HTTP) 3.1 URLRe ...

  5. df---显示磁盘分区使用空间

    df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 语法 df(选项)(参数) 选项 -a或--all:包含全部的文 ...

  6. 洛谷 P3692 [PUB1]夏幻的考试

    P3692 [PUB1]夏幻的考试 题目背景 夏之幻是软件工程系的大神,学校把举办考试的任务交给她了. 题目描述 某大学软工专业要举办一场笔试,学生们要在机读答题卡上填写答案来进行答题.学校把机读卡识 ...

  7. POJ 1325 &amp;&amp; ZOJ 1364--Machine Schedule【二分图 &amp;&amp; 最小点覆盖数】

    Machine Schedule Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13071   Accepted: 5575 ...

  8. 为root账户更名

    为root账户更名 处于安全考虑许多管理员想把root更名,具体方法如下: 1.先以root登陆系统 2.用vi 编辑/etc/passwd文件,将第一行的第一个root修改为你想要的账户名,然后保存 ...

  9. Fragment-Transaction 源码分析

    概述 这篇文章的简要分析了Activity中的Transaction和add,replace等操作以及backstack的工作原理. 分析transaction源码的原因是因为我在写一个测试代码的时候 ...

  10. GridView1.DataKeys[e.RowIndex].Value 是什么含义?

    https://zhidao.baidu.com/question/88518619.html举个例子来说吧 你将一个student表绑定到grid上 这个表里有一些字段 包括id 姓名 学号 等等等 ...