1. 程式人生 > >簡述Linux進程間通信之命名管道FIFO

簡述Linux進程間通信之命名管道FIFO

error pri include mask urn mode linux 系統 sizeof

  上文聊到管道(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