进程间通信之FIFO有名管道

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liu_zhen_kai/article/details/82110095

无名管道的概念

无名管道是临时的,在完成通信后自动消失,因为文件描述符只在某个进程中可见,所以无名管道只能用于具有亲缘关系的进程之间的通信。
有名管道FIFO是一种特殊的文件机制,依赖于文件系统,可以实现任意进程之间的通信。

用shell创建有名管道

[liu@bogon 07]$ cat pipe.c > fifo 

发生阻塞等待
启动另一终端:
[liu@bogon 07]$ cat < fifo 
/*
    read from parents then print

    int pipe(int pipefd [2]);

    pipe() creates a pipe, a unidirectional data channel that can be used for interprocess communication.  The array pipefd is used to return two file
           descriptors referring to the ends of the pipe.  pipefd[0] refers to the read end of the pipe.  pipefd[1] refers to the  write  end  of  the  pipe.
                  Data  written  to  the  write  end of the pipe is buffered by the kernel until it is read from the read end of the pipe.

    on sucess returns 0, else returns -1

*/

有名管道和普通文件一样有路径,文件权限和其他等属性,但是有名管道没有在磁盘中存储任何信息,文件大小始终为0,它的储存信息始终在内存当中,拥有的磁盘路径只是一个接口,为了实现进程间通信,当两个进程都退出时,命名管道的生命周期也就结束了。


有名管道的管理以及特性
1.创建有名管道
函数mkfifo

extern int mkfifo (__const char *__path, __mode_t __mode)
参数分析:
    __path:创建的有名管道名字以及路径,默认为当前目录
    __mode:创建的管道的读写权限
返回值:
    成功返回0,失败返回-1.

mkfifo会根据参数建立有名管道文件,文件不存在则被创建,新的管道文件权限为mode的值,mkfifo建立的文件一般都以读取方式存取,再使用open打开管道文件,可以实现进程之间的通信。

2,读写有名管道
有名管道的实质依然是一块内存空间,open打开管道接口之后,需要用write和read来进行读写操作才能实现进程之间的通信。
另外,操作有名管道的阻塞位置为open位置,而不是无名管道的读写位置。

<1>如果一个进程以读/写方式打开了FIFO,进程将会阻塞等待另外一个进程打开该FIFO的写/读,直到打开成功后进程才能继续运行,当然一个进程可以同时打开读写操作,但是这样的做法无意义,而且可能发生未知错误。

<2>两个进程如果完成打开读/写FIFO,将阻塞读操作按以下方式执行:

  • 如果管道中无数据,则默认读操作阻塞等待
  • 如果管道中数据小于期望读取的数据,则读取管道中所有的数据返回

<3>两个进程已经完成读/写FIFO,将以阻塞写操作按以下方式执行:

  • 如果管道中没有空间,则默认读操作阻塞
  • 如果管道中有空间,但是小于欲写入数据量,则写满后将阻塞
  • 如果管道中空间大于欲写入数据量,将写入后直接返回

<4>两个进程完成了读/写FIFO,其中一个进程中途退出

  • 未退出的一端如果为写操作,将返回SIGPIPE信号
  • 未退出的一端如果为读操作,读操作将不再阻塞,直接返回0

非亲缘关系进程之间通信实例

写端:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <sys/ipc.h>
  5 #include <sys/stat.h>
  6 #include <string.h>
  7 #include <fcntl.h>
  8 #include <string.h>
  9 #include <errno.h>
 10 
 11 int main()
 12 {
 13     int fifo_fd = -1;
 14     char buf[128] = {0};
 15 
 16         if(mkfifo("./test.fifo", 0664) == -1)
 17 
 18             if(errno == EEXIST)
 19             {
 20 
 21             }
 22             else
 23             {
 24                 perror("mkfifo"),
 25                     exit(0);
 26             }
 27 
 28 
 29     printf("please input >");
 30     fgets(buf, 127, stdin);
 31     fifo_fd = open("./test.fifo", O_WRONLY);
 32     write(fifo_fd, buf, strlen(buf) + 1);
 33     
 34     return 0;
 35 }   

读端:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <sys/ipc.h>
  5 #include <sys/stat.h>
  6 #include <string.h>
  7 #include <fcntl.h>
  8 #include <string.h>
  9 #include <errno.h>
 10 
 11 int main()
 12 {
 13     int fifo_fd = -1;
 14     char buf[128] = {0};
 15 
 16         if(mkfifo("./test.fifo", 0664) == -1)
 17 
 18             if(errno == EEXIST)
 19             {
 20 
 21             }
 22             else
 23             {
 24                 perror("mkfifo"),
 25                     exit(0);
 26             }
 27 
 28 
 29     printf("recive : ");
 30     fifo_fd = open("./test.fifo", O_RDONLY);
 31     read(fifo_fd, buf, 128);
 32     printf("%s\n", buf);
 33     return 0;
 34 }

运行结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/liu_zhen_kai/article/details/82110095