linux进程间通信之命名管道fifo用法及注意事项

普通管道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. #define MYFIFO "myfifo"
  10. #define BUFF_SIZE 1024
  11. int main(int argc,char* argv[]) {
  12.     char buff[BUFF_SIZE];
  13.     int real_write;
  14.     int fd;
  15.     if(argc<=1){
  16.         printf("Usage: ./fifo_write_test string\n");
  17.         exit(1);
  18.     }
  19.     sscanf(argv[1],"%s",buff);
  20. // 测试FIFO是否存在,若不存在,mkfifo一个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. //调用open以只写方式打开FIFO,返回文件描述符fd    
  28.     if((fd=open(MYFIFO,O_WRONLY))==-1){
  29.         printf("Open fifo error!\n");
  30.         exit(1);
  31.     }
  32. //调用write将buff写到文件描述符fd指向的FIFO中
  33.     if ((real_write=write(fd,buff,BUFF_SIZE))>0) {
  34.         printf("Write into pipe: '%s'.\n",buff);
  35.         exit(1);
  36.     }
  37.     
  38.     close(fd);
  39.     exit(0);
  40. }
复制代码



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


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


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

posted on 2018-06-25 21:36  wudymand  阅读(2136)  评论(0编辑  收藏  举报

导航