普通管道应用的一个重大限制就是他没有名字,因此只能用于具有亲缘关系的进程之间通信,有名管道很好的克制了这个限制,FIFO不同于普通管道之处在于他提供了一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通信。
int mkfifo(const char*pathname, mode_t mode);
用来创建有名管道。
参数pathname 是管道的 路径及名字 字符串。
参数mode 是该文件的权限
值得注意的是:open()和write() 函数的阻塞和非阻塞机制,如果双方都阻塞,先运行 有名管道read.c 或者先运行 有名管道write.c都可以,先运行的会阻塞等待后运行的; 如果 有名管道read.c以非阻塞方式率先运行 ,则会一直读取管道信息,即使有名管道write.c不运行,它也会一直读取,此时什么也读取不到; 但是如果有名管道write.c以非阻塞方式率先运行,则会因为没有进程进行读取动作而报错,错误信息保存在errno中。
// 有名管道read.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define FIFO "/tmp/myfifo"
int main(int argc, char *argv[])
{
int fd;
char buf[20];
int len = 0;
if(mkfifo(FIFO, O_CREAT|O_EXCL) < 0) //如果没有会自动创建
{
if(errno == EEXIST)
{
printf("cannot create fifo, have a FIFO \n");
}
}
printf("preaing to recv . . \n");
if((fd = open(FIFO, O_RDONLY, 0766)) < 0)
// if((fd = open(FIFO, O_RDONLY|O_NONBLOCK, 0766)) < 0) //非阻塞
{
printf("open fifo error\n");
exit(1);
}
while(1)
{
memset(buf, 0, sizeof(buf));
if((len = read(fd, buf, 10)) == -1)
{
if(errno == EAGAIN)
{
printf("no data yet\n");
}
}
else
{
printf("read len = %d str = %s from FIFO, len = %d\n", strlen(buf), buf, len);
}
sleep(1);
}
return 0;
}
// 有名管道write.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define FIFO "/tmp/myfifo"
int main(int argc, char *argv[])
{
int fd;
int len = 0;
char w_buf[50];
if(argc < 2)
{
printf("please input str!\n");
exit(1);
}
// fd = open(FIFO, O_WRONLY | O_NONBLOCK,0766); //非阻塞
fd = open(FIFO, O_WRONLY,0766);
if(fd == -1)
{
if(errno == ENXIO)
{
printf("open error!,no reading process\n");
}
printf("open error\n");
exit(1);
}
strcpy(w_buf, argv[1]);
while(1)
{
if((len = write(fd, w_buf, strlen(w_buf))) == -1)
{
if(errno == EAGAIN)
{
printf("The FIFO has not been read yet.\n");
}
}
else
{
printf("write str %s to FIFO \n",w_buf);
}
sleep(1);
}
close(fd);
return 0;
}