国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 經(jīng)典進(jìn)程間通信之無名管道和有名管道

經(jīng)典進(jìn)程間通信之無名管道和有名管道 時(shí)間:2018-09-26      來源:未知

眾所周知作為UNIX IPC中老的一種形式管道,是所有UNIX系統(tǒng)都提供的一種通信機(jī)制,因而它應(yīng)用的范圍非常廣泛。例如我們可以使用管道符“|”來連接進(jìn)程。在Linux系統(tǒng)中,由管道連接起來的進(jìn)程可以自動運(yùn)行,就如同在他們有一個數(shù)據(jù)流一樣。根據(jù)管道的適用范圍將其分為:無名管道(pipe)和有名管道(fifo)。本文主要圍繞二者出發(fā),討論管道通信的機(jī)制。

一、無名管道(pipe)

1.什么是管道

一個管道實(shí)際上就是個只存在于內(nèi)存中的文件,對這個文件的操作要通過兩個已經(jīng)打開文件進(jìn)行,它們分別代表管道的兩端。管道是一種特殊的文件,它不屬于某一種文件系統(tǒng),而是一種獨(dú)立的文件系統(tǒng),有其自己的數(shù)據(jù)結(jié)構(gòu)。類似時(shí)空隧道的概念,建立兩個進(jìn)程之間的通訊橋梁。數(shù)據(jù)的讀出和寫入:一個進(jìn)程向管道中寫的內(nèi)容被管道另一端的進(jìn)程讀出。寫入的內(nèi)容每次都添加在管道緩沖區(qū)的末尾,并且每次都是從緩沖區(qū)的頭部讀出數(shù)據(jù)。

2.無名管道的特性

(1)只能用于具有親緣關(guān)系的進(jìn)程之間的通信,通常一個管道由一個進(jìn)程創(chuàng)建,然后該進(jìn)程調(diào)用fork,此后父子進(jìn)程之間就可以通過管道通信。

(2)半雙工的通信模式,具有固定的讀端和寫端:傳輸方向同時(shí)只能是一個方向,。

(3)管道可以看成是一種特殊的文件,對于它的讀寫可以使用文件IO如read、write函數(shù):但是在文件系統(tǒng)里并不存在pipe對應(yīng)的文件而且不支持如lseek() 操作。

3.無名管道的創(chuàng)建

無名管道可以由pipe()函數(shù)創(chuàng)建

#include

int pipe(int pipefd[2]);

pipe函數(shù)調(diào)用成功返回0,調(diào)用失敗返回-1。

調(diào)用pipe函數(shù)時(shí)在內(nèi)核中開辟一塊緩沖區(qū)(稱為管道)用于通信,它有一個讀端一個寫端,然后通過pipefd參數(shù)傳出給用戶程序兩個文件描述符,pipefd[0]指向管道的讀端,pipefd[1]指向管道的寫端(很好記,就像0是標(biāo)準(zhǔn)輸入1是標(biāo)準(zhǔn)輸出一樣)。所以管道在用戶程序看起來就像一個打開的文件,通過read(pipefd[0]);或者write(pipefd[1]);向這個文件讀寫數(shù)據(jù)其實(shí)是在讀寫內(nèi)核緩沖區(qū)。

詳細(xì)的創(chuàng)建流程:

step1: 父進(jìn)程創(chuàng)建一個pipe,其中fd[0]固定用于讀管道,而fd[1]固定用于寫管道。

Step2:父進(jìn)程fork,子進(jìn)程繼承了父進(jìn)程的管道

Step3:之后取決于我們想要的數(shù)據(jù)流方向來關(guān)閉相應(yīng)的端。

4.無名管道讀寫注意事項(xiàng)

當(dāng)管道的一端被關(guān)閉后:

(1)當(dāng)讀一個寫端已被關(guān)閉的管道時(shí),在所有數(shù)據(jù)都被讀取后, read返回0,以指示達(dá)到了文件結(jié)束處(從技術(shù)方面考慮,管道的寫端還有進(jìn)程時(shí),就不會產(chǎn)生文件的結(jié)束?梢詮(fù)制一個管道的描述符,使得有多個進(jìn)程具有寫打開文件描述符。但是,通常一個管道只有一個讀進(jìn)程,一個寫進(jìn)程)。

