Linux下處理序間通訊:具名管道-mkfifo

來源:互聯網
上載者:User

轉自:http://cpp.ezbty.org/content/science_doc/linux%E4%B8%8B%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1%EF%BC%9A%E5%91%BD%E5%90%8D%E7%AE%A1%E9%81%93_mkfifo

摘要:處理序間通訊的方法有很多,FIFO與管道是最古老,也是相對來說更簡單的一個通訊機制。FIFO相對管道有一個優勢,就是FIFO只要求兩個進程是同一主機的,而不要求進程之間存在親緣關係。FIFO是存在於檔案系統的檔案,可以使用諸如open、read、write等函數來操作。本文總結網路和APUE關於FIFO討論,同時參考了Linux系統手冊。

目錄 [隱藏]
  1. FIFO(具名管道)概述
  2. mkfifo函數
  3. 具名管道讀寫規則
    1. 從FIFO中讀取資料
    2. 從FIFO中寫入資料
  4. FIFO樣本
FIFO(具名管道)概述

FIFO是一種進程通訊機制,它突破通常管道無法進行無關進程之間的通訊的限制,使得同一主機內的所有的進程都可以通訊。FIFO是一個檔案類型,stat結構中st_mode指明一個檔案結點是不是一個FIFO,可以使用宏S_ISFIFO來測試這一點。

當一個FIFO存在於檔案系統裡時,我們只需要在想進行通訊的進程內開啟這個檔案就可以了。當然FIFO作為一個特殊的檔案,它有一些不同普通檔案特性,下面會詳細詳述它的讀寫規則,這些相對精通檔案來有一定的區別。

我們可以使用open、read、write來操作FIFO檔案,從而實現處理序間通訊的目的。在shell環境下,也可以直接使用FIFO,這時往往與重寫向有一些關聯,一般系統都提供mkfifo公用程式來建立一個FIFO檔案,這個程式實際上使用mkfifo系統調用來完成這個事。

mkfifo函數

mkfifo建立一個指定名字的FIFO,它的函數原型如下:

#include<sys/stat.h>
int mkfifo(const char* pathname, mode_t mode);
傳回值:成功,0;失敗,-1

 

參數pathname指出想要建立的FIFO路徑,參數mode指定建立的FIFO訪問模式。這個訪問會與當前進程的umask進程運算,以產生實際應用的許可權模式。

mkfifo返回-1時表示建立過程中遇到某種錯誤,此時會設定errno,使用者可以檢測errno來取得進一步資訊:

  • EACCES: 路徑所在的目錄不允許執行許可權
  • EEXIST:路徑已經存在,這時包括路徑是一個符號連結,無論它是懸空還沒有懸空。
  • ENAMETOOLONG:要麼全部的檔案名稱大於PATH_MAX,要麼是單獨的檔案名稱大於NAME_MAX。在GNU系統裡沒有這個檔案名稱長度的限制,但在其它系統裡可能存在。
  • ENOENT:目錄部分不存在,或者是一個懸空連結。
  • ENOTDIR:目錄部分不一個目錄。
  • EROFS:路徑指向一個唯讀檔案系統。

 

具名管道讀寫規則

FIFO又叫具名管道,事實上它與管道確實在下許多相似之處,下面關於規則的討論很體現這個相似。

從FIFO中讀取資料

約定:如果一個進程為了從FIFO中讀取資料而阻塞開啟了FIFO,那麼稱該進程內的讀操作為設定了阻塞標誌的讀操作。

  • 如果有進程寫開啟FIFO,且當前FIFO為空白,則對於設定了阻塞標誌的讀操作來說,將一直阻塞下去,直到有資料可以讀時才繼續執行;對於沒有設定阻塞標誌的讀操作來說,則返回0個位元組,當前errno值為EAGAIN,提醒以後再試。
  • 對於設定了阻塞標誌的讀操作來說,造成阻塞的原因有兩種:一、當前FIFO內有資料,但有其它進程在讀這些資料;二、FIFO本身為空白。
    解阻塞的原因是:FIFO中有新的資料寫入,不論寫入資料量的大小,也不論讀操作請求多少資料量,只要有資料寫入即可。
  • 讀開啟的阻塞標誌只對本進程第一個讀操作施加作用,如果本進程中有多個讀操作序列,則在第一個讀操作被喚醒並完成讀操作後,其它將要執行的讀操作將不再阻塞,即使在執行讀操作時,FIFO中沒有資料也一樣(此時,讀操作返回0)。
  • 如果沒有進程寫開啟FIFO,則設定了阻塞標誌的讀操作會阻塞。
  • 如果FIFO中有資料,則設定了阻塞標誌的讀操作不會因為FIFO中的位元組數少於請求的位元組數而阻塞,此時,讀操作會返回FIFO中現有的資料量。
