Unix系统早期一般使用多进程解决问题。有时多个进程之间需要交互数据,而进程和进程之间不能直接交互数据,因此引入了进程间通信(IPC)。
IPC主要包括以下方式:
1. 文件I/O
2. 信号
3. 管道
4. 共享内存
5. 消息队列
6. 信号量集
7. 网络socket
其中,共享内存、消息队列和信号量集都遵循XSI IPC,因此三者编程中有很多共性。管道目前很少使用。
管道(FIFO或PIPE)之所以目前很少使用,是由于他有两点局限性:
1. 一般为半双工(即同一时刻,数据只能在一个方向流动,也就是不能同时传输)。
2. 管道只能在两个有共同祖先进程的两个进程之间使用。
管道分为有名管道(有文件名)和无名管道(没有名字)。有名管道就是自己创建管道文件,然后进行交互。无名管道就是系统帮我们创建管道文件,利用系统的管道文件进行交互。
也就是有名管道适用于所有的进程的通信,无名管道只适用于fork()创建的父子进程之间的通信。
管道也是一个文件,后缀名为.pipe。我们可以使用mkfifo命令或mkfifio()函数创建一个有名管道文件:
$ mkfifo a.pipe
mkfifo函数定义如下:
#include<sys/types.h> #include<sys/stat.h> int mkfifo(const char * pathname,mode_t mode); /* 示例 */ mkfifo("a.pipe", 0777); /* 成功返回0,失败返回-1,错误代码存在errno中 */
读管道示例代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <fcntl.h> 5 6 int main() 7 { 8 int fd = open("a.pipe", O_RDONLY); 9 if (fd == -1) 10 perror("open"), exit(-1); 11 12 int x = 0; 13 while (1) { 14 int res = read(fd, &x, sizeof(x)); 15 if (res == -1) { 16 perror("read"); 17 close(fd); 18 exit(-1); 19 } 20 if (!res) break; 21 printf("x=%d\n", x); 22 } 23 close(fd); 24 25 return 0; 26 }