普通管道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'.