亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Linux服務器 > 正文

Linux通過匿名管道進行進程間通信

2024-09-05 23:04:34
字體:
供稿:網(wǎng)友

本文研究的主要是Linux通過匿名管道進行進程間通信的相關內(nèi)容,具體介紹如下。

在前面,介紹了一種進程間的通信方式:使用信號,我們創(chuàng)建通知事件,并通過它引起響應,但傳遞的信息只是一個信號值。這里將介紹另一種進程間通信的方式——匿名管道,通過它進程間可以交換更多有用的數(shù)據(jù)。

一、什么是管道

如果你使用過Linux的命令,那么對于管道這個名詞你一定不會感覺到陌生,因為我們通常通過符號“|"來使用管道,但是管理的真正定義是什么呢?管道是一個進程連接數(shù)據(jù)流到另一個進程的通道,它通常是用作把一個進程的輸出通過管道連接到另一個進程的輸入。

舉個例子,在shell中輸入命令:ls -l | grep string,我們知道ls命令(其實也是一個進程)會把當前目錄中的文件都列出來,但是它不會直接輸出,而是把本來要輸出到屏幕上的數(shù)據(jù)通過管道輸出到grep這個進程中,作為grep這個進程的輸入,然后這個進程對輸入的信息進行篩選,把存在string的信息的字符串(以行為單位)打印在屏幕上。

二、使用popen函數(shù)

1、popen函數(shù)和pclose函數(shù)介紹

有靜就有動,有開就有關,與此相同,與popen函數(shù)相對應的函數(shù)是pclose函數(shù),它們的原型如下:

#include <stdio.h> FILE* popen (const char *command, const char *open_mode); int pclose(FILE *stream_to_close); 

poen函數(shù)允許一個程序?qū)⒘硪粋€程序作為新進程來啟動,并可以傳遞數(shù)據(jù)給它或者通過它接收數(shù)據(jù)。command是要運行的程序名和相應的參數(shù)。open_mode只能是"r(只讀)"和"w(只寫)"的其中之一。注意,popen函數(shù)的返回值是一個FILE類型的指針,而Linux把一切都視為文件,也就是說我們可以使用stdio I/O庫中的文件處理函數(shù)來對其進行操作。

如果open_mode是"r",主調(diào)用程序就可以使用被調(diào)用程序的輸出,通過函數(shù)返回的FILE指針,就可以能過stdio函數(shù)(如fread)來讀取程序的輸出;如果open_mode是"w",主調(diào)用程序就可以向被調(diào)用程序發(fā)送數(shù)據(jù),即通過stdio函數(shù)(如fwrite)向被調(diào)用程序?qū)憯?shù)據(jù),而被調(diào)用程序就可以在自己的標準輸入中讀取這些數(shù)據(jù)。

pclose函數(shù)用于關閉由popen創(chuàng)建出的關聯(lián)文件流。pclose只在popen啟動的進程結(jié)束后才返回,如果調(diào)用pclose時被調(diào)用進程仍在運行,pclose調(diào)用將等待該進程結(jié)束。它返回關閉的文件流所在進程的退出碼。

2、例子

