管道是unix系統最古老的ipc形式。它有以下兩點侷限性:
通常是父程序通過系統呼叫pipe()建立管道,然後fork()出子程序,這兩個程序就可以通過管道進行通訊了。
管道fd:一條管道有兩個檔案描述符,這兩個檔案描述符是在呼叫pipe(fd)建立管道時獲取獲取的。
寫端程序:只向管道寫資料的程序。在使用管道時,先close(fd[0])、再通過write(fd[1])向管道寫資料。
讀端程序:只從管道讀資料的程序。在使用管道時,先close(fd[1])、在通過read(fd[0])從管道讀取資料。
下列**在linux環境下,貼上到本地後可以直接編譯執行。
#include
//declare int pipe(int pipefd[2]);
#include
//pipe_buf
#include
#include
#include
#define msg_from_parent "hello, world!"
int fd[2]
=;//儲存管道的兩個檔案描述符,fd[0] for read, fd[1] for write
intmain
(int argc,
char
**ar**)
pid =
fork()
;if(pid <0)
// fork error
else
if(pid >0)
// branch of parent
/* !!非常重要,writer寫完後必須關閉write end
* 否則reader在讀完管道中的資料後,再次讀管道時會因為沒有資料而一直阻塞 */
close
(fd[1]
);//建議注釋掉這行**,執行檢視下效果。有驚喜喲。你會發現printf()中\n有將緩衝區重新整理的效果
/* 父程序阻塞等待子程序退出 */if(
waitpid
(pid,
null,0
)<0)
printf
("parent exit\n");
}else
// branch of son
;// 故意把buf設的小一點,這樣可以多次讀取管道,觀察更多細節
int readlen =0;
doperror
("after read");
printf
("%s"
, read_buf)
;// printf()的fmt如果加上'\n',其效果可不只是換行喲。
//'\n'其實還有fflush(stdout)的作用:將printf緩衝區的資料重新整理到stdout(即螢幕)上。
}while
(readlen >0)
;close
(fd[0]
);printf
("\nson exit\n");
}return0;
}
如果pipe的一端被關閉,以下兩條規則將生效:
如果寫端關閉,那麼讀端將管道中的資料全部讀完後,如果再次呼叫read,將會返回0。
換言之,如果寫端程序寫完資料後沒有關閉pipe的寫端檔案描述符,那麼讀端程序在讀取乙個不再有資料可讀的管道時會阻塞。
如果讀端關閉,那麼寫端write時,將會產生訊號sigpipe,如果該訊號未被處理,write將返回-1,且errno被置為epipe。
關於linux訊號處理,有時間單寫一篇部落格總結一下。這裡只需要注意,向乙個讀端關閉的管道寫資料,write會返回-1;如果讀端沒有關閉,但是管道的資料一直沒有被讀端程序讀走,那麼當管道中快取資料達到pipe_buf規定的上限時(本示例中列印出的上限是4096 bytes),write會阻塞!
以上兩條規則告訴我們,不管是讀端程序還是寫端程序,用完了管道都要記得關閉啊!否則對端程序再次讀寫管道時會阻塞的!好嚴重的!
**********===
先寫到這裡,其實還有一些需要總結,有時間再填坑吧。
Unix管道與命名FIFO
事實上,管道與fifo是不同的 管道是pipe,基本上pipe 完就可以用了 fifo需要先mkfifo,然後再open 如果mkfifo發現fifo已存在,那麼說明已建立過,此時open pipe沒有名字,只能在親緣程序裡使用。當然,技術上講,可以傳遞描述符後,非親緣也可以用。但比較麻煩 fifo...
UNIX命名管道FIFO
fifo,又稱命名管道,是linux下 unix環境下 一種程序間通訊的機制,應用廣泛。函式mkfifo用於建立命名管道,使用命令man 3 mkfifo可檢視此函式資訊。fifo建立後,可以像普通檔案一樣對其訪問。執行命令 mkfifo tmp fifo cat tmp fifo 程式阻塞。再開啟...
unix下管道程式設計
模型pipe close dup2 read write 使用fopen和fclose的繞行自行查閱相關資料 首先基本了解這四個函式的分別作用 include intpipe int filedes 2 返回值 成功,返回0,否則返回 1。引數陣列包含pipe使用的兩個檔案的描述符。fd 0 讀管道...