前面学习过(匿名)管道(见前面博客),匿名管道只能用于有亲缘关系的各个进程之间,为了解决这个限制,UNIX系统进而引入了FIFO,也称为有名管道(named pipe)。shell
FIFO(first in, first out),是一个半双工数据流,也即一个半双工管道。不一样于匿名管道的是,每一个FIFO有一个路径名(或文件名)与之关联,也即FIFO的名字。有了名字,无亲缘关系的进程间就能够经过管道进行数据传输了。app
建立FIFO的方式:函数
使用shell命令 mkfifo建立一个有名管道学习
[infor@s123 FIFO]$ mkfifo npipe [infor@s123 FIFO]$ ls -l prw-r--r-- 1 infor app 0 Nov 13 11:32 npipe
上面咱们建立了一个有名管道npipe,咱们能够看到有名管道实际上是一个文件,文件类型是“p”,管道类型。
咱们在开启两个终端,分别为A和B。在A终端下将数据写入管道,在B终端下将数据读出来。spa
[infor@s123 FIFO]$ ping 10.4.123.124 >> npipe #会阻塞在这里,等待另外一个进程读
在终端A下将ping的结果写入管道npipe,这里会一直阻塞到另外一个进程将数据所有读出或停止读出。code
[infor@s123 FIFO]$ cat npipe PING 10.4.123.124 (10.4.123.124) 56(84) bytes of data. 64 bytes from 10.4.123.124: icmp_seq=0 ttl=128 time=0.838 ms 64 bytes from 10.4.123.124: icmp_seq=1 ttl=128 time=0.835 ms 64 bytes from 10.4.123.124: icmp_seq=2 ttl=128 time=0.843 ms 64 bytes from 10.4.123.124: icmp_seq=3 ttl=128 time=0.834 ms
在终端B下读取npipe。
使用C库函数mkfifo建立一个有名管道进程
#include <sys/types.h> #include <sys/stat.h> /* 函数说明:依参数pathname创建特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限 返回值:若成功则返回0,不然返回-1,错误缘由存于errno中 */ int mkfifo(const char *pathname, mode_t mode);
对于建立方式,mkfifo隐含指定O_CREAT|O_EXCL,也即mkfifo建立一个新的FIFO,若是该FIFO已经存在,则会返回EEXIST错误。ip
对于参数mode可有以下选项:
S_IRUSR:当前用户可读
S_IWUSR:当前用户可写
S_IRGRP:组成员可读
S_IWGRP:组成员可写
S_IROTH:其余用户可读
S_IWOTH:其余用户可写博客
下面经过例子看下如何使用。it
假若有这样一个案例。进程A执行完将执行结果写入管道,等待进程B将该结果读出。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #define FIFO_NAME ("/tmp/fifo.1") // 设定FIFO的名字 #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定建立FIFO的权限 /*建立一个FIFO,等待另外一个进程读取*/ int main() { int writefd; char status[] = "success"; size_t n = 0; // 建立FIFO if(mkfifo(FIFO_NAME, FILE_MODE) < 0) { if(EEXIST == errno) { printf("FIFO:%s已经存在,不能从新建立\r\n", FIFO_NAME); } else { perror("建立FIFO错误"); exit(1); } } // 打开FIFO writefd = open(FIFO_NAME, O_WRONLY, 0); if(-1 == writefd) { perror("打开FIFO失败"); unlink(FIFO_NAME); exit(1); } // 写入执行状态 n = write(writefd, status, strlen(status)); if(n != strlen(status)) { perror("写入FIFO失败"); unlink(FIFO_NAME); exit(1); } if(-1 == close(writefd)) { perror("关闭FIFO失败"); unlink(FIFO_NAME); exit(1); } return 0; }
编译并执行:
[infor@s123 FIFO]$ gcc -o wnpipe wnpipe.c [infor@s123 FIFO]$ ./wnpipe #阻塞在这里等待另一个进程读取FIFO
这里咱们看一下/tmp/fifo.1 是否生成:
[infor@s123 tmp]$ ls -l /tmp/fifo.1 prw-r--r-- 1 infor app 0 Nov 13 12:58 /tmp/fifo.1
咱们看到FIFO文件已经生成。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #define FIFO_NAME ("/tmp/fifo.1") // 设定FIFO的名字 #define MAXLINE (1024) /*读取FIFO内容*/ int main() { int readfd; char status[MAXLINE]; size_t n = 0; // 打开FIFO readfd = open(FIFO_NAME, O_RDONLY, 0); if(-1 == readfd) { perror("打开FIFO失败"); unlink(FIFO_NAME); exit(1); } // 读取FIFO n = read(readfd, status, MAXLINE); if(-1 == n) { perror("读取FIFO失败"); exit(1); } printf("管道内容:%s\r\n", status); // 关闭FIFO if(-1 == close(readfd)) { perror("关闭FIFO失败"); unlink(FIFO_NAME); exit(1); } // 删除FIFO unlink(FIFO_NAME); return 0; }
编译并执行:
[infor@s123 FIFO]$ gcc -o rnpipe rnpipe.c [infor@s123 FIFO]$ ./rnpipe 管道内容:success
这里咱们再看一下/tmp/fifo.1 是否还存在:
[infor@s123 tmp]$ ls -l /tmp/fifo.1 ls: /tmp/fifo.1: No such file or directory
能够看到文件已被删除了。
2011-11-13 任洪彩 qdurenhongcai@163.com
转载请注明出处。