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