管道(pipe)是無名管道,他是程序資源的一部分,隨著程序的結束而消失。並且它只能在擁有公共祖先程序的程序內通訊。而有名管道(fifo)的出現則解決了這個問題。fifo提供了乙個路徑名與它關聯。這樣可以通過訪問該路徑就能使得兩個程序之間相互通訊。此處的fifo嚴格遵守「先進先出」原則。讀總是從頭開始的,寫總是從尾部進行的。匿名管道和fifo都不支援lseek函式對他們操作。linux下建立有名管道的函式是mkfifo。
函式原型: int mkfifo(const char * pathname,mode_t mode);
函式功能:建立乙個fifo檔案,用於程序之間的通訊。pathname就是路徑名,mode是該檔案的許可權。返回值表示是否成功,返回0表示成功,返回-1表示失敗,失敗原因在errno中。(建立fifo的時候,要求不存在這樣的fifo)。
和pipe建立匿名管道相比,mkfifo需要設定檔案許可權。這是因為pipe建立的匿名管道是核心借助緩衝區建立的,它不在磁碟上真實存在,只在記憶體中存在。而mkfifo建立的有名管道是在磁碟上真實存在的,因此需要檔案許可權,正是由於真實存在這樣乙個檔案,所以才克服了在任意程序間通訊的問題。
例如執行下面**來建立乙個fifo。
可以看到,它以p開頭,表示它是乙個fifo檔案。它是真實存在於磁碟上的,不僅僅在記憶體中。程序結束了這個檔案仍然在。fifo和匿名管道一樣,預設下要考慮阻塞。
當使用o_nonblock標誌的時候,開啟fifo檔案,讀取操作會立即返回。但是如果沒有程序讀取fifo檔案,那麼寫入fifo的操作會返回enxio錯誤**。
不使用o_nonblock標誌時,開啟fifo的操作必須等待其他程序寫入fifo後才執行,當然寫入fifo的操作也必須等到其他程序來讀取fifo以後才能執行。
當存在這個fifo檔案的時候,再次建立這個fifo會顯示file exists。
首先,第一種情形的測試。
#include#include#include#include#include#includeint main()
pid_t pid;
pid = fork();
if(0 < pid)
else
exit(0);
}if(0 == pid)
if(-1 == pid)
return 0;
}
執行結果如下:
可以看到會發生錯誤,因為它沒有阻塞。那麼接著試一下直接讀乙個fifo檔案,看看會發生什麼。
#include#include#include#include#include#includeint main()
; ret = mkfifo("my_fifo",0666);
if(0 != ret)
pid_t pid;
pid = fork();
if(0 < pid)
else
exit(0);
}if(0 == pid)
if(-1 == pid)
return 0;
}
看到的結果是對乙個空的fifo檔案開啟並執行read操作是沒有問題的。
先以唯讀方式開啟,如果沒有程序已經為寫而開啟乙個 fifo, 唯讀 open() 成功,並且 open() 不阻塞。
下面,當不設定o_nonblock標誌的時候,fifo和匿名管道的處理方式是一樣的。管道這個名字是非常形象的,乙個管道必須有兩端(就是在乙個程序中必須讀,另乙個程序必須寫),只有這樣,才能正常操作,否則程序將會阻塞。例如下面這樣。
#include#include#include#include#include#include#includeint main()
; ret = mkfifo("my_fifo",0666);
if(0 != ret)
pid_t pid;
pid = fork();
if(0 < pid)
else
wait(null);
exit(0);
}if(0 == pid)
if(-1 == pid)
return 0;
}
我們僅僅在父程序中進行了寫(write),沒有其他程序在讀(read)。這樣造成的結果是程序一直阻塞在這裡,如下
沒有輸出結果,阻塞在這裡不動了。而當我們加上注釋掉了那兩句話以後,程式就會有輸出,結果如下:
或者說,這也體現了程序的並發行,管子有了一端以後,還必須有另一端,這才能構成管道。
上述的情形都是在唯讀或者只寫下開啟fifo檔案而言的,如果使用o_rdwr開啟fifo檔案,那麼除了read空fifo會阻塞。其餘將不會有問題。
測試一下,fifo用於兩個無關程序直接的通訊。首先建立我們有兩個程序,乙個是test1,另乙個是test2.
//test1的源**
//test1是寫fifo
#include#include#include#include#include#includeint main()
; ret = mkfifo("fifo",0666); 中建立fifo檔案
fd = open("fifo",o_wronly); //只寫方式開啟
write(fd,str,5);
close(fd);
return 0;
}
//test2的源**
//test2是讀fifo
#include#include#include#include#include#includeint main()
; fd = open("fifo",o_rdonly);
read(fd,str,5);
printf("%s\n",str);
close(fd);
return 0;
}
我們把test1和test2的源**生成可執行檔案後,開啟兩個終端。如果我先執行test1,然後執行test2.那麼test2將讀取到fifo中的資料。如下所示。
我們沒有設定o_nonblock,先執行test1之後,會發現test1阻塞在這裡。等我們把test2也執行了之後,test1不在阻塞,執行結束,然後test2也成功列印出了hello。
換個執行順序,我們先執行test2,然後執行test1.這樣會發現test2阻塞在這裡。等我們把test1也執行了之後,test2不在阻塞,向螢幕列印hello.
如果我們不想讓fifo阻塞,那麼開啟檔案的時候設定為可讀可寫即可。
fd = open("fifo", o_rdwr);
當然,如果fifo是空的,那麼即使設定了可讀可寫,read()操作仍舊會阻塞。這樣的執行結果和上面所說的是一致的。自己執行一下才能深刻理解。這裡不好用說明。
呼叫 write() 函式向 fifo 裡寫資料,當緩衝區已滿時 write() 也會阻塞。
首先使用mkfifo命令建立乙個fifo檔案,然後將ls的輸出重定向到myfifo。
可以看到阻塞在了這裡,我們現在開啟另外乙個終端,輸入cat myfifo。
這樣就將ls的結果列印出來了,同時另外乙個終端也不再阻塞。
Linux程序通訊 有名管道
管道 pipe 是無名管道,他是程序資源的一部分,隨著程序的結束而消失。並且它只能在擁有公共祖先程序的程序內通訊。而有名管道 fifo 的出現則解決了這個問題。fifo提供了乙個路徑名與它關聯。這樣可以通過訪問該路徑就能使得兩個程序之間相互通訊。此處的fifo嚴格遵守 先進先出 原則。讀總是從頭開始...
程序通訊 有名管道
無名管道只能由父子程序使用 但是通過命名管道,不相關的程序也能交換資料。建立管道mkfifo 開啟管道open 讀管道read 寫管道write 關閉管道close 刪除管道unlink 函式作用 建立有名管道 函式原型 int mkfifo const char pathname,mode t m...
Linux程序通訊之有名管道
1 定義參照前文無名管道 2 特點 1 區別於無名,管道有名管道可以使互不相關的兩個程序通訊 在建立管道時,通過路徑 檔名來進行識別 2 建立有名管道後,程序可以將其作為檔案來進行讀寫 3 先進先出fifo。4 fifo在寫入的資料的位元組數小於或者等於pipe buf時,能夠保證write操作是原...