2.3 利用 Linux 系统调用实现进程间通信(李鹏)
1. 管道
一、实验要求
使用管道实现进程间通信。
二、设计方案介绍
a. 程序结构
创建两个进程,一个进程向管道写数据,另一个进程从管道读数据。以这种方式实现进
程间通信。
b.管道概念
管道是 UNIX 进程间通信(InterProcess Communication,IPC)最古老的形式。从实现
机制讲,管道是和内存中的一个文件索引节点相关联的两个文件描述符。我们可以利用管道
在进程之间传送数据。当引用管道的最后一个进程关闭了这些文件描述符之后,管道也就消
失了。管道有如下限制:
1).它们是半双工的,数据只能在一个方向上流动。
2).管道只能在具有共同祖先的进程之间使用。
三、程序所用系统函数(系统调用)的介绍
管道是调用 pipe 函数建立的:
#include <unistd.h>
int pipe(int fildes[2]);
参数 fildes 返回两个文件描述符:fildes[0]代表读管道描述符,fildes[1]代表写管道描述
符。fildes[1]的输入就是 fildes[0]的输出。
通常管道由一个进程创建,然后这个进程调用 fork 系统调用,产生一个子进程,这样父
子进程之间就都拥有了读写这个管道的文件描述符,由于管道是半双工的,这样就需要读管
道的进程关闭写端(fildes[1]),写管道的进程关闭读端(fildes[0])。
下图表示了管道在进程间通信中的用法:
如上图所示,父进程和子进程之间通过管道进行单向通信。父进程拥有写管道描述符,
子进程拥有读管道描述符。父进程可以通过 write 系统调用向管道内写数据,而子进程可以
通过 read 系统调用从管道内读数据。这样就实现了进程间通讯。在 UNIX/Linux 中的 shell
解释程序中的管道命令就可以通过这种管道实现。
此外,标准 I/O 函数库中还提供了两个经过包装的与管道有关的函数 popen 和 pclose。
#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
int pclose(FILE *fp);
这两个函数将管道的创建和关闭操作包装起来,简化用户对管道的使用。函数 popen 首
先调用 pipe 创建一条管道,并调用 fork 函数产生一个子进程,然后子进程调用 exec 执行
cmdstring,并且返回一个标准 I/O 文件指针。如果参数 type 是“r”,则返回的文件指针指向
父进程
fd[1]
管道
子进程
fd[0]