程序通訊之有名管道
一、前言:
我們前面部落格講過,父子程序之間,對於檔案操作的檔案操作符是共享的,而對於程序的全域性資料,堆區資料,棧區資料是不共享的,那麼程序之間到底是怎麼進行資訊的傳遞的呢,具體的實現,以及傳遞的過程是怎麼完成的呢,前面我們講過訊號在程序之間的使用,那也是一種程序之間資訊的傳遞。
二、程序的通訊方式---有名管道
程序的通訊方式主要有訊號,管道,訊號量,訊息佇列,共享記憶體,socket(套接字);
而我們今天說的是管道中的有名管道,那麼什麼是管道呢,在前面的檔案系統中說過乙個檔案的分類中有乙個檔案類叫管道檔案,而我們這邊說的管道就是管道檔案,為啥呢?linux下一切皆檔案。
接著我們看它的定義:
管道:在記憶體上開闢一塊空間,用檔案描述符指向這塊空間(也就是以操作檔案的方式來使用這塊空間)。
有名管道:在檔案系統中存在乙個檔案標識(檔名),但是這管道檔案不佔據磁碟空間,而是在記憶體上,需要傳遞的資料快取在記憶體區域上。
管道檔案與普通檔案的區別:
儲存:管道檔案---------------記憶體
普通檔案---------------磁碟
有名管道是一種特殊的管道:稱為fifo(first in first out,先進先出),類似於我們在資料結構中學的『佇列』,它也叫命名管道,用於沒有聯絡的程序之間的通訊。
接著我們看兩個無關的程序之間資料傳輸的圖示:
上面是兩個程序之間進行資訊的傳遞,利用管道檔案,而管道檔案所在為記憶體區域,當程序a對管道檔案進行寫操作,程序b 就會從管道檔案讀取程序a寫在管道檔案中的資料,從而實現兩個程序之間資料的傳遞。
建立管道的命令:
shell下: mkfifo + 所要建立的管道檔名
函式中建立管道檔案的函式是:
int mkfifo(const char*pathname, mode_t mode);
管道檔案的操作:
開啟:int open(char *path,int flag,);
讀:int read(int fd, void *buff, size_t size);
寫: int write(int fd, void *buff, size_t size);
關閉:int close(int fd);
對於普通檔案操作時開啟檔案,如果這個檔案不存在,則建立,但是對於管道檔案則不行,則需要呼叫上面的mkfifo()函式,建立乙個管道檔案。
三、練習:
利用有名管道使程序a將"hello world"傳送給程序b:
**如下:
管道檔名為:baby
寫操作:檔名:a.c
#include #include #include #include #include int main()
讀操作:檔名:b.c
#include #include #include #include #include int main()
執行結果:
只執行 ./a的時候
什麼也沒有列印,而我們在函式內部定義的開啟成功則列印"open succes",但是輸出面板上並沒有,說明open這個函式開啟並沒有成功。反過來我們看讀取檔案。
只執行 ./b(讀取檔案)的時候
也是沒有列印和上述現象一模一樣,那這到底是什麼原因呢。我們接著試一下,兩個程式(程序)同時執行時會有什麼現象,理想情況下,兩個都會列印open succes,b檔案也就是讀取檔案會列印hello world 。
兩個同時執行:開啟兩個終端,分別執行./a ./b
當./a 命令發出時,沒有變化,當./b繼續執行時,這時候./a執行的終端下列印出了open succes,說明管道檔案開啟成功,而./b在它的所在終端下也列印出了open succes,和hello world 說明一切與預想的一模一樣。這又是為什麼呢,為什麼兩個程式單獨執行的時候open都沒有執行,而當同時執行的時候,兩個程式都執行正常呢。
提到這裡,它的主要原因是與有名管道的特性分不開的。
open阻塞:
對於./a程式,當單獨執行的時候,open以只寫方式開啟上面所建立的管道檔案baby,這時候,open函式會阻塞執行,直到有另外乙個程序以唯讀或者讀寫的方式去開啟管道檔案的時候,兩個程序才會執行下去。
反之對於./b程式,當程式單獨執行且open以唯讀方式開啟所建立的管道檔案baby,也會引起阻塞,直到有乙個程序以只寫或者讀寫的方式開啟管道檔案,才會成功執行下去。
read阻塞:
read函式也會引起阻塞執行,直到管道中有資料或者寫端關閉。
write阻塞:
write函式也會引起阻塞執行,當管道檔案寫滿的時候。
這裡管道檔案滿,說明管道檔案也有乙個容量上限,我們知道管道檔案在記憶體上,而記憶體的大小,在32位系統上是4gb大小,那麼管道檔案到底是預設多大呢(肯定比4gb小);
下面我們做乙個小測試:
測試內容:
管道檔案的大小:
**如下:
#include #include #include #include #include void main()
close(fd);
exit(0);
}
結果:
count顯示是65536,而我們每次往管道檔案寫乙個char 型別的『x』,意思寫了65536個『x』,也就是65536個位元組,當寫到65536的時候,程式不再執行,說明管道檔案已滿,這時候,就是管道檔案的最大容量。也就是管道檔案預設容量 = 65536位元組 = 64k位元組 = 16個頁面(這裡的1k就是1024位元組)。我們其實也可以用fcntl函式來修改管道容量(後期將解釋)。
四、半雙工和全雙工通訊
半雙工通訊:在一次通訊中,資料流向是單向的。如對講機和以前的電報
全雙工通訊:在任意時刻,資料都可以雙向流通。如現在的手機通訊。
程序間通訊之有名管道
相對於無名管道而言,有名管道當然是有名字的,這樣就可以使任何程序通過檔名或路徑名與該管道掛鉤。所以,有名管道可用於任意兩程序之間的通訊。就有名管道和無名管道的實現來說,主要是在開啟方式上有所不同,管道檔案一旦開啟 建立 以後兩者對管道檔案的讀 寫和關閉操作相同。int open const char...
Linux程序通訊之有名管道
1 定義參照前文無名管道 2 特點 1 區別於無名,管道有名管道可以使互不相關的兩個程序通訊 在建立管道時,通過路徑 檔名來進行識別 2 建立有名管道後,程序可以將其作為檔案來進行讀寫 3 先進先出fifo。4 fifo在寫入的資料的位元組數小於或者等於pipe buf時,能夠保證write操作是原...
程序通訊 有名管道
無名管道只能由父子程序使用 但是通過命名管道,不相關的程序也能交換資料。建立管道mkfifo 開啟管道open 讀管道read 寫管道write 關閉管道close 刪除管道unlink 函式作用 建立有名管道 函式原型 int mkfifo const char pathname,mode t m...