很多時候,我們根本就不知道輸出數(shù)據(jù)的長度,為了避免定義一個非常大的數(shù)組作為緩沖區(qū),我們可以以塊的方式來發(fā)送數(shù)據(jù),一次讀取一個塊的數(shù)據(jù)并發(fā)送一個塊的數(shù)據(jù),直到把所有的數(shù)據(jù)都發(fā)送完。下面的例子就是采用這種方式的數(shù)據(jù)讀取和發(fā)送方式。源文件名為popen.c,代碼如下:

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  int main() {   FILE *read_fp = NULL;   FILE *write_fp = NULL;   char buffer[BUFSIZ + 1];   int chars_read = 0;      //初始化緩沖區(qū)   memset(buffer, '/0', sizeof(buffer));   //打開ls和grep進程   read_fp = popen("ls -l", "r");   write_fp = popen("grep rwxrwxr-x", "w");   //兩個進程都打開成功   if(read_fp && write_fp)   {     //讀取一個數(shù)據(jù)塊     chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);     while(chars_read > 0)     {       buffer[chars_read] = '/0';       //把數(shù)據(jù)寫入grep進程       fwrite(buffer, sizeof(char), chars_read, write_fp);       //還有數(shù)據(jù)可讀,循環(huán)讀取數(shù)據(jù),直到讀完所有數(shù)據(jù)       chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);     }     //關閉文件流     pclose(read_fp);     pclose(write_fp);     exit(EXIT_SUCCESS);   }   exit(EXIT_FAILURE); } 

運行結(jié)果如下:

linux,進程間通信,管道,進程的管道通信,linux進程間通信管道,進程的管道通信實驗,基于管道的進程間通信

從運行結(jié)果來看,達到了信息篩選的目的。程序在進程ls中讀取數(shù)據(jù),再把數(shù)據(jù)發(fā)送到進程grep中進行篩選處理,相當于在shell中直接輸入命令:ls -l | grep rwxrwxr-x。

3、popen的實現(xiàn)方式及優(yōu)缺點

當請求popen調(diào)用運行一個程序時,它首先啟動shell,即系統(tǒng)中的sh命令,然后將command字符串作為一個參數(shù)傳遞給它。

這樣就帶來了一個優(yōu)點和一個缺點。優(yōu)點是:在Linux中所有的參數(shù)擴展都是由shell來完成的。所以在啟動程序(command中的命令程序)之前先啟動shell來分析命令字符串,也就可以使各種shell擴展(如通配符)在程序啟動之前就全部完成,這樣我們就可以通過popen啟動非常復雜的shell命令。

而它的缺點就是:對于每個popen調(diào)用,不僅要啟動一個被請求的程序,還要啟動一個shell,即每一個popen調(diào)用將啟動兩個進程,從效率和資源的角度看,popen函數(shù)的調(diào)用比正常方式要慢一些。

三、pipe調(diào)用

如果說popen是一個高級的函數(shù),pipe則是一個底層的調(diào)用。與popen函數(shù)不同的是,它在兩個進程之間傳遞數(shù)據(jù)不需要啟動一個shell來解釋請求命令,同時它還提供對讀寫數(shù)據(jù)的更多的控制。

pipe函數(shù)的原型如下:

#include <unistd.h> int pipe(int file_descriptor[2]); 

我們可以看到pipe函數(shù)的定義非常特別,該函數(shù)在數(shù)組中墻上兩個新的文件描述符后返回0,如果返回返回-1,并設置errno來說明失敗原因。

數(shù)組中的兩個文件描述符以一種特殊的方式連接起來,數(shù)據(jù)基于先進先出的原則,寫到file_descriptor[1]的所有數(shù)據(jù)都可以從file_descriptor[0]讀回來。由于數(shù)據(jù)基于先進先出的原則,所以讀取的數(shù)據(jù)和寫入的數(shù)據(jù)是一致的。

特別提醒:

1、從函數(shù)的原型我們可以看到,它跟popen函數(shù)的一個重大區(qū)別是,popen函數(shù)是基于文件流(FILE)工作的,而pipe是基于文件描述符工作的,所以在使用pipe后,數(shù)據(jù)必須要用底層的read和write調(diào)用來讀取和發(fā)送。

2、不要用file_descriptor[0]寫數(shù)據(jù),也不要用file_descriptor[1]讀數(shù)據(jù),其行為未定義的,但在有些系統(tǒng)上可能會返回-1表示調(diào)用失敗。數(shù)據(jù)只能從file_descriptor[0]中讀取,數(shù)據(jù)也只能寫入到file_descriptor[1],不能倒過來。

例子:

首先,我們在原先的進程中創(chuàng)建一個管道,然后再調(diào)用fork創(chuàng)建一個新的進程,最后通過管道在兩個進程之間傳遞數(shù)據(jù)。源文件名為pipe.c,代碼如下:

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  int main() {   int data_processed = 0;   int filedes[2];   const char data[] = "Hello pipe!";   char buffer[BUFSIZ + 1];   pid_t pid;   //清空緩沖區(qū)   memset(buffer, '/0', sizeof(buffer));    if(pipe(filedes) == 0)   {     //創(chuàng)建管道成功     //通過調(diào)用fork創(chuàng)建子進程     pid = fork();     if(pid == -1)     {       fprintf(stderr, "Fork failure");       exit(EXIT_FAILURE);     }     if(pid == 0)     {       //子進程中       //讀取數(shù)據(jù)       data_processed = read(filedes[0], buffer, BUFSIZ);       printf("Read %d bytes: %s/n", data_processed, buffer);       exit(EXIT_SUCCESS);     }     else     {       //父進程中       //寫數(shù)據(jù)       data_processed = write(filedes[1], data, strlen(data));       printf("Wrote %d bytes: %s/n", data_processed, data);       //休眠2秒,主要是為了等子進程先結(jié)束,這樣做也只是純粹為了輸出好看而已       //父進程其實沒有必要等等子進程結(jié)束       sleep(2);       exit(EXIT_SUCCESS);     }   }   exit(EXIT_FAILURE); } 

運行結(jié)果為:

linux,進程間通信,管道,進程的管道通信,linux進程間通信管道,進程的管道通信實驗,基于管道的進程間通信

可見,子進程讀取了父進程寫到filedes[1]中的數(shù)據(jù),如果在父進程中沒有sleep語句,父進程可能在子進程結(jié)束前結(jié)束,這樣你可能將看到兩個輸入之間有一個命令提示符分隔。

四、把管道用作標準輸入和標準輸出

下面來介紹一種用管道來連接兩個進程的更簡潔方法,我們可以把文件描述符設置為一個已知值,一般是標準輸入0或標準輸出1。這樣做最大的好處是可以調(diào)用標準程序,即那些不需要以文件描述符為參數(shù)的程序。

為了完成這個工作,我們還需要兩個函數(shù)的輔助,它們分別是dup函數(shù)或dup2函數(shù),它們的原型如下

#include <unistd.h> int dup(int file_descriptor); int dup2(int file_descriptor_one, int file_descriptor_two); 

dup調(diào)用創(chuàng)建一個新的文件描述符與作為它的參數(shù)的那個已有文件描述符指向同一個文件或管道。對于dup函數(shù)而言,新的文件描述總是取最小的可用值。而dup2所創(chuàng)建的新文件描述符或者與int file_descriptor_two相同,或者是第一個大于該參數(shù)的可用值。所以當我們首先關閉文件描述符0后調(diào)用dup,那么新的文件描述符將是數(shù)字0.

例子

在下面的例子中,首先打開管道,然后fork一個子進程,然后在子進程中,使標準輸入指向讀管道,然后關閉子進程中的讀管道和寫管道,只留下標準輸入,最后調(diào)用execlp函數(shù)來啟動一個新的進程od,但是od并不知道它的數(shù)據(jù)來源是管道還是終端。父進程則相對簡單,它首先關閉讀管道,然后在寫管道中寫入數(shù)據(jù),再關閉寫管道就完成了它的任務。源文件為pipe2.c,代碼如下:

#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h>  int main() {   int data_processed = 0;   int pipes[2];   const char data[] = "123";   pid_t pid;    if(pipe(pipes) == 0)   {     pid = fork();     if(pid == -1)     {       fprintf(stderr, "Fork failure!/n");       exit(EXIT_FAILURE);     }     if(pid == 0)     {       //子進程中       //使標準輸入指向fildes[0]       close(0);       dup(pipes[0]);       //關閉pipes[0]和pipes[1],只剩下標準輸入       close(pipes[0]);       close(pipes[1]);       //啟動新進程od       execlp("od", "od", "-c", 0);       exit(EXIT_FAILURE);     }     else     {       //關閉pipes[0],因為父進程不用讀取數(shù)據(jù)       close(pipes[0]);       data_processed = write(pipes[1], data, strlen(data));       //寫完數(shù)據(jù)后,關閉pipes[1]       close(pipes[1]);       printf("%d - Wrote %d bytes/n", getpid(), data_processed);     }   }   exit(EXIT_SUCCESS); } 

運行結(jié)果為:

linux,進程間通信,管道,進程的管道通信,linux進程間通信管道,進程的管道通信實驗,基于管道的進程間通信

從運行結(jié)果中可以看出od進程正確地完成了它的任務,與在shell中直接輸入od -c和123的效果一樣。

五、關于管道關閉后的讀操作的討論

現(xiàn)在有這樣一個問題,假如父進程向管道file_pipe[1]寫數(shù)據(jù),而子進程在管道file_pipe[0]中讀取數(shù)據(jù),當父進程沒有向file_pipe[1]寫數(shù)據(jù)時,子進程則沒有數(shù)據(jù)可讀,則子進程會發(fā)生什么呢?再者父進程把file_pipe[1]關閉了,子進程又會有什么反應呢?

當寫數(shù)據(jù)的管道沒有關閉,而又沒有數(shù)據(jù)可讀時,read調(diào)用通常會阻塞,但是當寫數(shù)據(jù)的管道關閉時,read調(diào)用將會返回0而不是阻塞。注意,這與讀取一個無效的文件描述符不同,read一個無效的文件描述符返回-1。

六、匿名管道的缺陷

看了這么多相信大家也知道它的一個缺點,就是通信的進程,它們的關系一定是父子進程的關系,這就使得它的使用受到了一點的限制,但是我們可以使用命名管道來解決這個問題。命名管道將在下一篇文章:Linux進程間通信——使用命名管道中介紹。

總結(jié)

以上就是本文關于Linux通過匿名管道進行進程間通信的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
欧美日韩亚洲系列| 欧洲精品乱码久久久久蜜桃| 青青青视频在线免费观看| 偷拍自拍在线视频| 美女少妇一区二区| 亚洲精品中文字幕乱码无线| 中文字幕理伦片免费看| 日本全棵写真视频在线观看| 中文字幕影片免费在线观看| 一区二区三视频| 91在线一区二区| 国产综合久久久久久久久久久久| 一区二区免费在线观看| 日韩精品一线二线三线| 日韩美女视频一区二区| 99视频在线视频| 日韩福利小视频| 中文日韩在线视频| 国产精品视频在线观看| 亚洲v在线观看| 成人黄色中文字幕| 日本少妇一区| 韩国成人在线| 成人区精品一区二区婷婷| 国产精品手机视频| 成年人网站免费视频| 91se在线观看| 色综合激情久久| 国产情侣呻吟对白高潮| 亚洲精品第一国产综合精品| 91精品国产一区二区在线观看| 亚洲视频福利| 国产精品美乳在线观看| 国产精品久久久影院| 欧美精品一区二区视频| 日韩视频免费在线| 国产sm在线观看| 666欧美在线视频| 婷婷免费在线视频| 久久国产精品波多野结衣| 国产丝袜精品第一页| 岛国在线免费| 伊人色在线视频| www.亚洲资源| 国产精品日日摸夜夜添夜夜av| 性欧美精品中出| 四色永久免费网站| 国产成人无码一区二区在线播放| 亚洲图片久久| 青青草国产一区二区三区| 中文字幕欧美日韩在线| 久久一区二区三区喷水| 国产毛片视频网站| 天堂√最新版中文在线| 日韩专区一区二区| 国产欧美一区二区视频| 亚洲午夜久久久久中文字幕| 久久日一线二线三线suv| 懂色av噜噜一区二区三区av| 成年人免费网站在线观看| 国产精品一区二区三区免费| 91精品国产色综合久久不卡98口| 中文字幕 日韩有码| 日韩亚洲欧美成人一区| 国产精品果冻传媒潘| 亚洲电影视频在线| 亚洲精品555| 91麻豆福利精品推荐| 一区二区三区视频免费视频观看网站| 国产精品蜜臀| 2025韩国大尺度电影| 欧美亚洲激情| 欧美精品成人91久久久久久久| 亚洲精品福利视频| 亚洲午夜av电影| 97人妻精品一区二区三区| 国产福利精品一区二区| 99riav1国产精品视频| 日韩aⅴ视频一区二区三区| 亚洲精品久久久久久久久久久| 三级全黄的视频在线观看| 成人黄色在线免费| 亚洲第一av网站| 奇米一区二区三区av| 四虎永久在线精品免费一区二区| 爱爱视频免费在线观看| 日韩欧美电影在线观看| 欧日韩一区二区三区| 不卡在线观看av| 久9久9色综合| 日日噜噜夜夜狠狠视频| 国产精品你懂得| 国产精品国产馆在线真实露脸| 成人性教育av免费网址| 欧美精品久久一区二区| 美洲天堂一区二卡三卡四卡视频| 亚洲一卡二卡三卡四卡五卡| 欧美黄片一区二区三区| 日本午夜精品理论片a级appf发布| 7777久久香蕉成人影院| 扒开腿狂躁女人爽出白浆2| 男女啪啪无遮挡| 四虎www4hu永久免费| 人妻丰满熟妇av无码久久洗澡| 欧美不卡视频一区发布| 色男人天堂av| 色欲AV无码精品一区二区久久| 国产av无码专区亚洲a∨毛片| 久热精品视频在线免费观看| 婷婷综合视频| 粗大黑人巨茎大战欧美成人| 盗摄牛牛av影视一区二区| 女人黄色片免费| 欧美日韩在线一二三| 久久久久久久人妻无码中文字幕爆| 一本色道久久综合亚洲精品婷婷| 日韩欧美国产中文字幕| 国产精品免费看久久久香蕉| 国产精品12p| xfplay5566色资源网站| 三级小说一区| 午夜精品久久| 99久久精品日本一区二区免费| 九色porny自拍视频| 黄色免费观看视频网站| 精品视频一区二区不卡| 大香煮伊手机一区| 天堂网www在线资源中文| 黄色亚洲在线| 69av在线播放| 欧美sm美女调教| 麻豆视频免费在线播放| 精品亚洲视频在线| 视色视频在线观看| 久久天堂电影| 欧美激情久久久| 久久视频国产精品免费视频在线| 色婷婷狠狠18| 丁香网亚洲国际| 午夜亚洲影视| 国产精品一区不卡| 成年人网站免费在线观看| 欧美成人精品在线视频| 亚洲国产欧美另类丝袜| 91精品天堂| 精品黑人一区二区三区在线观看| 在线日韩av永久免费观看| 红桃视频一区二区三区免费| 成年人网站91| 精品久久久久一区二区国产| 色播久久人人爽人人爽人人片视av| 欧美日韩一区二区在线观看视频| 在线欧美亚洲| 亚洲午夜激情视频| 少妇又色又爽又黄的视频| 成人免费福利在线| 嫩草影院在线观看未满十八| 欧美视频一区二区| 亚洲女人视频| 97国产suv精品一区二区62| 97看剧电视剧大全| 蜜桃传媒视频麻豆第一区免费观看| 人妻妺妺窝人体色www聚色窝| 久久中文字幕精品| 国产精品美女一区二区三区| 琪琪亚洲精品午夜在线| 色偷偷综合网| 日韩电影免费一区| 青青草原国产在线观看| 自拍视频在线播放| 大荫蒂性生交片| wwwjizzjizzcom| 免费高清在线| 中文字幕一区二区人妻电影| 亚洲精品日日夜夜| 国产欧美日韩综合一区在线观看| 国产精品白丝jk喷水视频一区| 美女视频第一区二区三区免费观看网站| 成人手机在线免费视频| 国产乱人伦真实精品视频| 日韩精品美女| 丰满少妇又爽又紧又丰满电影| 欧美成人中文| 两性午夜免费视频| 2019中文字幕在线视频| 一本一本久久a久久综合精品| youjizz.com日本| 亚洲美女在线免费观看| 伦理片一区二区| 日韩欧美aⅴ综合网站发布| 国产黄色91视频| 国产伦理吴梦梦伦理| 麻豆一区二区在线| 成a人片亚洲日本久久| 国产欧美日韩网站| 国产国产一区| 免费黄视频网站| 粉嫩老牛aⅴ一区二区三区| 精品一二三区视频| 欧美影院一区| 国产美女视频一区二区二三区| 精品国产视频一区二区三区| 日本在线观看视频网站| 日本一二区免费| 日韩电影免费在线| 午夜影视一区二区三区| 国产剧情日韩欧美| www.色综合.com| 日韩中文字幕亚洲一区二区va在线| 日韩亚洲欧美一区二区三区| 自拍亚洲国产| 欧美激情第3页| 色综合久久精品亚洲国产| 久久久久久免费观看| 欧美日韩国产不卡在线看| 欧美日韩视频在线播放| 一呦二呦三呦精品国产| 日韩一区二区三区免费观看| 嫩草嫩草嫩草嫩草| 8x海外华人永久免费日韩内陆视频| www亚洲成人| 在线天堂中文字幕| av成人免费观看| 黄色a级片免费| 在线观看国产精品一区| 欧美色网址大全| 日日草天天草| 一区二区高清视频| 免费在线观看一级片| 久久精品视频观看| 蜜桃视频在线观看免费视频网站www| 日本在线一区二区三区| 性xxxxfreexxxxx欧美丶| www.涩涩爱| 欧美日韩aaa| 久久av在线| 日韩在线观看成人| 热三久草你在线| 亚洲中文字幕无码一区二区三区| h网址在线观看| 一本久久a久久精品vr综合| 国产欧美亚洲一区| 岳张嘴把我的精子吞下去| 爱情岛论坛亚洲入口| 伊人伊人av电影| 国产精品日韩在线播放| 粗大的内捧猛烈进出在线视频| 中文字幕18页| 国产精品私人影院| 日韩一区二区麻豆国产| 中文子幕无线码一区tr| 成人免费网站在线| 一区二区三区四区国产精品| 在线观看国产一区二区| 色就是色欧美色图| 全彩无遮挡全彩口工漫画h#| 99热这里有精品| 草草视频在线一区二区| 成人啪啪18免费游戏链接| 日韩av色在线| 中文字幕第88页| www.视频在线.com| 男女视频在线观看网站| 亚洲激情中文字幕| 性视频1819p久久| 久久国产亚洲精品无码| 视频二区在线播放| 毛片在线播放视频| 欧美精品777| 久久精品国产一区二区三| 国产一区二区三区四区三区四| 电影亚洲一区| 麻豆传媒mv| jyzzz在线观看视频| 狠狠色成人综合网图片区| 成人精品视频.| 久久久久久**毛片大全| 亚洲午夜av| 免费在线观看黄色网| 欧美 亚洲 视频| 亚洲视频观看| 青娱乐国产精品视频| 国内精彩免费自拍视频在线观看网址| 国产精品久久久久久av| 免费黄色a网站| 一区二区欧美久久| 国产精品久久久久久久久久三级| 欧美日韩一级大片网址| 日本成人精品| 福利视频一区二区三区四区| 欧美最猛性xxxxxhd| 污污的视频免费| 国产亚洲一本大道中文在线| 青青草成人av| 亚洲国产高清在线| 亚洲午夜久久久久久尤物| 婷婷综合亚洲| 男人天堂av在线播放| 欧美亚洲视频在线看网址| av在线亚洲天堂| 精品国产亚洲一区二区三区在线观看| 岛国一区二区在线观看| 成人免费在线观看网站| 成人免费毛片日本片视频| 特色特色大片在线| 福利在线一区二区三区| 日韩精品极品毛片系列视频| 国产精品自拍av| 在线黄色国产电影| 欧美三级黄色大片| 国产精品免费在线免费| 国产污视频网站| 精品午夜久久福利影院| 中文字幕欧美国内| 四虎网站在线观看| 国产精品成人观看视频免费| 成人在线免费高清视频| 欧美无砖砖区免费| 超碰在线99| 国产视频一区二区在线| 一区二区三区短视频| 久久久久久国产精品久久| 日韩激情一区二区三区| 91爱视频在线| 中国视频免男男gay| 在线免费av播放| 另类小说视频一区二区| 欧美系列一区二区|