當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > IPC機(jī)制之管道
每個(gè)進(jìn)程各自有不同的用戶地址空間,任何一個(gè)進(jìn)程的全局變量在另一個(gè)進(jìn)程中都看不到,所以進(jìn)程之間要交換數(shù)據(jù)必須通過(guò)內(nèi)核,在內(nèi)核中開(kāi)辟一塊緩沖區(qū),進(jìn)程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進(jìn)程2再?gòu)膬?nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機(jī)制稱為進(jìn)程間通信(IPC,InterProcess Communication)。
管道是一種最基本的IPC機(jī)制,由pipe函數(shù)創(chuàng)建:
int pipe(int filedes[2]);
調(diào)用pipe函數(shù)時(shí)在內(nèi)核中開(kāi)辟一塊緩沖區(qū)(稱為管道)用于通信,它有一個(gè)讀端一個(gè)寫(xiě)端,然后通過(guò)filedes參數(shù)傳出給用戶程序兩個(gè)文件描述符,filedes[0]指向管道的讀端,filedes[1]指向管道的寫(xiě)端(很好記,就像0是標(biāo)準(zhǔn)輸入1是標(biāo)準(zhǔn)輸出一樣)。所以管道在用戶程序看起來(lái)就像一個(gè)打開(kāi)的文件,通過(guò)read(filedes[0]);或者write(filedes[1]);向這個(gè)文件讀寫(xiě)數(shù)據(jù)其實(shí)是在讀寫(xiě)內(nèi)核緩沖區(qū)。pipe函數(shù)調(diào)用成功返回0,調(diào)用失敗返回-1。
管道具體的劃分為兩種:命令管道與匿名管道
1.命名管道(FIFO)
匿名管道應(yīng)用的一個(gè)限制就是只能在具有共同祖先(具有親緣關(guān)系)的進(jìn)程間通信。
如果我們想在不相關(guān)的進(jìn)程之間交換數(shù)據(jù),可以使用FIFO文件來(lái)做這項(xiàng)工作,它經(jīng)常被稱為命名管道。
命名管道可以從命令行上創(chuàng)建,命令行方法是使用下面這個(gè)命令:
$ mkfifo filename
命名管道也可以從程序里創(chuàng)建,相關(guān)函數(shù)有:
int mkfifo(const char *filename,mode_t mode);
2.匿名管道
匿名管道由pipe函數(shù)創(chuàng)建并打開(kāi)。
命名管道由mkfifo函數(shù)創(chuàng)建,打開(kāi)用open。
FIFO(命名管道)與pipe(匿名管道)之間唯一的區(qū)別在它們創(chuàng)建與打開(kāi)的方式不同,這些工作完成之后,它們具有相同的語(yǔ)義。
3.命名管道的打開(kāi)規(guī)則
如果當(dāng)前打開(kāi)操作是為讀而打開(kāi)FIFO時(shí)
O_NONBLOCK disable:阻塞直到有相應(yīng)進(jìn)程為寫(xiě)而打開(kāi)該FIFO
O_NONBLOCK enable:立刻返回成功
如果當(dāng)前打開(kāi)操作是為寫(xiě)而打開(kāi)FIFO時(shí)
O_NONBLOCK disable:阻塞直到有相應(yīng)進(jìn)程為讀而打開(kāi)該FIFO
O_NONBLOCK enable:立刻返回失敗,錯(cuò)誤碼為ENXIO
需要注意的是打開(kāi)的文件描述符默認(rèn)是阻塞的,大家可以寫(xiě)兩個(gè)很簡(jiǎn)單的小程序測(cè)試一下,主要也就一條語(yǔ)句
int fd = open("p2", O_WRONLY); 假設(shè)p2是命名管道文件,把打開(kāi)標(biāo)志換成 O_RDONLY 就是另一個(gè)程序了,可以先運(yùn)行RD程序,此時(shí)會(huì)阻塞,再在另一個(gè)窗口運(yùn)行WR程序,此時(shí)兩個(gè)程序都會(huì)從open返回成功。非阻塞時(shí)也不難測(cè)試,open時(shí)增加標(biāo)志位就可以了。