首页 > 代码库 > 简述Linux进程间通信之命名管道FIFO

简述Linux进程间通信之命名管道FIFO

  上文聊到管道(pipe),可以使有亲缘关系的进程间进行通信.

  对于没有亲缘关系的进程如何通信?本文来聊一聊命名管道FIFO.

一、概念

  命名管道FIFO,提供一个路径名与之关联,以文件形式存储于文件系统中.

  一个进程以r方式打开,另一个程序以w方式打开,即可在两个进程之间建立管道.

  通过以fifo文件作为媒介,可以使任意两个进程通过该文件进行通信.

  命名管道(fifo)特性与管道(pipe)类似,不必赘述.

  下面我们看FIFO如何进行进程间通信,首先来介绍一下所用到的函数:

二、函数原型

#include <sys/types.h>
#include <sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode); 

  函数mknod参数:

  path:为创建的命名管道的全路径名:

  mod:为创建的命名管道的模式,指明其存取权限;

  dev:为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到.

  函数mkfifo前两个参数的含义和mknod相同.

  这两个函数调用成功都返回0,失败都返回-1.

  下面我来看一组实例,以server与client为例,server为接受端,client为发送端.

三、通信实例

  server端:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
    umask(0);   //将umask设置为0
    //创建管道文件,“S_IFIFO|0666”指明创建一个命名管道且存取权限为0666
    if(mkfifo("./fifo",S_IFIFO|0666)==-1){
        perror("mkfifo");
        return 1;
    }
    //以只读方式打开管道文件
    int fd = open("./fifo",O_RDONLY);
    if(fd == -1){
        perror("open");
        return 2;
    }
    char buff[1024] = {0};
    int i = 0;
    //接受消息
    while(1){
        ssize_t s = read(fd,buff,sizeof(buff)-1);
        buff[s] = 0;
        printf("server receive#%s\n",buff);
    }
    close(fd);
    return 0;
}

  client端:

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int main(){
    int fd = open("./fifo",O_WRONLY);
    if(fd == -1){
        perror("open");
        return 2;
    }
    char buff[1024] = {0};
    int i = 0;
    for(i=0; i<5; ++i){
        printf("client send#");
        fflush(stdout);
        ssize_t s = read(0,buff,sizeof(buff)-1);
        buff[s-1] = 0;
        write(fd,buff,sizeof(buff));
    }
    close(fd);
    return 0;
}

  (代码貌似有些小问题,待修复...)

四、额外说明

  对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;

  对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;

  程序不能以O_RDWR模式打开FIFO文件进行读写操作,这样做的后果并未明确定义,如果一个管道以读/写方式打开,进程就会从这个管道读回它自己的输出.

五、对比管道(pipe)与命名管道(fifo)

  管道(pipe)用于具有血缘关系的的进程间通信,而命名管道(fifo)可以用于任意两个进程之间通信.

简述Linux进程间通信之命名管道FIFO