(2)如果寫一個讀端已被關(guān)閉的管道,則產(chǎn)生信號SIGPIPE。如果忽略該信號或者捕捉該信號并從其處理程序返回,則write出錯返回,errn設(shè)置為EPIPE。在寫管道時(shí),常數(shù)PIPE_BUF規(guī)定了內(nèi)核中管道緩存器的大小。如果對管道進(jìn)行write調(diào)用,而且要求寫的字節(jié)數(shù)小于等于PIPE_BUF,則此操作不會與其他進(jìn)程對同一管道(或FIFO)的write相交錯。但是,若有多個進(jìn)程同時(shí)寫一個管道(或FIFO),而且某個或某些進(jìn)程要求寫的字節(jié)數(shù)超過PIPE_BUF字節(jié)數(shù),則數(shù)據(jù)可能會與其他寫操作的數(shù)據(jù)相交錯。

5.popen和pclose函數(shù)

因?yàn)槌R姷牟僮魇莿?chuàng)建一個連接到另一個進(jìn)程的管道,然后讀其輸出或向其發(fā)送輸入,所以標(biāo)準(zhǔn)I / O庫為實(shí)現(xiàn)這些操作提供了兩個函數(shù)popen和pclose。在這邊就不詳細(xì)說明了,大家感興趣的化可以查看Man手冊中的描述。

6.示例代碼

#include

#include

#include

int pid1, pid2;

int main( )

{

int fd[2];

char outpipe[100], inpipe[100];

pipe(fd); /*創(chuàng)建一個管道*/

while ((pid1 = fork( )) == -1);

if (pid1 == 0)

{

sprintf(outpipe, "child 1 process is sending message!");

/*把串放入數(shù)組outpipe中*/

write(fd[1], outpipe, 50); /*向管道寫長為50字節(jié)的串*/

exit(0);

}

else

{

while((pid2 = fork( )) == -1);

if (pid2 == 0)

{

sprintf(outpipe, "child 2 process is sending message!");

write(fd[1], outpipe, 50);

exit(0);

}

else

{

//wait(NULL); /*同步*/

read(fd[0], inpipe, 50); /*從管道中讀長為50字節(jié)的串*/

printf("%s\n", inpipe);

//wait(NULL);

read(fd[0], inpipe, 50);

printf("%s\n",inpipe);

exit(0);

}

}

return 0;

}

二、有名管道(fifo)

1.有名管道的概念

為何要提出有名管道的說法,目的是為了克服無名管道的不足之處:

(1)無名管道只能用于具有親緣關(guān)系的進(jìn)程之間,這就限制了無名管道的使用范圍

(2)有名管道可以使互不相關(guān)的兩個進(jìn)程互相通信。有名管道可以通過路徑名來指出,并且在文件系統(tǒng)中可見

為了這種有名管道,Linux中專門設(shè)立了一個專門的特殊文件系統(tǒng)--管道文件,以FIFO的文件形式存在于文件系統(tǒng)中,這樣,即使與FIFO的創(chuàng)建進(jìn)程不存在親緣關(guān)系的進(jìn)程,只要可以訪問該路徑,就能夠彼此通過FIFO相互通信,因此,通過FIFO不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。但在磁盤上只是一個節(jié)點(diǎn),而文件的數(shù)據(jù)則只存在于內(nèi)存緩沖頁面中,與普通管道一樣。

2.有名管道的創(chuàng)建

(1)有名管道可以從命令行上創(chuàng)建,命令行方法是使用下面這個命令:

$ mkfifo myfifo

(2)有名管道也可以從程序里創(chuàng)建,相關(guān)API有:

#include

#include

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

mkfifo函數(shù)成功返回0,失敗返回-1并且設(shè)置errno。

該函數(shù)的第一個參數(shù)是一個普通的路徑名,也就是創(chuàng)建后FIFO的名字。第二個參數(shù)與打開普通文件的open()函數(shù)中的mode參數(shù)相同。如果mkfifo的一個參數(shù)是一個已經(jīng)存在路徑名時(shí),會返回EEXIST錯誤,所以一般典型的調(diào)用代碼首先會檢查是否返回該錯誤,如果確實(shí)返回該錯誤,那么只要調(diào)用打開FIFO的函數(shù)open就可以了。

3.FIFO的open打開規(guī)則

O_RDONLY、O_WRONLY和O_NONBLOCK標(biāo)志共有四種合法的組合方式:

flags=O_RDONLY:open將會調(diào)用阻塞,除非有另外一個進(jìn)程以寫的方式打開同一個FIFO,否則一直等待。

flags=O_WRONLY:open將會調(diào)用阻塞,除非有另外一個進(jìn)程以讀的方式打開同一個FIFO,否則一直等待。

