1)無名管道:
管道是半雙工的,資料只能向乙個方向流動;需要雙方通訊時,需要建立起兩個管道;只能用於父子程序或者兄弟程序之間(具有親緣關係的程序)。
單獨構成一種獨立的檔案系統:管道對於管道兩端的程序而言,就是乙個檔案,但它不是普通的檔案,它不屬於某種檔案系統,而是自立門戶,單獨構成一種檔案系統,並且只存在與記憶體中。
資料的讀出和寫入:乙個程序向管道中寫的內容被管道另一端的程序讀出。寫入的內容每次都新增在管道緩衝區的末尾,並且每次都是從緩衝區的頭部讀出資料。(有點像佇列哈)
#include
int pipe(int fd[2])
該函式建立的管道的兩端處於乙個程序中間,在實際應用中沒有太大意義,因此,乙個程序在由 pipe()
建立管道後,一般再
fork
乙個子程序,然後通過管道實現父子程序間的通訊(因此也不難推出,
只要兩個程序中存在親緣關係,這裡的親緣關係指的是具有共同的祖先,都可以採用管道方式來進行通訊
)。向管道中寫入資料時,linux
將不保證寫入的原子性,管道緩衝區一有空閒區域,寫程序就會試圖向管道寫入資料。如果讀程序不讀走管道緩衝區中的資料,那麼寫操作將一直阻塞。
注:只有在管道的讀端存在時,向管道中寫入資料才有意義。否則,向管道中寫入資料的程序將收到核心傳來的sifpipe
訊號,應用程式可以處理該訊號,也可以忽略(預設動作則是應用程式終止)。
2)有名管道:不同於管道之處在於它提供乙個路徑名與之關聯,以
fifo
的檔案形式存在於檔案系統中。
這樣,即使與fifo
的建立程序不存在親緣關係的程序,只要可以訪問該路徑,就能夠彼此通過
fifo
相互通訊(能夠訪問該路徑的程序以及
fifo
的建立程序之間),因此,通過
fifo
不相關的程序也能交換資料。
值得注意的是,fifo
嚴格遵循先進先出(
first in first out
),對管道及
fifo
的讀總是從開始處返回資料,對它們的寫則把資料新增到末尾。它們不支援諸如
lseek()
等檔案定位操作。
有名管道的建立
#include
#include
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 『』』
while :
doecho 「
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
的連線方式。
(資料**於網際網路)
無名管道和有名管道
無名管道 無名管道建立 int pipe int filedis 2 當乙個管道建立時,它會建立兩個檔案描述符 filedis 0 用於讀管道,filedis 1 用於寫管道 管道用於不同程序間通訊。通常先建立乙個管道,再通過fork函式建立乙個子程序,該子程序會繼承父程序所建立的管道 有名管道 有...
無名管道(PIPE)與 有名管道(FIFO)
更多資料 我的目錄 1 無名管道的建立 標頭檔案 include 函式原型 int pipe int pipefd 2 引數 pipefd 乙個至少具有兩個int型資料的陣列 pipefd 0 讀端的檔案描述符,只能讀取管道中的資訊 pipefd 1 寫端的檔案描述符,只能往管道中寫入資訊 返回值 ...
管道 無名管道 和FIFO 有名管道
管道是最初的unixipc形式,但是因為管道沒有名字,所以它們只能用於有親緣關係的程序使用 進而有名管道 fifo 應運而生,有名管道有乙個路徑名與之關聯,所以允許無親緣關係的程序訪問同乙個fifo。以下具體介紹管道 管道的建立 管道由函式 int pipe int fd 2 建立,提供乙個單向資料...