1、管道(pipe)node
管道是進程間通訊的主要手段之一。一個管道實際上就是個只存在於內存中的文件,對這個文件的操做要經過兩個已經打開文件進行,它們分別表明管道的兩端。管道是一種特殊的文件,它不屬於某一種文件系統,而是一種獨立的文件系統,有其本身的數據結構。根據管道的適用範圍將其分爲:無名管道和命名管道。linux
● 無名管道編程
主要用於父進程與子進程之間,或者兩個兄弟進程之間。在linux系統中能夠經過系統調用創建起一個單向的通訊管道,且這種關係只能由父進程來創建。所以,每一個管道都是單向的,當須要雙向通訊時就須要創建起兩個管道。管道兩端的進程均將該管道看作一個文件,一個進程負責往管道中寫內容,而另外一個從管道中讀取。這種傳輸遵循「先入先出」(FIFO)的規則。數據結構
● 命名管道ide
命名管道是爲了解決無名管道只能用於近親進程之間通訊的缺陷而設計的。命名管道是創建在實際的磁盤介質或文件系統(而不是隻存在於內存中)上有本身名字的文件,任何進程能夠在任什麼時候間經過文件名或路徑名與該文件創建聯繫。爲了實現命名管道,引入了一種新的文件類型——FIFO文件(遵循先進先出的原則)。實現一個命名管道實際上就是實現一個FIFO文件。命名管道一旦創建,以後它的讀、寫以及關閉操做都與普通管道徹底相同。雖然FIFO文件的inode節點在磁盤上,可是僅是一個節點而已,文件的數據仍是存在於內存緩衝頁面中,和普通管道相同。函數
系統調用pipe是用來創建管道的。該調用的聲明格式以下:
int pipe(int filedes[2]);
一個管道擁有兩個文件描述符用來通訊,它們指向一個管道的索引節點,該調用將這兩文件描述符放在參數filedes中返回。如今的許多系統中管道容許數據雙向流動,但通常習慣上,文件描述符filedes[0]用來讀數據,filedes[1]用來寫數據。若是要求程序的可移植性好,就按照習慣的用法來編程。調用成功時,返回值爲0;錯誤時,返回-1,並設置錯誤代碼errno:
EMFILE:進程使用了過多的文件描述符。
ENFILE:系統文件表滿。
EFAULT:參數filedes無效。
對於寫管道:
寫入管道的數據按到達次序排列。若是管道滿,則對管道的寫被阻塞,直到管道的數據被讀操做讀取。對於寫操做,若是一次write調用寫的數據量小於管道容量,則寫必須一次完成,即若是管道所剩餘的容量不夠,write被阻塞直到管道的剩餘容量能夠一次寫完爲止。若是write調用寫的數據量大於管道容量,則寫操做分屢次完成。若是用fcntl設置管道寫端口爲非阻塞方式,則管道滿不會阻塞寫,而只是對寫返回0。spa
對於讀管道:
讀操做按數據到達的順序讀取數據。已經被讀取的數據在管道內再也不存在,這意味着數據在管道中不能重複利用。若是管道爲空,且管道的寫端口是打開狀態,則讀操做被阻塞直到有數據寫入爲止。一次read調用,若是管道中的數據量不夠read指定的數量,則按實際的數量讀取,並對read返回實際數量值。若是讀端口使用fcntl設置了非阻塞方式,則當管道爲空時,read調用返回0。
設計
有名管道又稱爲FIFO,是進程間通訊的一種方式。FIFO具備如下特色:索引
1.全雙工的通訊模式,數據先進先出;進程
2.能夠用於任意的進程之間,經過指定相同的管道文件進行通訊;
3.文件名存在文件系統中,而管道中的內容存在於內存中。可經過open、read、write對其操做;
使用FIFO的步驟以下:
1、建立/打開一個FIFO
FIFO是一種文件類型,在Linux系統中FIFO的類型用p表示。以下所示:
-rwxr-xr-x 1 root root 7368 2008-10-29 09:05 create_fifo
-rw-r--r-- 1 root root 380 2008-10-29 09:05 create_fifo.c
prw-r--r-- 1 root root 0 2009-06-12 14:18 myfifo
-rwxr-xr-x 1 root root 8178 2008-10-29 08:58 read_fifo
-rw-r--r-- 1 root root 1185 2008-10-29 09:00 read_fifo.c
-rwxr-xr-x 1 root root 8333 2009-06-12 14:20 write_fifo
-rw-r--r-- 1 root root 1139 2009-06-12 14:19 write_fifo.c
能夠看到,雖然FIFO文件存在於文件系統中(可供不一樣的進程打開),但FIFO中的內容都存放在內存中,因此文件大小始終爲0。
因爲FIFO不是普通文件,因此只能用文件IO來訪問。
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
函數mkfifo用於建立一個有名管道,參數path指定要建立的FIFO的路徑,mode爲該管道文件的訪問權限,通常用八進制數表示。
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int oflag, ... );
函數open經過指定路徑打開一個文件,不一樣的進程能夠調用open打開同一個FIFO進行通訊。參考下面的代碼(相關頭文件省略)
#define BUF_SIZE 51 int main(int argc, char *argv[]) { int fd; ssize_t n; char buf[BUF_SIZE]; if ( argc <2) { fprintf(stdout, 「Usage: %s <fifo_path>\n」, argv[0]); exit(1); } if ( mkfifo(argv[1], 0666) < 0 ) // 建立FIFO失敗 { if (errno != EEXIST ) // 出錯緣由不是由於管道已存在 { fprintf(stderr, 「mkfifo() failed %s\n」, strerror(errno)); exit(-1); } } if ( (fd = open(argv[1], O_RDWR)) < 0 ) // 打開FIFO出錯 { // 注:< 優先級要高於 = fprintf(stderr, 「open() failed %s\n」, strerror(errno)); exit(-1); } … return 0; }