一、函数原型
#include <sys/stat.h>
#include <sys/types.h>
int mkfifo( const char * filename, mode_t mode );
功能:创建有名管道
FIFO
参数:
filename:指定新创建FIFO的文件名称(包含路径名)
二、有名管道特性
当调用open()来打开 FIFO文件时,O_NONBLOCK会有影响
mode:指定FIFO的读写权限,和 open 函数的mode参数一样。新创建FIFO的用户ID和组ID规则域open 函数相同
返回值:函数如果成功返回0,出 错返回–1,并更改errno的值
- 没有指定O_NONBLOCK时,有名管道需要用open函数打开以后使用,如果以只读方式打开,会阻塞到有写方式打开管道,同样以只写方式打开会阻塞到以读方式打开。
- 如果指定了O_NONBLOCK,则只读open会立即返回。但是,如果没有进程已经为读而打开一个 FIFO ,那么只写open将会收到一个SIGPIPE信号,终止进程
- 有名管道FIFO可以用在没有亲缘关系的进程中
三、注意事项
- fifo文件并不存在磁盘上,磁盘上只存其属性和链接等。
- 读FIFO时,如果没有写入数据,read要阻塞到有某个其他进程将数据写入。
- 写 FIFO时,如果如果FIFO有足够空间,write函数会返回写入的字节数;如果空间不够,write函数会阻塞,直到有空间供其写入为止
- 在对管道读的过程中,如果写端关闭,则读一个写端已关闭的 FIFO 时,read 返回。如果将读端关闭, 则写一个读端关闭的管道,则产生SIGPIPE信号,程序退出。如果忽略该信号或者捕捉该信号并处理程序返回,则write返回-1,errno设置为EPIPE
- write和read会同样使管道文件偏移量改变。但无法使用lseek对FIFO操作
- 当写入管道的数据小于PIPE_BUF时,write操作是一个原子操作。
- 说明:在服务器端打开公共FIFO的时候,如果仅以只读打开,则当所有的客户端都退出时,服务器端会读取到文件结束符。这个问题的解决办法是服务器以读写打开公共FIFO
例程:
fifor.c文件:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#define error_exit(_errmsg_) error(EXIT_FAILURE, errno, _errmsg_)
#define FIFO_PATH "/tmp/fifo926"
#define BUFF_SIZE 1024
int main()
{
int fd;
char *buff = NULL;
if (-1 == mkfifo(FIFO_PATH, 0666)) {
if (EEXIST != errno)
error_exit("mkfifo");
}
puts("before open ... ");
if (-1 == (fd = open(FIFO_PATH, O_RDONLY)))
error_exit("open");
puts("after open ... ");
buff = (char *)malloc(BUFF_SIZE);
if (-1 == read(fd, buff, BUFF_SIZE))
error_exit("write");
puts(buff);
close(fd);
free(buff);
return 0;
}
fifow.c文件:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <error.h>
#include <errno.h>
#define error_exit(_errmsg_)
error(EXIT_FAILURE, errno, _errmsg_)
#define FIFO_PATH
"/tmp/fifo926"
#define BUFF_SIZE
1024
int main()
{
int fd;
if (-1 == mkfifo(FIFO_PATH, 0666)) {
if (EEXIST != errno)
error_exit("mkfifo");
}
puts("before open ... ");
if (-1 == (fd = open(FIFO_PATH, O_WRONLY)))
error_exit("open");
puts("after open ... ");
if (-1 == write(fd, "helloworld", 11))
error_exit("write");
close(fd);
return 0;
}