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