Posix管道基本知識

2021-06-27 19:21:56 字數 2928 閱讀 1647

1. 基本資訊

管道是最早的ipc形式,一般可以分為管道和fifo(命名管道)兩類,使用通常的read和write進行讀寫。管道可以分為全雙工和半雙工管道。不同版本的unix提供了不同的實現。svr4的pipe建立的為全雙工管道,而posix1標準則為半雙工管道。一般是先全雙工管道使用socketpair函式較為可靠。

2. pipe、popen、pclose

#include int pipe(int fd[2]);
該函式會返回兩個檔案描述符,fd[0]用來讀、fd[1]用來寫。

儘管管道由單個程序建立,但其一般會作為程序通訊的手段。過程大致如下:

首先,乙個程序建立管道後fork出乙個自身的副本

接著,父程序關閉讀入端,子程序關閉寫入端

這樣就形成了一條父程序到子程序的單向流。實際上當我們執行who | sort | lp命令時,將建立3個程序和2個管道。而如果我們需要雙向資料流時,其步驟如下:

a. 建立兩條管道(fd1[2] 和 fd2[2])

b. fork出自身的副本

c. 父程序關閉管道1的讀和管道2的寫

d. 子程序關閉管道1的寫和管道2的讀

#include file *popen(const char *command, const char *type);//成功返回檔案指標,失敗返回null

int pclose(file *stream);//成功返回shell中止狀態,出錯返回-1

command      shell命令列,函式在呼叫程序和命令列程序間建立乙個管道

type                 管道型別,type = w為寫管道、type = r 為讀管道

3. 命名管道(fifo)

上面我們提到的主要是匿名管道的一些介面,其主要是針對有親緣關係的程序通訊。而命名管道可以允許無親緣關係的程序訪問同乙個fifo。

#include  #include int mkfifo(const char *pathname, mode_t mode);
pathname       普通unix路徑名,也是該fifo的名字

mode               許可權位

本函式已經隱含指定了o_creat | o_excl標誌位,即其要麼建立乙個fifo,要麼返回乙個eexist錯誤,如果我們不希望建立乙個新的fifo則,我們需要使用open函式。在shell環境下我們可以使用mkfifo命令建立命名管道。實際上fifo不能開啟既讀又寫,有且僅可以由乙個。對fifo的寫操作總是將內容新增到末尾,讀操作總是從開頭返回資料。下面我們給出乙個無親緣關係的伺服器-客戶端示例子:

#define fifo1 "/tmp/fifo.1"

#define fifo2 "/tmp/fifl.2"

void server(int ,int );

int main(int argc, char *argv)

readfd = open(fifo1, o_rdonly, 0);

writefd = open(fifo2, o_wronly, 0);

server(readfd,writefd);

}

客戶端:

#define fifo1 "/tmp/fifo.1"

#define fifo2 "/tmp/fifl.2"

void server(int ,int );

int main(int argc, char *argv)

4. 額外屬性

a. open管道時,可以指定o_nonblock;或使用fcntl指定o_nonblock.

b. read時,管道中的資料小於read要求的資料時,只返回可用資料

c. write時,要寫入的資料小於等於pipe_buf,則保證寫操作是原子性的,否則不保證原子性

d. write時,如果管道為非阻塞,若寫入位元組大於管道可用位元組,則返回eagain(小於pipe_buf);若fifo中有乙個位元組的空間,則返回寫入的位元組數,如果滿,則返回eagain(大於pipe_buf);

e. 如果向乙個沒有為讀開啟的管道寫入,則會產生乙個sigpipe.預設為中止程序,若忽略該訊號,則write返回epipe.

d. read乙個沒有為寫開啟的管道時,read會返回0(檔案結束符)。當面對多客戶的情形時,一旦最後乙個客戶退出,就會返回檔案結束符,我們不得不關閉描述符然後重新開啟,等待下乙個讀開啟。在設計時,我們可以再伺服器程序中開啟乙個寫管道,這樣就可以保證管道的寫端永遠有乙個以上的寫開啟。

5. 位元組流

實際上,管道使用位元組流i/o模型,其不區分記錄邊界,解決的方法有三個:

a. 帶內特殊終止符:寫操作加入換行符,讀每次讀一行

b. 顯式長度:每個記錄前冠以它的長度

c. 每次連線乙個記錄:以連線斷開標誌為記錄結束標誌,需要為每個記錄建立連線

e. 我們還可以自己構建結構化的訊息,每個訊息乙個記錄,這樣通過讀寫結構化的訊息就可以了,這種方案示例如下:

#define maxmesdata (pipe_buf - 2 * sizeof(long))

#define mesghdrsize (sizeof(struct mymesg) - maxmesdata)

struct mymesg;

ssize_t mesg_send(int fd, struct mymesg *mptr)

ssize_t mesg_recv(int fd, struct mymesg *mptr)

使用管道時我們需要注意兩個限制:

open_max   程序最大開啟檔案描述符限制,sysconf可查

pipe_buf     可以原子化的讀寫乙個管道的最大資料量pathconf或fpathconf可查,和管道路徑相關。

Oracle 基本知識

乙個表空間只能屬於乙個資料庫 每個資料庫最少有乙個控制檔案 建議3個,分別放在不同的磁碟上 每個資料庫最少有乙個表空間 system表空間 建立system表空間的目的是盡量將目的相同的表存放在一起,以提高使用效率,只應存放資料字典 每個資料庫最少有兩個聯機日誌組,每組最少乙個聯機日誌檔案 乙個資料...

Oracle 基本知識

乙個表空間只能屬於乙個資料庫 每個資料庫最少有乙個控制檔案 建議3個,分別放在不同的磁碟上 每個資料庫最少有乙個表空間 system表空間 建立system表空間的目的是盡量將目的相同的表存放在一起,以提高使用效率 每個資料庫最少有兩個聯機日誌檔案 乙個資料檔案只能屬於乙個表空間 乙個資料檔案一旦被...

Oracle 基本知識

oracle 文章摘要 oracle 基本知識。正文 oracle 基本知識 乙個表空間只能屬於乙個資料庫 每個資料庫最少有乙個控制檔案 建議3個,分別放在不同的磁碟上 每個資料庫最少有乙個表空間 system表空間 建立system表空間的目的是盡量將目的相同的表存放在一起,以提高使用效率 每個資...