Linux程式間通訊②:有名管道FIFO

一隻老風鈴發表於2020-10-11

常規的匿名管道通過pipe建立一片記憶體緩衝區,並對外提供兩個檔案描述符,用於只讀或者只寫操作。但其使用範圍很小,只能用於父、子程式間的通訊。因此Linux還提供有名管道的支援。

管道的本質是一片可以讀寫的緩衝區域,Linux將其描述為檔案(UNIX思想:一切IO皆是檔案) 對於有名管道,其主要特點是:

  • 存在於檔案系統中,包含檔名,管道檔案被組織成樹狀結構
  • 兩個程式之間無需有聯絡,可以通過管道進行通訊
  • 對有名管道的操作和檔案操作類似,支援讀,寫

 

【有名管道的建立】

mkfifo(const char* filename,mode)   //建立指定名字的管道檔案  並指明mode
int main()
{
    if(mkfifo("./fifo_test",0777)<0)
    {
        cout<<"create fifo error"<<endl;
        return -1;
    }
    cout<<" create success"<<endl;
    return 0;
}

執行結果:

可以看到,通過mkfifo成功建立了fifo_test的管道檔案,但其與磁碟上的普通檔案不同,只是對緩衝區的一個抽象描述。

 

基於這個有名管道,fifo_test  可以通過其它程式來實現讀寫操作。

【寫端】

首先通過access判斷管道檔案是否存在,如果不在,那麼mkfifo建立一個管道檔案。

然後,不斷的接受stdin輸入,並通過write寫入到管道檔案

當輸入的字元為'q'時,結束程式

#include "stdio.h"
#include "stdlib.h"
#include<iostream>
#include <unistd.h>
#include <sys/stat.h>
#include "sys/types.h"
#include "fcntl.h"
using  namespace std;
int main(int argc, char *argv[])
{
    int i, ret, fd;
    char p_flag = 0;

    /* 建立有名管道 */
    if (access("./myfifo", 0) < 0) {   //先判斷有名管道檔案是否存在,不存在需要先建立
        ret = mkfifo("./myfifo", 0777);  //許可權
        if (ret < 0) {
           cout<<"create fifo error"<<endl;
            return -1;
        }
        cout<<"create fifo success"<<endl;
    }

    fd=open("./myfifo", O_WRONLY);//只寫入方式
    if (fd < 0) {
        cout<<"open fifo error"<<endl;
        return -1;
    }
    cout<<"open fifo success"<<endl;

   char c;
   while(cin>>c)
   {
	    write(fd,&c,sizeof(c));
       if(c=='q')
           break;
      
   }
  
    return 0;
}

 

【讀端】

首先通過access判斷管道檔案是否存在,如果不在,那麼mkfifo建立一個管道檔案。

然後,不斷的通過read從管道讀取字元,並顯示。

當接收的字元為'q'時,結束程式

 

int main(int argc, char *argv[])
{
    int i, ret, fd;
    char p_flag = 0;
    if (access("./myfifo", 0) < 0) {   //先判斷有名管道檔案是否存在,不存在需要先建立
        ret = mkfifo("./myfifo", 0777);  //許可權
        if (ret < 0) {
           cout<<"create fifo error"<<endl;
            return -1;
        }
        cout<<"create fifo success"<<endl;
    }
    fd=open("./myfifo", O_RDONLY);//只讀方式
    if (fd < 0) {
        cout<<"open fifo error"<<endl;
        return -1;
    }
    cout<<"open fifo success"<<endl;
   char c;
   while(1)
   {
       read(fd,&c, sizeof(c));
       cout<<c<<endl;//列印輸出
       if(c=='q')
           break;
   }

    return 0;
}

 

 

g++ write.cpp -o write
g++ read.cpp -o read

 

 

分別啟動寫入端程式,讀取端程式,執行結果:

 

由此可見,有名管道 named pipe 其主要特點是:

  1. 提供了一種多程式之間通訊的方式,本質是多程式讀取同一片記憶體緩衝區。
  2. 相較於匿名管道,由於採取了檔名標識,可以在不是父子程式關係之間通訊。
  3. 對管道的讀寫操作與其它檔案操作類似,Linux通過VFS進行抽象統一描述。(一切IO皆是檔案思想)

 

 

相關文章