flags=O_RDONLY|O_NONBLOCK:如果此時(shí)沒有其他進(jìn)程以寫的方式打開FIFO,此時(shí)open也會成功返回,此時(shí)FIFO被讀打開,而不會返回錯誤。

flags=O_WRONLY|O_NONBLOCK:立即返回,如果此時(shí)沒有其他進(jìn)程以讀的方式打開,open會失敗打開,此時(shí)FIFO沒有被打開,返回-1。

總而言之:

● 在一個FIFO上打開一個讀端

● 在一個FIFO上打開一個寫端

4.有名管道的讀寫規(guī)則

有名管道的讀寫原則和無名管道的讀寫原則基本一致,主要參考無名管道的讀寫原則即可。

5.示例代碼

使用完成拷貝文件的功能:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ERR_EXIT(m)

do {

perror(m);

exit(EXIT_FAILURE);

} while(0)

int main(int argc, char *argv[])

{

mkfifo("tp", 0644);

int infd = open("Makefile", O_RDONLY);

if (infd == -1)

ERR_EXIT("open error");

int outfd;

outfd = open("tp", O_WRONLY);

if (outfd == -1)

ERR_EXIT("open error");

char buf[1024];

int n;

while ((n = read(infd, buf, 1024)) > 0)

write(outfd, buf, n);

close(infd);

close(outfd);

return 0;

}

三、無名管道與有名管道的區(qū)別與聯(lián)系

1.PIPE和FIFO的區(qū)別:

對于FIFO和無名管道的編碼區(qū)別:

(1)創(chuàng)建并打開一個管道只需調(diào)用pipe。創(chuàng)建并打開一個FIFO則需在調(diào)用mkfifo后再調(diào)用open。

(2)管道在所有進(jìn)程終都關(guān)閉它之后自動消失。FIFO的名字則只有通過調(diào)用unlink才文件系統(tǒng)刪除。

FIFO需要額外調(diào)用的好處是:FIFO在文件系統(tǒng)中有一個名字,該名字允許某個進(jìn)程創(chuàng)建個FIFO,與它無親緣關(guān)系的另一個進(jìn)程來打開這個FIFO。對于管道來說,這是不可能的。

系統(tǒng)規(guī)定 :如果寫入的數(shù)據(jù)長度小于等于PIPE_BUF字節(jié),那么或者寫入全部字節(jié),要么一個字節(jié)都不寫入。

在非阻塞的write調(diào)用情況下,如果FIFO 不能接收所有寫入的數(shù)據(jù),將按照下面的規(guī)則進(jìn)行:

(1)請求寫入的數(shù)據(jù)的長度大于PIPE_BUF字節(jié),調(diào)用失敗,數(shù)據(jù)不能被寫入。

(2)請求寫入的數(shù)據(jù)的長度小于PIPE_BUF字節(jié),將寫入部分?jǐn)?shù)據(jù),返回實(shí)際寫入的字節(jié)數(shù),返回值也可能是0。

其中。PIPE_BUF是FIFO的長度,它在頭文件limits.h中被定義。在linux或其他類UNIX系統(tǒng)中,它的值通常是4096字節(jié)。注意:PIPE_BUF與FIFO容量是有區(qū)別的,PIPE_BUF表示可原子的寫往一個管道或FIFO的大數(shù)據(jù)量。PIPE_BUF為4096,但是FIFO的容量為65536.

2.PIPE和FIFO的相同點(diǎn):

(1)雖然管道,特別是有名管道可以很方便地在雙向上打開讀寫,但其內(nèi)核實(shí)現(xiàn)依然是單向的。嚴(yán)格遵循先進(jìn)先出(first in first out),對管道及FIFO的讀總是從開始處返回?cái)?shù)據(jù),對它們的寫則把數(shù)據(jù)添加到末尾。

(2)pipe, fifo都不支持諸如lseek()等文件定位操作。

(3)對于pipe或者fifo,如果在讀端或者寫端打開了多個讀寫端(進(jìn)程),之間的讀寫是不確定的,需要通過其他的同步機(jī)制實(shí)現(xiàn)多進(jìn)程通訊的同步。

上一篇:Linux下動態(tài)庫和靜態(tài)庫的制作及使用

下一篇:Android導(dǎo)入第三方靜態(tài)庫.a編譯成動態(tài)庫.so

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號-5,京公海網(wǎng)安備11010802025203號

回到頂部