色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > 經典進程間通信之無名管道和有名管道

經典進程間通信之無名管道和有名管道 時間:2018-09-26      來源:未知

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

一、無名管道(pipe)

1.什么是管道

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

2.無名管道的特性

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

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

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

3.無名管道的創建

無名管道可以由pipe()函數創建

#include

int pipe(int pipefd[2]);

pipe函數調用成功返回0,調用失敗返回-1。

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

詳細的創建流程:

step1: 父進程創建一個pipe,其中fd[0]固定用于讀管道,而fd[1]固定用于寫管道。

Step2:父進程fork,子進程繼承了父進程的管道

Step3:之后取決于我們想要的數據流方向來關閉相應的端。

4.無名管道讀寫注意事項

當管道的一端被關閉后:

(1)當讀一個寫端已被關閉的管道時,在所有數據都被讀取后, read返回0,以指示達到了文件結束處(從技術方面考慮,管道的寫端還有進程時,就不會產生文件的結束。可以復制一個管道的描述符,使得有多個進程具有寫打開文件描述符。但是,通常一個管道只有一個讀進程,一個寫進程)。

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

5.popen和pclose函數

因為常見的操作是創建一個連接到另一個進程的管道,然后讀其輸出或向其發送輸入,所以標準I / O庫為實現這些操作提供了兩個函數popen和pclose。在這邊就不詳細說明了,大家感興趣的化可以查看Man手冊中的描述。

6.示例代碼

#include

#include

#include

int pid1, pid2;

int main( )

{

int fd[2];

char outpipe[100], inpipe[100];

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

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

if (pid1 == 0)

{

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

/*把串放入數組outpipe中*/

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

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字節的串*/

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

//wait(NULL);

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

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

exit(0);

}

}

return 0;

}

二、有名管道(fifo)

1.有名管道的概念

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

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

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

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

2.有名管道的創建

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

$ mkfifo myfifo

(2)有名管道也可以從程序里創建,相關API有:

#include

#include

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

mkfifo函數成功返回0,失敗返回-1并且設置errno。

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

3.FIFO的open打開規則

O_RDONLY、O_WRONLY和O_NONBLOCK標志共有四種合法的組合方式:

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

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

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

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

總而言之:

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

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

4.有名管道的讀寫規則

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

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;

}

三、無名管道與有名管道的區別與聯系

1.PIPE和FIFO的區別:

對于FIFO和無名管道的編碼區別:

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

(2)管道在所有進程終都關閉它之后自動消失。FIFO的名字則只有通過調用unlink才文件系統刪除。

FIFO需要額外調用的好處是:FIFO在文件系統中有一個名字,該名字允許某個進程創建個FIFO,與它無親緣關系的另一個進程來打開這個FIFO。對于管道來說,這是不可能的。

系統規定 :如果寫入的數據長度小于等于PIPE_BUF字節,那么或者寫入全部字節,要么一個字節都不寫入。

在非阻塞的write調用情況下,如果FIFO 不能接收所有寫入的數據,將按照下面的規則進行:

(1)請求寫入的數據的長度大于PIPE_BUF字節,調用失敗,數據不能被寫入。

(2)請求寫入的數據的長度小于PIPE_BUF字節,將寫入部分數據,返回實際寫入的字節數,返回值也可能是0。

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

2.PIPE和FIFO的相同點:

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

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

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

上一篇:Linux下動態庫和靜態庫的制作及使用

下一篇:Android導入第三方靜態庫.a編譯成動態庫.so

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 2020亚洲午夜无码天堂 | 丰满老熟好大bbbxxx | 欧美xxxxx在线观看 | 欧美人成片免费观看视频 | 国产人妖视频一区二区 | 日本免费一二三区中文 | 国产精品最新精品网页 | 男人大臿蕉香蕉大视频 | 2018av天堂在线视频精品观看 | 蜜臀免费av | 美女内射无套日韩免费播放 | 国产尤物AV尤物在线看 | 国产微拍精品一区二区 | 三年片观看免费观看大全 | 亚洲国产成人精品无码区在线网站 | 毛色毛片免费观看 | 国产午夜亚洲精品不卡在线观看 | 酒店大战丝袜高跟鞋人妻 | 亚洲精品一区国产精品丝瓜 | 国产精品白丝AV网站 | 国产美女视频国产视视频 | 揉着我的奶从后面进去视频 | 久久久无码中文字幕久... | 国产在线拍91揄自揄视精品91 | 色吊丝中文字幕 | 一夲道DVD高清无码 老司机精品视频一区二区 美女脱得一二净(无内裤)视频 | 日本免费一区二区三区在线播放 | 天天躁日日躁狠狠躁一区 | 初高中生啪啪网站汐汐最迷人 | 亚洲va天堂va欧美ⅴ | 亚洲成av人片在线观看无码不卡 | 日本精品AⅤ一区二区三区 久久久国产精品免费A片 | 精品少妇人妻AV免费久久洗澡 | 被黑人猛躁10次高潮视频 | 亚洲日本VA午夜中文字幕一区 | 日韩精品无码一区二区 | 亚洲AV无码成人精品区在线观看 | 国产在线观看免费视频在线 | 国产乱视频网站 | 亚洲aⅴ在线无码播放 | 国产精品无码AV一区二区三区 |