1. 有名管道函数接口
无名管道仅仅适用于亲缘进程之间的通信,如果要在任意进程间通信,且保证写入具有原子性,那么可以使用FIFO
功能 | 描述 | 其它 |
---|---|---|
头文件 | sys/types.h sys/stat.h | / |
原型 | int mkfifo(const char *pathname, mode_t mode); | / |
参数 | pathname:fifo的名字 | mode:文件权限 |
返回值 | 成功返回0 | 失败返回-1 |
2. 有名管道FIFO特性
- 有名字,存储在文件系统中
- 任何具有相应权限的进程都可以使用open()来获取FIFO的文件描述符
- 跟普通文件一样:使用统一的read()/write()来读写
- 和普通文件不同:不能使用lseek()来定位,原因同PIPE
- 具有写入原子性,支持多进程进行同时写操作而不会互相踩踏
- First In First Out,最先被写入FIFO的数据,最先被读出来
3. 有名管道FIFO代码示例
FIFO的写端
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#define FIFO "./fifo4test" //有名管道fifo的名字
int main(int argc, char**argv){
if(access(FIFO, F_OK)){ //测试文件是否存在
mkfifo(FIFO, 0644);
}
int fifo = open(FIFO, O_WRONLY); //以只写的方式打开
char *msg = "Hello, I am writing...";
int count = 0; //统计写的次数
while(1){
int n = write(fifo, msg, strlen(msg)); //将数据写入到fifo
printf("Writed %d times, %d bytes have been sended. \n", ++count, n);
sleep(2); //每隔2秒写一次
}
return 0;
}
FIFO的读端
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define FIFO "./fifo4test" //有名管道fifo的名字
int main(int argc, char**argv){
if(access(FIFO, F_OK)){ //判断文件是否存在
mkfifo(FIFO, 0644);
}
int fifo = open(FIFO, O_RDONLY); //只读方式打开管道
int count = 0; //计数,读取的次数
char msg[200];
while(1){
bzero(msg, 200);
read(fifo, msg, 200); //从管道中读取数据
printf("From FIFO read %d times, buffer: %s\n", ++count, msg);
sleep(20); //每隔20秒读一次
}
return 0;
}
可以看到有个有名管道fifo4test被创建了
需要指出的是:
- 如果只运行写端不运行读端或者只运行读端不运行写端,open函数会被阻塞,因为管道文件(包括PIPE、FIFO、SOCKET)不可以只有在读端或者写端的情况下被打开
- 如果只打开写端,而不进行数据写入的话,读端会被阻塞,直到写端写入数据,因为默认情况下是阻塞方式读取数据的,可以使用fcntl()函数使得FIFO变成非阻塞模式