linux程序間通訊 命名管道

2021-07-24 02:42:07 字數 3408 閱讀 4667

命名管道也被稱為fifo檔案,它是一種特殊型別的檔案,它在檔案系統中以檔名的形式存在,但是它的行為卻和之前所講的沒有名字的管道(匿名管道)類似。

有名管道是有名有形的,為了使用這種管道linux中設立了乙個專門的特殊檔案系統–管道檔案,它存在於檔案系統中,任何程序可以在任何時候通過有名管道的路徑和檔案來訪問管道,但是在磁碟上的只是乙個節點,而檔案的資料則只存在於記憶體緩衝頁面中與普通管道一樣

我們可以使用兩下函式之一來建立乙個命名管道,他們的原型如下:

int mkfifo(const

char *filename, mode_t mode);

int mknod(const

char *filename, mode_t mode | s_ififo, (dev_t)0);

這兩個函式都能建立乙個fifo檔案,注意是建立乙個真實存在於檔案系統中的檔案,filename指定了檔名,而mode則指定了檔案的讀寫許可權。

mknod是比較老的函式,而使用mkfifo函式更加簡單和規範,所以建議在可能的情況下,盡量使用mkfifo而不是mknod。

與開啟其他檔案一樣,fifo檔案也可以使用open呼叫來開啟。注意,mkfifo函式只是建立乙個fifo檔案,要使用命名管道還得將其開啟。

但是有兩點要注意:

1、就是程式不能以o_rdwr模式開啟fifo檔案進行讀寫操作,其行為未明確定義,因為如乙個管道以讀/寫方式開啟,程序就會讀回自己的輸出,同時我們通常使用fifo只是為了單向的資料傳遞。

2、就是傳遞給open呼叫的是fifo的路徑名,而不是正常的檔案。

開啟fifo檔案通常有四種方式:

open(const

char *path, o_rdonly);//1

open(const

char *path, o_rdonly | o_nonblock);//2

open(const

char *path, o_wronly);//3

open(const

char *path, o_wronly | o_nonblock);//4

在open函式的呼叫的第二個引數中,你看到乙個陌生的選項o_nonblock,選項o_nonblock表示非阻塞,加上這個選項後,表示open呼叫是非阻塞的,如果沒有這個選項,則表示open呼叫是阻塞的。

open呼叫的阻塞是什麼一回事呢?很簡單,對於以唯讀方式(o_rdonly)開啟的fifo檔案,如果open呼叫是阻塞的(即第二個引數為o_rdonly),除非有乙個程序以寫方式開啟同乙個fifo,否則它不會返回;如果open呼叫是非阻塞的的(即第二個引數為o_rdonly | o_nonblock),則即使沒有其他程序以寫方式開啟同乙個fifo檔案,open呼叫將成功並立即返回。

對於以只寫方式(o_wronly)開啟的fifo檔案,如果open呼叫是阻塞的(即第二個引數為o_wronly),open呼叫將被阻塞,直到有乙個程序以唯讀方式開啟同乙個fifo檔案為止;如果open呼叫是非阻塞的(即第二個引數為o_wronly | o_nonblock),open總會立即返回,但如果沒有其他程序以唯讀方式開啟同乙個fifo檔案,open呼叫將返回-1,並且fifo也不會被開啟。

試想這樣乙個問題,只使用乙個fifo檔案,如果有多個程序同時向同乙個fifo檔案寫資料,而只有乙個讀fifo程序在同乙個fifo檔案中讀取資料時,會發生怎麼樣的情況呢,會發生資料塊的相互交錯?

為了解決這一問題,就是讓寫操作的原子化。怎樣才能使寫操作原子化呢?答案很簡單,系統規定:在乙個以o_wronly(即阻塞方式)開啟的fifo中, 如果寫入的資料長度小於等待pipe_buf,那麼或者寫入全部位元組,或者乙個位元組都不寫入。如果所有的寫請求都是發往乙個阻塞的fifo的,並且每個寫請求的資料長度小於等於pipe_buf位元組,系統就可以確保資料決不會交錯在一起。

這裡有兩個原始檔,乙個fifowrite.c,它在需要時建立管道,然後向管道寫入資料,資料由檔案data.txt提供,大小為10m,內容全是字元『0』。另乙個原始檔為fiforead.c,它從fifo中讀取資料,並把讀到的資料儲存到另乙個檔案dataformfifo.txt中。

/***fifowrite.c檔案***/

#include

#include

#include

#include

#include

#include

#include

#include

int main()

} printf("process %d opening fifo o_wronly\n", getpid());

//以只寫阻塞方式開啟fifo檔案,以唯讀方式開啟資料檔案

pipe_fd = open(fifo_name, open_mode);

data_fd = open("data.txt", o_rdonly);

printf("process %d result %d\n", getpid(), pipe_fd);

if(pipe_fd != -1)

//累加寫的位元組數,並繼續讀取資料

bytes_sent += res;

bytes_read = read(data_fd, buffer, pipe_buf);

buffer[bytes_read] = '\0';

} close(pipe_fd);

close(data_fd);

} else

exit(exit_failure);

printf("process %d finished\n", getpid());

exit(exit_success);

}

/***fiforead.c檔案***/

#include

#include

#include

#include

#include

#include

#include

#include

int main()

while(res > 0);

close(pipe_fd);

close(data_fd);

} else

exit(exit_failure);

printf("process %d finished, %d bytes read\n", getpid(), bytes_read);

exit(exit_success);

}

Linux程序間通訊 命名管道

ipc 命名管道 一 原理 管道的乙個不足之處是沒有名字,因此,只能用於具有親緣關係的程序間通訊,在命名管道 named pip 或fifo 提出後,該限制得到了克服。fifo 不同於管道之處 在於它提供乙個路徑名與之關聯,以fifo的檔案形式儲存於檔案系統中 命名管道是乙個裝置檔案,因此,即使程序...

linux程序間通訊(命名管道)

在處理程序間通訊的問題時,匿名管道只能在有親緣關係的程序中進行通訊。如何做到在任意兩個程序之間通訊,這就要用到命名管道。命名管道也被稱為fifo檔案,它是一種特殊型別的檔案,在檔案系統中以檔案的形式存在,它的行為和匿名管道類似。可以使用mkfifo函式來建立乙個命名管道。int mkfifo con...

Linux程序間通訊 命名管道

我們知道,匿名管道只能用於父子關係的程序之間。那麼沒有這種關係的程序之間該如何進行資料傳遞呢?1.什麼是命名管道 匿名管道是在快取中開闢的輸出和輸入檔案流的空間,只能用於父子關係的程序之間。因為父子程序的輸入和輸出檔案描述符是一致的。命名管道是一種實際存在的fifo檔案,稱作 管道檔案 用於不同程序...