进程间的通讯方式_管道(有名管道)

来源:互联网 发布:中国校园足球现状知乎 编辑:程序博客网 时间:2024/05/21 21:44
当从一个进程连接数据流到另一个进程时,我们使用属于管道(pipe)。我们通常是把一个进程的输出通过管道连接到另一个进程的输入。
(管道是在内存上开辟出一块空间,不被任何其他进程所占用的)管道包括全双工通讯和半双工通讯。

管道原理:

管道操作:
      有名管道:应用于任意两个进程之间数据的单向传递
      创建:命令方式(mkfifo)、函数方式(mkfifo)
      打开:open
      写数据:write
      读数据:read
      关闭:close
      有名管道是在文件目录树中有一个文件标识(管道文件),实际不占用磁盘空间,数据缓存在内存中。
      与通过 pipe 调用创建管道不同,FIFO 是以命名文件的形式存在, 而不是打开的文件描述符,所以在对它进行读写操作之前必须先打开它。FIFO 也用 open 和 close 函数打开和关闭,这与我们的对文件的操作一样,但它多了一些其他功能,对 FIFO 来说, 传递给 open 调用的是 FIFO 的路径名, 而不是一个正常的文件。 
     
      阻塞运行函数:函数调用后并不会立即返回,需要等待某些条件的发生才会返回,open 操作管道文件时,阻塞运行的函数。
      如果一个进程以只写方式打开一个管道文件,open 会阻塞运行,直到有一个进程以读的方式打开这个管道文件,open 才会返回,进程才会接着执行。
      如果一个进程以只读方式打开一个管道文件,open 会阻塞运行,直到有一个进程以写的方式打开这个管道文件,open 才会返回,进程才会接着执行。
      read 函数也会阻塞运行, 直到写端写入数据或所有写端关闭时返回。
      read 读取数据并且会将内存上的已读数据清空。

练习:A进程负责循环接受用户输入的数据,以“end”为结束标志,B进程负责统计用户输入的单词的个数,显示到界面上。
      首先利用 mkfifo FIFO 命令创建管道文件“FIFO”,如图所示:
      A进程代码如下:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <assert.h>#include <fcntl.h>int main(){int fd = open("FIFO", O_WRONLY);assert(fd != -1);if (fd == -1){exit(0);}char buffer[128] = {0};printf("Please input:");fgets(buffer, 128, stdin);while (strncmp(buffer,"end",3) != 0){write(fd, buffer, strlen(buffer)-1);memset(buffer, 0, 128);fgets(buffer, 128, stdin);}close(fd);return 0;}
      B进程代码如下:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <assert.h>#include <fcntl.h>int main(){int fd = open("FIFO", O_RDONLY);assert(fd != -1);if (fd == -1){exit(0);}char buffer[128] = {0};int count = 0;while (read(fd,buffer,127) > 0){printf("%s\n", buffer);count++;}printf("count: %d\n",count);close(fd);return 0;}
测试运行结果如图所示: