17、有名管道与无名管道之间的区别
?
1)無名管道:管道是半雙工的,數據只能向一個方向流動;需要雙方通信時,需要建立起兩個管道;只能用于父子進程或者兄弟進程之間(具有親緣關系的進程)。
??? 單獨構成一種獨立的文件系統:管道對于管道兩端的進程而言,就是一個文件,但它不是普通的文件,它不屬于某種文件系統,而是自立門戶,單獨構成一種文件系統,并且只存在與內存中。
??? 數據的讀出和寫入:一個進程向管道中寫的內容被管道另一端的進程讀出。寫入的內容每次都添加在管道緩沖區的末尾,并且每次都是從緩沖區的頭部讀出數據。(有點像隊列哈)
#include <unistd.h>
int pipe(int fd[2])
??? 該函數創建的管道的兩端處于一個進程中間,在實際應用中沒有太大意義,因此,一個進程在由 pipe()創建管道后,一般再fork一個子進程,然后通過管道實現父子進程間的通信(因此也不難推出,只要兩個進程中存在親緣關系,這里的親緣關系指的是具有共同的祖先,都可以采用管道方式來進行通信)。
??? 向管道中寫入數據時,linux將不保證寫入的原子性,管道緩沖區一有空閑區域,寫進程就會試圖向管道寫入數據。如果讀進程不讀走管道緩沖區中的數據,那么寫操作將一直阻塞。
注:只有在管道的讀端存在時,向管道中寫入數據才有意義。否則,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序可以處理該信號,也可以忽略(默認動作則是應用程序終止)。
2)有名管道:不同于管道之處在于它提供一個路徑名與之關聯,以FIFO的文件形式存在于文件系統中。這樣,即使與FIFO的創建進程不存在親緣關系的進程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信(能夠訪問該路徑的進程以及FIFO的創建進程之間),因此,通過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀總是從開始處返回數據,對它們的寫則把數據添加到末尾。它們不支持諸如lseek()等文件定位操作。
有名管道的創建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
??? 該函數的第一個參數是一個普通的路徑名,也就是創建后FIFO的名字。第二個參數與打開普通文件的open()函數中的mode 參數相同。如果mkfifo的第一個參數是一個已經存在的路徑名時,會返回EEXIST錯誤,所以一般典型的調用代碼首先會檢查是否返回該錯誤,如果確實返回該錯誤,那么只要調用打開FIFO的函數就可以了。一般文件的I/O函數都可以用于FIFO,如close、read、write等等
3)無名管道由一個在基本文件系統存儲設備上的INODE,一個與其相連的內存INODE,兩個打開文件控制塊(分別對應管道的信息發送端和信息接收端)及其所屬進程的描述信息來標識,在系統執行PIPE(P)命令行之后生成。并在P[0]中返回管道的讀通道打開文件描述等,在P[1]中返回管道的寫通道打開文件描述符。從結構上看,無名管道沒有文件路徑名,不占用文件目錄項,因此文件目錄結構中的鏈表不適用于這種文件,它只是存在于打開文件結構中的一個臨時文件,隨其所依附的進程的生存而生存,當進程終止時,無名管道也隨之消亡。
送入管道的信息一旦被讀進程取用就從管道中消失了,讀寫操作之間符合先進先出的隊列原則。
??? 管道文件是進程間通信的工具,為了盡量少的占用系統存儲資源,一般系統均將其限制為最大長度為4096(PIPSIZ)字節的小型文件。當欲寫入的消息超過4096字節時,就產生了讀、寫進程之間的同步問題。首先寫操作查找PIPE文件中當前指針的偏移量F-OFFSET,然后從此位置開始盡量寫入信息,當長度達到4096字節時,系統控制寫進程進入睡眠狀態,一直等待讀進程取走全部信息時,文件長度指針置0,寫進程才被喚醒繼續工作。
??? 為防止多個進程同時讀寫一個管道文件而產生混亂,在管道文件的INODE標志字I-FLAY項中設置了ILOCK標志項,以設置軟件鎖的方式實現多進程間對管道文件的互斥使用。
無名管道存在著如下兩個嚴重的缺點。
??? 第一,無名管道只能用于連接具有共同祖先的進程。
??? 第二,無名管道是依附進程而臨時存在的。所以后來推出了一種無名管道的變種-有名管道,它常被稱為FIFO。有名管道除繼承了無名管道的所有特性優點之外,還屏棄了無名管道的兩個缺點。
??? 首先,FIFO是一種永久性的機構,它具有普通的UNIX系統文件名。在系統下可利用MKNOD命令建立永久的管道,除非刻意刪除它,否則它將一直保持在系統中。
其次,正是由于有名管道以“文件名”來標識,所以只要事先約定某一特定文件名,那樣所有知道該約定的服務進程,不論它們之間是否有親屬關系,都可以便利地利用管道進行通信。
??? 通過下面的命令可以創建一個命名管道:
??? /etc/mknod pipe_name p?
??? 其中“pipe_name”是要創建的命名管道的名字,參數p 必須出現在命名管道名字之后。?
??? 命名管道文件被創建后,一些進程就可以不斷地將信息寫入命名管道文件里,而另一些進程也可以不斷地從命名管道文件中讀取信息。對命名管道文件的讀寫操作是可以同時進行的。下面的例子顯示命名管道的工作過程。
??? 進程A、B、C中運行的程序只是一條簡單的echo命令,它們不斷地把信息寫入到命名管道文件/tmp/pipe1中。與此同時,程序中的“read msg”命令不斷地從命名管道文件/tmp/pipe1中讀取這些信息,從而實現這些進程間的信息交換。?
??? 程序執行時,首先創建命名管道文件,此時程序處于等待狀態,直到A、B、C進程中某一個進程往命名管道中寫入信息時,程序才繼續往下執行。使用rm命令可以刪除命名管道文件從而清除已設置的 命名管道。?
??? 下面是一個用于記錄考勤的例子:?
??? 在主機上運行的程序/tmp/text產生命名管道/tmp/pipe1,并不斷地從命名管道中讀取信息送屏幕上顯示。?
/tmp/text程序:
if [ ! -p /tmp/pipe1 ]
then
? /etc/mknode /tmp/pipe1 p
fi
while :
do
? read msg
? if [ “$msg" = “" ]
? then
continue
? else
echo “$msg"
? fi
done < /tmp/pipe1
?? 在終端上運行的是雇員簽到程序/tmp/text1。每個雇員在任何一臺終端上鍵入自己的名字或代碼,程序/tmp/text1將把這個名字連同當時的簽到時間送入命名管道。
/tmp/text1程序:
tty=‘who am I | awk ‘{print $2}’’
while :
do
echo “Enter your name: \c" > /dev/$tty
????? read name
????? today=‘date’
????? echo “$name\t$today"
????? done > /tmp/pipe1
?? 當雇員從終端上輸入自己的姓名后,運行/tmp/text程序的主機將顯示類似下面的結果:?
wang Thu Jan 28 09:29:26 BTJ 1999
he Thu Jan 28 09:29:26 BTJ 1999
cheng Thu Jan 28 09:30:26 BTJ 1999
zhang Thu Jan 28 09:31:26 BTJ 1999
named pipes(命名管道)管道具有很好的使用靈活性,表現在:
?? 1) 既可用于本地,又可用于網絡。
?? 2) 可以通過它的名稱而被引用。
?? 3) 支持多客戶機連接。
?? 4) 支持雙向通信。
?? 5) 支持異步重疊I/O操作。
不過,當前只有Windows NT,UNIX支持服務端的命名管道技術,win95/97/98等不支持。 SQL Server等數據庫就有named pipes的連接方式。
(資料來源于互聯網)
總結
以上是生活随笔為你收集整理的17、有名管道与无名管道之间的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Altiris 7.1 远程
- 下一篇: 灾备理论-可靠的异地灾备