UNP(卷2:進程間通信)—— 第4章:管道和FIFO


管道

由pipe創建,提供一個單向的數據流。

#include <unistd.h>

int pipe(int fd[2]);
                                     // 返回:成功則爲0,出錯則爲-1
該函數返回兩個文件描述符 fd[0] 和 fd[1] 。前者打開來讀,後者打開來寫

所有管道都是半雙工的,即單向數據流。

全雙工管道

某些系統提供全雙工管道:

1、SVR4的pipe函數。


2、socketpair函數。

/* socketpair - create a pair of connected sockets */

#include <sys/socket.h>

int socketpair(int domain, int type, int protocol, int socket_vector[2]);
                                                                           // 返回:成功則爲0,出錯則爲-1

popen 和 pclose 函數

#include <stdio.h>

FILE *popen(const char *command, const char *type);
                                                    // 返回:若成功則爲文件指針,若出錯則爲NULL

int pclose(FILE *stream);
                                                    // 返回:若成功則爲shell的終止狀態,若出錯則爲-1

popen 函數,它創建一個管道並啓動另外一個進程,該進程要麼從該管道讀出標準輸入,要麼往該管道寫入標準輸出。

command是一個shell命令行,

type:

(1)type爲 r ,調用進程讀進command的標準輸出。

(2)type爲 w,調用進程寫進command的標準輸入。

pclose函數關閉有popen創建的標準I/O流,等待其中的命令終止,然後返回shell的終止狀態。


FIFO

#include <sys/types.h>
#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);
                                                      // 返回:成功則爲0,出錯則爲-1

pathname是一個路徑名。FIFO的名字。

mode參數指定文件權限位。

在創建出一個FIFO後,它必須或者打開來讀,或者打開來寫。不能打開來既讀又寫,因爲它是半雙工的。


首先,一個描述符能以兩種方式設置成非阻塞。

(1)調用open時可指定O_NONBLOCK標誌。

(2)如果一個描述符已經打開,那麼可以調用fcntl以啓用O_NONBLOCK標誌。

因爲管道沒有open調用,在pipe調用中沒法指定O_NONBLOCK標誌,所以管道必須使用fcntl函數來設置。



下面是關於管道或FIFO的讀出與寫入的若干額外規則。

(1)如果請求讀出的數據量多於管道或FIFO中當前可用數據量,那麼只返回這些可用的數據。


(2)如果請求寫入的數據的字節數小於或等於PIPE_BUF(一個Posix限制值,可以通過getconf命令查看PIPE_BUF的大小),那麼write操作保證的原子的。這意味着,如果有兩個進程差不多同時往同一個管道或FIFO寫,那麼或者先寫入來自第一個進程的所有數據,再寫入來自第二個進程的所有數據,或者顛倒過來。系統不會互相混雜來自這兩個進程的數據。然而,如果請求寫入的數據的字節數大於PIPE_BUF,那麼write操作不能保證是原子的。


(3)O_NONBLOCK標誌的設置對write操作的原子性沒有影響。原子性完全是由所請求字節數是否小於等於PIPE_BUF決定的。然而當一個管道或FIFO設置成非阻塞時,來自write的返回值取決於待寫的字節數以及該管道或FIFO中當前可用空間的大小。

寫入的字節數小於等於PIPE_BUF:

a.如果該管道或FIFO中有足以存放所請求字節數的空間,那麼所有數據字節都寫入。

b.如果該管道或FIFO中沒有足以存放所請求字節數的空間,那麼立即返回一個EAGAIN錯誤。

寫入的字節數大於PIPE_BUF:

a.如果該管道或FIFO中至少有1字節空間,那麼內核寫入該管道或FIFO能容納數目的數據字節,該數目同時作爲來自write的返回值。

b.如果該管道或FIFO已滿,那麼立即返回一個EAGAIN錯誤。


(4)如果向一個沒有爲讀打開着的管道或FIFO寫入,那麼內核將產生一個SIGPIPE信號;

a.如果調用進程既沒有捕獲也沒有忽略該SIGPIPE信號,所採取的默認行爲就是終止該進程。

b.如果調用進程忽略了該SIGPIPE信號,或者捕獲了該信號並從其信號處理程序中返回,那麼write返回一個EPIPE錯誤。


管道和FIFO限制:

系統加於管道和FIFO的唯一限制爲:

OPEN_MAX        一個進程在任意時刻打開的最大描述符數。(Posix要求至少爲16)

PIPE_BUF          可原子地寫往一個管道或FIFO的最大數據量。(Posix要求至少爲512)

定義在頭文件<limits.h>






























發佈了98 篇原創文章 · 獲贊 74 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章