從FIFO中寫入資料

約定:如果一個進程為了向FIFO中寫入資料而阻塞開啟FIFO,那麼稱該進程內的寫操作為設定了阻塞標誌的寫操作。

FIFO的長度是需要考慮的一個很重要因素。系統對任一時刻在一個FIFO中可以存在的資料長度是有限制的。它由#define PIPE_BUF定義,在標頭檔limits.h中。在Linux和許多其他類UNIX系統中,它的值通常是4096位元組,Red Hat Fedora9下是4096,但在某些系統中它可能會小到512位元組。

雖然對於只有一個FIFO寫進程和一個FIFO的讀進程而言,這個限制並不重要,但只使用一個FIFO並允許多個不同進程向一個FIFO讀進程發送請求的情況是很常見的。如果幾個不同的程式嘗試同時向FIFO寫資料,能否保證來自不同程式的資料區塊不相互交錯就非常關鍵了à也就是說,每個寫操作必須“原子化”。

設定了阻塞標誌的寫操作:

  • 當要寫入的資料量不大於PIPE_BUF時,Linux將保證寫入的原子性。如果此時管道空閑緩衝區不足以容納要寫入的位元組數,則進入睡眠,直到當緩衝區中能夠容納要寫入的位元組數時,才開始進行一次性寫操作。即寫入的資料長度小於等於PIPE_BUF時,那麼或者寫入全部位元組,或者一個位元組都不寫入,它屬於一個一次性行為,具體要看FIFO中是否有足夠的緩衝區。
  • 當要寫入的資料量大於PIPE_BUF時,Linux將不再保證寫入的原子性。FIFO緩衝區一有空閑地區,寫進程就會試圖向管道寫入資料,寫操作在寫完所有請求寫的資料後返回。

沒有設定阻塞標誌的寫操作:

  • 當要寫入的資料量不大於PIPE_BUF時,Linux將保證寫入的原子性。如果當前FIFO空閑緩衝區能夠容納請求寫入的位元組數,寫完後成功返回;如果當前FIFO空閑緩衝區不能夠容納請求寫入的位元組數,則返回EAGAIN錯誤,提醒以後再寫。
  • 當要寫入的資料量大於PIPE_BUF時,Linux將不再保證寫入的原子性。在寫滿所有FIFO空閑緩衝區後,寫操作返回。
FIFO樣本

本段給出使用FIFO一個樣本,它體現了兩個使用FIFO的典型情景。

建立FIFO

#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main()
{
        int res = mkfifo("/tmp/my_fifo", 0777);
        if(res == 0)
        {
                printf("FIFO created\n");
        }
        exit(EXIT_SUCCESS);
}

 

使用FIFO

#include<errno.h>
#include<sys/stat.h>
#include<fcntl.h>

FIFO "/tmp/my_fifo"
//本程式從一個FIFO讀資料,並把讀到的資料列印到標準輸出
//如果讀到字元“Q”,則退出
int main(int argc, char** argv)
{
        char buf_r[100];
        int fd;
        int nread;
        if((mkfifo(FIFO, O_CREAT) < 0) && (errno != EEXIST))
        {
                printf("不能建立FIFO\n");
                exit(1);
        }

        printf("準備讀取資料\n");
        fd = open(FIFO, O_RDONLY, 0);
        if(fd == -1)
        {
                perror("開啟FIFO");
                exit(1);
        }

        while(1)
        {
                if((nread = read(fd, buf_r, 100)) == -1)
                {
                        if(errno == EAGAIN) printf("沒有資料\n");
                }

                //假設取到Q的時候退出
                if(buf_r[0]=='Q') break;

                buf_r[nread]=0;
                printf("從FIFO讀取的資料為:%s\n", buf_r);
                sleep(1);
        }

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.