UNIX網絡編程卷二 筆記 管道和FIFO

第1章 管道和FIFO

1.1 pipe


int pipe(int fd[2]);

創建一個單向、半雙工管道,其中fd[0]用於讀,fd[1]用於寫。

1.2 fork

管道很少在單個進程內使用,一般用在兩個有親緣關係的進程間,父進程在pipe後fork,然後和子進程或子進程的後裔利用這個管道通信。


pipe(fd);   
if ((pid = fork()) == 0)   
{   
    close(fd[0]);   
    /*用fd[1]向父進程傳遞數據*/
}   
close(fd[1]);   
/*用fd[0]接收子進程傳遞的數據*/

1.3 全雙工管道

可移植的創建全雙工管道的方法是創建兩個管道,分別負責一個方向的通信。

Linux中可以用socketpair創建一對Unix域套接字來模擬全雙工管道的功能。

1.4 popen和pclose


FILE *popen(const char *cmd, const char *type);   
int pclose(FILE *stream);

管道的一種常見應用模式是父進程pipe+fork後,子進程重定向標準輸入和輸出,再exec執行一個目標程序。

popen用來簡化這一系列操作,其中type用來指定讀寫。pclose會先關閉文件流,等到子進程執行結束後再返回子進程的退出狀態。

1.5 shell中創建管道

當在shell中輸入這樣的命令時:


who | sort | lp

該shell將創建三個進程和其間的兩個管道,還把每個管道的fd[0]複製到相應進程的stdin,fd[1]複製到相應進程的stdout上。

1.6 mkfifo


int mkfifo(const char *pathname, mode_t mode);

mkfifo用來創建一個FIFO文件,它的mode隱含了O_CREAT | O_EXCL。FIFO允許無親緣關係的任意進程訪問,這是和管道的最大區別。

1.7 打開FIFO

創建FIFO後,可用open或fopen打開FIFO,打開時只能指定讀或寫,不能同時指定。

默認的阻塞模式下,以讀或寫模式打開一個FIFO時,若當前沒有進程以對應的寫或讀模式打開FIFO,這個open將會阻塞,直到另一個進程以對應模式打開FIFO才返回。不正確的FIFO操作可能會導致死鎖。

非阻塞模式下,讀模式打開一個沒有進程寫打開的FIFO會成功返回,相反則會返回錯誤。

所有打開FIFO的進程都關閉FIFO後,FIFO中的剩餘數據會被丟棄。

1.8 設置屬性

open打開FIFO時可指定O_NONBLOCK標誌,如:


writefd = open(FIFO1, O_WRONLY | O_NONBLOCK, 0);

對描述符可以用fcntl啓用O_NONBLOCK標誌。管道不能用open,因此必須用這一方法:


flags = fcntl(fd, F_GETFL, 0);   
flag |= O_NONBLOCK;   
fcntl(fd, F_SETFL, flags);

1.9 讀寫管道和FIFO

對管道和FIFO的write總從末尾寫,read總從開頭讀,lseek會返回錯誤。

阻塞模式下,read時若管道中有數據則返回,可能返回的數據比請求的少;若管道爲空,如果有進程寫打開該管道,則阻塞,否則返回0,表示遇到了EOF。

write時寫入的數據會分成若干個最大爲PIPE_BUF字節的段,每段都是原子寫入,但多個進程的多段數據寫入不保證原子性。寫一個沒有進程讀打開的FIFO會產生SIGPIPE信號。

非阻塞read和write不會影響操作的原子性,但會在需要阻塞的時候返回錯誤,包括:

1) read空管道。

2) write的字節數不大於PIPE_BUF,但管道中剩餘空間不足時,爲了保證原子操作。

3) write的字節數大於PIPE_BUF,管道中還有空間則寫入那麼多字節,否則返回錯誤。

1.10 FIFO的單服務器多客戶

服務器需要一個公開的FIFO路徑接收客戶的請求,客戶爲了能接收服務器的迴應,應該在請求中附上客戶自己創建的FIFO路徑。

併發服務器可以創建一個子進程池或子線程池來提高響應速度。

對迭代服務器的拒絕服務器型攻擊是指故意發送一個不完整的請求,服務器就會陷入對剩下部分的等待中。對併發服務器的攻擊則是發送大量獨立請求,導致服務器fork失敗。

1.11 字節流和消息

管道和FIFO發送的是無邊界的字節流,有三種技巧用於判定消息邊界:

1) 約定的終止符。

2) 顯式指定長度。

3) 每次連接一個記錄。

1.12 管道和FIFO的限制

系統的限制:

1) OPEN_MAX 打開的最大描述符數。

2) PIPE_BUF 原子寫入的最大數據量。

FIFO是單主機上的IPC形式,不能用在NFS文件系統上。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章