15.5 FIFO
(1)概念
1.FIFO也称为命名管道,通过FIFO不相关的进程也能实现通信
(2) 创建FIFO
[1]接口
int mkfifo(const char *path, mode_t mode);
说明:
1.创建FIFO后会生成一个文件,FIFO的路径名会存在于文件系统中。
2.mode参数与open中的mode参数相同(见3.3节)
3.新FIFO用户和组的所有权规则与4.6节所述相同。
int mkfifoat(int fd, const char *path, mode_t mode)
说明:
1.mkfifoat和mkfifo相似
2.如果path是绝对路径,fd将被忽略
3.如果path是相对路径,并且fd参数是一个打开目录的有效文件描述符,路径名和目录有关。
4.如果path是相对路径,并且fd参数有一个特殊值AT_FDCWD,则路径名以当前目录开始,mkfifoat和mkfifo类似
(3 )当open一个FIFO文件时,非阻塞标志(O_NONBLOCK)会产生下列影响:
1)FIFO文件没有指定O_NONBLOCK标志
1.以O_RDONLY方式open FIFO文件时,调用进程会被阻塞,直到其他某个进程以写方式打开(open)FIFO文件为止(O_WRONLY 或者 O_RDWR)。
2.以O_WRONLY方式open FIFO文件时,open要阻塞到某个其他进程为读而打开它为止。
3.以O_RDWR方式open FIFO文件时,不会被阻塞。
2)FIFO文件指定了O_NONBLOCK标志
1.以O_RDONLY或O_WRONLY或O_RDWR方式open FIFO文件时,会立即返回。
2.以O_RDONLY或者O_RDWR方式open FIFO文件时,如果FIFO文件还没有以写方式打开时,open返回-1,error被置为0
3.以O_WRONLY方式open FIFO文件时,如果FIFO文件还没有以读方式打开时,open返回-1,error被置为ENXIO
(4)说明
1.使用mkfifo或者mkfifoat创建FIFO时,要用open函数来打开,使用close关闭。
2.类似于管道,write一个尚无进程为读而打开的FIFO时,将会产生SIGPIPE信号。
3.若某个FIFO的最后一个写进程关闭了该FIFO,那么为该FIFO的读进程将产生一个文件结束标志。
4.一个给定的FIFO有多个写进程非常常见,PIPE_BUF说明了可被原子的写道FIFO的最大数据量。
(5)FIFO的两种用途
[1] shell命令使用FIFO将数据从一条管道传送到另一条是,无需创建中间临时文件。
[2] 客户进程-服务端进程应用程序中,FIFO用作汇聚点,在客户进程和服务进程二者之间传递数据。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/wait.h>
#include <sys/acct.h>
#include <errno.h>
#include <sys/times.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
// 测试FIFO文件的open特性
#define MFIFO_NONBLOCK
#define FIFOFILE_PATH "/workteam/zhouhouping/nfs/testCode/chapter15/FIFO/mfifo"
void delete_file(char *path)
{
char buf[100]={0};
sprintf(buf, "rm -rf %s", path);
system(buf);
}
int file_exists(const char *path)
{
return !access(path,F_OK);
}
int main()
{
int ret;
if (file_exists(FIFOFILE_PATH))
delete_file(FIFOFILE_PATH);
assert(0 == mkfifo(FIFOFILE_PATH, 0700)); // 0700:新建文件有可读可写可执行
printf("ok1\n");
#if defined(MFIFO_NONBLOCK)
//ret = open(FIFOFILE_PATH, O_RDONLY | O_NONBLOCK); // 不会被阻塞, ERROR: open=-1, errno= 0
//ret = open(FIFOFILE_PATH, O_WRONLY | O_NONBLOCK); // 不会被阻塞, ERROR: open=-1, errno= ENXIO
ret = open(FIFOFILE_PATH, O_RDWR | O_NONBLOCK); // 不会被阻塞, ERROR: open=-1, errno= 0
if (ret = -1) {
printf("ERROR: open=%d, errno= %d\n", ret, errno);
if (errno == ENXIO)
printf("errno == ENXIO\n");
}
#else
//open(FIFOFILE_PATH, O_RDONLY); // 阻塞
open(FIFOFILE_PATH, O_WRONLY); // 阻塞
//open(FIFOFILE_PATH, O_RDWR); // 不会被阻塞
#endif
printf("ok2\n");
return 0;
}