进程间通信IPC-命名管道FIFO
FIFO又被称为命名管道,未命名的管道只能在两个相关的进程之间使用,而这两个相关的进程还要有一个共同创建了它们的祖先进程,但是FIFO,不相关的进程之间也能交换数据。
FIFO是一种文件类型。通过stat结构的st_mode成员的编码可以知道文件是否是FIFO类型,在linux下查看自己创建的FIFO文件:
创建FIFO类似于创建文件,也存在于文件系统之中。定义如下:
1 #include <sys/stat.h> 2 int mkfifo(const char* path, mode_t mode); 3 int mkfifoat(int fd, const char* path, mode_t mode);
两个函数返回值:若成功返回0,失败则返回-1,使用方法参照open函数。
编写自己的后台FIFO读取程序:
1 #include <stdio.h> 2 #include <sys/stat.h> 3 #include <errno.h> 4 #include <fcntl.h> 5 6 int main(int argc, char* argv[]) 7 { 8 int fd; 9 int nRead; 10 char szBuff[128]; 11 const char* szPath = "/tmp/fifo"; //临时目录的一个fifo,可以在程序里创建也可以在shell里创建 12 13 fd = open(szPath, O_RDONLY, 0); 14 if (-1 == fd) 15 { 16 printf("open fifo error\n"); 17 goto exit; 18 } 19 20 while(1) 21 { 22 if((nRead = read(fd, szBuff, sizeof(szBuff))) == -1) 23 { 24 if (errno == EAGAIN) 25 printf("no data\n"); 26 } 27 if (szBuff[0] == 'Q') 28 break; 29 szBuff[nRead] = '\0'; 30 printf("data:%s\n", szBuff); 31 sleep(1); 32 } 33 exit: 34 return 0; 35 }
使用cc fifo.c 编译成功后得到a.out,在命令提示符下输入:
1 $ ./a.out & 2 [1] 4768 //这里是进程ID回现
将a.out程序作为一个后台进程运行。
在终端创建fifo(也可以在程序内创建):
1 $ mkfifo /tmp/fifo 2 $ ls -ln /tmp/fifo 3 prw-rw-r-- 1 1001 1001 0 10月 9 22:04 /tmp/fifo
我们使用linux自带的tee回现程序和a.out进行通信。
1 $ tee /tmp/fifo //标准输出到fifo 2 hello fifo! // 这里是我输入的 3 hello fifo! // 这里是tee回现功能 4 data:hello fifo! // 这里是a.out回应 5 6 q 7 q 8 data:q // 这里是a.out回应 9 10 Q 11 Q 12 hello fifo? 13 hello fifo? 14 [1]+ 完成 ./a.out
至此a.out与tee两个进程之间的通信已经完成了。