普通管道pipe只能在相关进程之间使用,例如父子进程。两个完全独立不相关的进程可以使用fifo,也就是命名管道。

命名管道fifo头文件及原型:

#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);


函数返回值成功返回0,失败返回-1。

命名管道fifo可以使不相关的独立进程之间互相通信,通过路径名识别,文件系统中可见。命名管道建立后,进程间可像普通文件一样操作,可使用open(),write(),read()等函数。为了读取操作而打开的命名管道可在open时设置O_RDONLY;为写入操作而打开的命名管道可在open时设置O_WRONLY。

命名管道fifo遵循先入先出原则,读时从头部读取数据,写时从尾部写入数据。

命名管道fifo与普通文件操作之间的区别是不支持如lseek()等文件定位,命名管道fifo默认打开是阻塞的。如果需要非阻塞,需要在open时设置O_NONBLOCK.

对于读取进程,如果是阻塞方式打开,如果当前命名管道fifo中没有数据,则进程会一直阻塞,直到有数据写入。如果是非阻塞打开,无论有无数据,读取进程会立即返回,没有数据时返回0.
对于写入进程,如果是阻塞方式打开,进程会一直阻塞直到数据可以被写入。如果非阻塞打开,当没有读打开时,写入进程会打开失败,返回-1.
写入进程fifo_write_test.c代码如下:


1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <string.h>
4. #include <sys/types.h>
5. #include <sys/stat.h>
6. #include <errno.h>
7. #include <unistd.h>
8. #include <fcntl.h>
9. 
10. #define MYFIFO "myfifo"
11. #define BUFF_SIZE 1024
12. 
13. int main(int argc,char* argv[]) {
14.     char buff[BUFF_SIZE];
15.     int real_write;
16.     int fd;
17. 
18.     if(argc<=1){
19.         printf("Usage: ./fifo_write_test string\n");
20.         exit(1);
21.     }
22. 
23.     sscanf(argv[1],"%s",buff);
24. 
25. // 测试FIFO是否存在,若不存在,mkfifo一个FIFO
26.     if(access(MYFIFO,F_OK)==-1){
27.         if((mkfifo(MYFIFO,0666)<0)&&(EEXIST!=errno)){
28.             printf("Can NOT create fifo file!\n");
29.             exit(1);
30.         }
31.     }
32. 
33. //调用open以只写方式打开FIFO,返回文件描述符fd    
34.     if((fd=open(MYFIFO,O_WRONLY))==-1){
35.         printf("Open fifo error!\n");
36.         exit(1);
37.     }
38. 
39. //调用write将buff写到文件描述符fd指向的FIFO中
40.     if ((real_write=write(fd,buff,BUFF_SIZE))>0) {
41.         printf("Write into pipe: '%s'.\n",buff);
42.         exit(1);
43.     }
44.     
45.     close(fd);
46.     exit(0);
47. 
48. }


读取进程fifo_read_test.c代码如下:

1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <string.h>
4. #include <sys/types.h>
5. #include <sys/stat.h>
6. #include <errno.h>
7. #include <unistd.h>
8. #include <fcntl.h>
9. 
10. #define MYFIFO "myfifo"
11. #define BUFF_SIZE 1024
12. 
13. int main() {
14.     char buff[BUFF_SIZE];
15.     int real_read;
16.     int fd;
17. 
18. //access确定文件或文件夹的访问权限。即,检查某个文件的存取方式
19. //如果指定的存取方式有效,则函数返回0,否则函数返回-1
20. //若不存在FIFO,则创建一个
21.     if(access(MYFIFO,F_OK)==-1){
22.         if((mkfifo(MYFIFO,0666)<0)&&(EEXIST!=errno)){
23.             printf("Can NOT create fifo file!\n");
24.             exit(1);
25.         }
26.     }
27. 
28. //以只读方式打开FIFO,返回文件描述符fd    
29.     if((fd=open(MYFIFO,O_RDONLY))==-1){
30.         printf("Open fifo error!\n");
31.         exit(1);
32.     }
33. 
34. // 调用read将fd指向的FIFO的内容,读到buff中,并打印
35.     while(1){
36.         memset(buff,0,BUFF_SIZE);
37.         if ((real_read=read(fd,buff,BUFF_SIZE))>0) {
38.             printf("Read from pipe: '%s'.\n",buff);
39.         }
40.     }
41.     
42.     close(fd);
43.     exit(0);
44. }

两份代码分别编译执行后如下:
写入进程执行:./fifo_write_test abc
                       Write into pipe: 'abc'.


读取进程输出:Read from pipe: 'abc'.