首页 > 代码库 > 简述Linux进程间通信之命名管道FIFO
简述Linux进程间通信之命名管道FIFO
上文聊到管道(pipe),可以使有亲缘关系的进程间进行通信.
对于没有亲缘关系的进程如何通信?本文来聊一聊命名管道FIFO.
一、概念
命名管道FIFO,提供一个路径名与之关联,以文件形式存储于文件系统中.
一个进程以r方式打开,另一个程序以w方式打开,即可在两个进程之间建立管道.
通过以fifo文件作为媒介,可以使任意两个进程通过该文件进行通信.
命名管道(fifo)特性与管道(pipe)类似,不必赘述.
下面我们看FIFO如何进行进程间通信,首先来介绍一下所用到的函数:
二、函数原型
#include <sys/types.h> #include <sys/stat.h> int mknod(const char *path,mode_t mod,dev_t dev); int mkfifo(const char *path,mode_t mode);
函数mknod参数:
path:为创建的命名管道的全路径名:
mod:为创建的命名管道的模式,指明其存取权限;
dev:为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到.
函数mkfifo前两个参数的含义和mknod相同.
这两个函数调用成功都返回0,失败都返回-1.
下面我来看一组实例,以server与client为例,server为接受端,client为发送端.
三、通信实例
server端:
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int main(){ umask(0); //将umask设置为0 //创建管道文件,“S_IFIFO|0666”指明创建一个命名管道且存取权限为0666 if(mkfifo("./fifo",S_IFIFO|0666)==-1){ perror("mkfifo"); return 1; } //以只读方式打开管道文件 int fd = open("./fifo",O_RDONLY); if(fd == -1){ perror("open"); return 2; } char buff[1024] = {0}; int i = 0; //接受消息 while(1){ ssize_t s = read(fd,buff,sizeof(buff)-1); buff[s] = 0; printf("server receive#%s\n",buff); } close(fd); return 0; }
client端:
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int main(){ int fd = open("./fifo",O_WRONLY); if(fd == -1){ perror("open"); return 2; } char buff[1024] = {0}; int i = 0; for(i=0; i<5; ++i){ printf("client send#"); fflush(stdout); ssize_t s = read(0,buff,sizeof(buff)-1); buff[s-1] = 0; write(fd,buff,sizeof(buff)); } close(fd); return 0; }
(代码貌似有些小问题,待修复...)
四、额外说明
对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;
对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;
程序不能以O_RDWR模式打开FIFO文件进行读写操作,这样做的后果并未明确定义,如果一个管道以读/写方式打开,进程就会从这个管道读回它自己的输出.
五、对比管道(pipe)与命名管道(fifo)
管道(pipe)用于具有血缘关系的的进程间通信,而命名管道(fifo)可以用于任意两个进程之间通信.
简述Linux进程间通信之命名管道FIFO