国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

Linux兩種管道通信方式的分析

2023-09-06 05:43鄧飛蔡波
現(xiàn)代信息科技 2023年14期

鄧飛 蔡波

摘 ?要:Linux系統(tǒng)中管道通信是從Unix系統(tǒng)繼承的一種通信方式,管道是操作系統(tǒng)內(nèi)核管理的一個內(nèi)存緩沖區(qū),采用半雙工的通信方式。由于管道是臨界資源,所以進程要互斥地訪問管道,管道分為無名管道和命名管道。文章分析了Linux進程之間采用無名管道和命名管道通信的特點,并對無名管道的父子進程、兄弟進程以及命名管道通信進行了研究對比。

關(guān)鍵詞:進程通信;臨界資源;無名管道;命名管道

中圖分類號:TP311 ? ? 文獻標(biāo)識碼:A ? 文章編號:2096-4706(2023)14-0054-03

Analysis of Two Pipe Communication Ways of Linux

DENG Fei, CAI Bo

(Chengdu Colledge of University of Electronic Science and Technology of China, Chengdu ?611731, China)

Abstract: Pipe communication in Linux system is a communication mode inherited from Unix system. The pipe is a memory buffer managed by the operating system kernel, and it adopts half-duplex communication mode. Because pipe is a critical resource, process should access the pipe file mutually exclusive. Pipes are divided into anonymous pipe and named pipe. This paper analyzes the characteristics of pipe communication mainly adopts the anonymous pipe and named pipe between Linux Processes. The research and comparison of the parent-child process, sibling process and the anonymous pipe and named pipe communication is carried out.

Keywords: process communication; critical resource; anonymous pipe; named pipe

0 ?引 ?言

Linux管道是由操作系統(tǒng)內(nèi)核管理的一個內(nèi)存緩沖區(qū),該緩沖區(qū)以循環(huán)隊列結(jié)構(gòu)采用先進先出方式的傳輸數(shù)據(jù),即管道采用某一方向的方式傳輸數(shù)據(jù),一個進程連接管道輸入端,該進程會向管道末端寫入數(shù)據(jù);另一個進程連接管道的輸出端,該進程會讀取被放入管道的數(shù)據(jù);而且管道中的數(shù)據(jù)只能被讀取一次,即不能重復(fù)讀取[1],數(shù)據(jù)所占用空間被讀走數(shù)據(jù)以便下次留給寫進程寫入數(shù)據(jù)。由于管道在進程通信過程中數(shù)據(jù)被存放在內(nèi)存緩沖區(qū),緩沖區(qū)是臨界資源,所以為了保證讀寫進程對緩沖區(qū)里數(shù)據(jù)正確訪問,對管道需要互斥訪問[2]。雖然管道并不能像普通磁盤文件存放數(shù)據(jù),但可以被看成特殊的文件,也可以使用讀、寫、關(guān)閉等系統(tǒng)函數(shù)訪問管道[3]。Linux管道分為無名管道和命名管道兩種。本文主要圍繞Linux無名管道的父子進程、兄弟進程通信以及命名管道通信特點進行研究對比。

1 ?無名管道通信機制

無名管道并不是真正的外存磁盤文件,實際為系統(tǒng)內(nèi)核緩沖區(qū)。具有血緣關(guān)系的兩個進程只能使用無名管道通信,指具有一個共同祖先的兩個進程之間才能利用無名管道通信,所以無名管道可以應(yīng)用在父子、兄弟進程之間的通信[4]。

由于無名管道沒有文件名,所以無名管道是通過文件描述符方式控制讀寫端來實現(xiàn)通信,當(dāng)進程新建管道時,系統(tǒng)會給調(diào)用pipe函數(shù)的進程分配文件描述符fd [0]和fd [1],一般情況下從管道讀取數(shù)據(jù)使用fd [0]端,而往管道寫入數(shù)據(jù)使用fd[1]端[5],這樣就形成了一條半雙工的擁有固定的讀端和寫端數(shù)據(jù)傳輸通道。

在實際使用無名管道通信時,系統(tǒng)給新建管道的進程返回文件描述符fd[0]和fd[1],接著新建子孫進程,子孫進程會繼承文件描述符fd[0]和fd[1],這些有血緣關(guān)系的進程都有自己的讀寫端,這樣便可以實現(xiàn)它們共享該管道[6],為了實現(xiàn)它們中任意兩個進程通信就需要保留相應(yīng)的讀、寫端,將多余的讀、寫端對應(yīng)的文件描述符關(guān)閉就可以了。

下面分別對父子、兄弟進程的無名管道通信進行分析。

1.1 ?父子進程之間的管道通信分析

一般情況在利用無名管道通信的父子進程之間建立起一條“子進程寫入父進程讀取”的通道,如圖1所示。父進程調(diào)用pipe()函數(shù)新建管道,系統(tǒng)給父進程指定文件描述符fd[0]和fd[1],接著創(chuàng)建子進程,子進程會繼承父進程的文件描述符fd[0]和fd[1],父子進程共享該管道;子進程保留文件描述符fd[1]向管道寫入數(shù)據(jù)而關(guān)閉自己的讀取端fd[0],而父進程保留文件描述符fd[0]從管道讀取數(shù)據(jù)而關(guān)閉自己的寫入端fd[1],這樣就建立了一條通信通道。

圖1 ?父子進程之間管道通信示意圖

父進程調(diào)用fork()創(chuàng)建子進程,父進程保留讀端fd[0],子進程保留寫端fd[1],其余讀寫端口關(guān)閉。子進程調(diào)用函數(shù)write(fd[1], s, strlen((const char*)s))將s指向的內(nèi)存數(shù)據(jù)寫入管道,fd[1]為子進程的寫入端;父進程調(diào)用函數(shù)read(fd[0],buf,size)從管道讀走數(shù)據(jù),fd[0]為父進程的讀端;size為管道對應(yīng)的內(nèi)核緩沖區(qū)大小。下面為通信父、子進程的部分代碼:

(1)/*子進程的部分代碼*/

{ /* 子進程關(guān)閉讀描述符*/

close(fd[0]);

/*子進程向管道寫入real_write字節(jié)數(shù)據(jù) */

real_write = write(fd[1], s, strlen((const char*)s)))

/* 完成所有寫任務(wù)后關(guān)閉寫端 */

close(fd[1]); }

(2)/*父進程的部分代碼*/

{ /*父進程關(guān)閉寫端*/

close(fd[1]);

/*父進程從管道中讀走real_read字節(jié)的數(shù)據(jù)*/

real_read = read(fd[0], buf, size);

/*完成所有讀任務(wù)后關(guān)閉讀取端*/

close(fd[0]); }

1.2 ?兄弟進程之間的管道通信分析

由于無名管道應(yīng)用在有血緣關(guān)系的進程之間通信,所以無名管道也能在兄弟進程之間實現(xiàn)通信。兄弟進程利用管道通信如圖2所示,父進程調(diào)用pipe()函數(shù)新建管道,系統(tǒng)給父進程指定文件描述符fd[0]和fd[1],接著由父進程新建子進程A、B,兩個子進程A、B都繼承父進程的文件描述符fd[0]、fd[1],這樣父進程和子進程A、B三個進程共享無名管道,即三個進程的文件描述符fd[0]、fd[1]分別和管道兩端相連接。

圖2 ?兄弟進程之間管道通信示意圖

父進程調(diào)用fork()創(chuàng)建子進程A、B,子進程A保留寫端fd[1],子進程B保留讀端fd[0],其余讀寫端口關(guān)閉,父進程的讀寫端都關(guān)閉,這樣形成“子進程A寫入,子進程B讀走數(shù)據(jù)”的通信通道。子進程A調(diào)用函數(shù)write(fd[1], s, strlen((const char*)s))將s指向的內(nèi)存數(shù)據(jù)寫入管道,fd[1]為子進程A的寫入端;子進程B調(diào)用函數(shù)read(fd[0], buf, size)從管道讀走數(shù)據(jù),fd[0]為子進程B的讀端;size為管道緩沖區(qū)大小。下面為通信子進程A、B的部分代碼:

(1)/*子進程A的部分代碼*/

{ /* 子進程A關(guān)閉讀描述符*/

close(fd[0]);

/* 子進程A向管道寫入real_write字節(jié)數(shù)據(jù) */

real_write = write(fd[1], s, strlen((const char*)s)))

/* 子進程A完成所有寫任務(wù)后關(guān)閉寫端 */

close(fd[1]); }

(2)/*子進程B的部分代碼*/

{ /*子進程B關(guān)閉寫端*/

close(pipe_fd[1]);

/* 子進程B向從管道讀走real_read字節(jié)數(shù)據(jù) */

real_read = read(fd[0], buf, size);

/* 完成所有讀任務(wù)后關(guān)閉讀端 */

close(pipe_fd[0]); }

2 ?命名管道通信分析

只是無名管道才能實現(xiàn)血緣關(guān)系的進程通信,為了實現(xiàn)無血緣進程通信而提出命名管道。命名管道雖然在外存磁盤上有文件標(biāo)識,但是利用命名管道通信的兩個進程傳輸?shù)臄?shù)據(jù)并不會存放在磁盤文件中,而是存放在內(nèi)存緩沖區(qū),命名管道對應(yīng)外存磁盤上的具體路徑下文件,如圖3所示,/home/FIFO表示在路徑/home下的命名管道文件FIFO。

圖3 ?命名管道通信示意圖

命名管道/home/FIFO被創(chuàng)建后,利用命名管道通信的兩個進程就可以將命名管道FIFO看成一個磁盤文件來訪問,這樣傳輸數(shù)據(jù)時會調(diào)用函數(shù)open()、read()和write()和close()等來訪問命名管道。由于命名管道采用隊列先進先出方式來處理數(shù)據(jù),只能單向傳送,所以對命名管道實現(xiàn)寫功能時將數(shù)據(jù)添加到管道尾部,實現(xiàn)讀功能時從命名管道首部讀取數(shù)據(jù)。

讀、寫進程訪問命名管道FIFO有阻塞和非阻塞兩種方式:

1)采用阻塞方式訪問命名管道時,對于寫進程,在讀進程讀完管道里數(shù)據(jù)之前寫進程會一直阻塞;而對于讀進程,命名管道FIFO中沒有數(shù)據(jù)或?qū)戇M程沒有完成寫操作之前讀進程會一直阻塞;

2)采用非阻塞方式訪問命名管道時,對于寫進程,在讀進程讀完管道里數(shù)據(jù)之前,寫操作只能部分?jǐn)?shù)據(jù)寫入管道或?qū)懖僮魇。粚τ谧x進程而言,無論管道FIFO有無數(shù)據(jù)時都會執(zhí)行讀操作,只是當(dāng)管道FIFO中沒有數(shù)據(jù)時讀操作結(jié)果返回0而已。

由于管道為臨界資源,為了實現(xiàn)互斥訪問命名管道,保證數(shù)據(jù)能正確傳輸,常常對命名管道實現(xiàn)讀、寫操作時采用阻塞方式[6]。

以上面圖4里創(chuàng)建的命名管道/home/FIFO為例,讀、寫進程采用阻塞方式打開管道,寫進程調(diào)用函數(shù)write (fd,buf,size)把寫進程緩沖區(qū)的數(shù)據(jù)寫入管道,讀進程調(diào)用函數(shù)read(fd,buf,size)從管道讀取數(shù)據(jù)到讀進程緩沖區(qū),size為管道緩沖區(qū)大小,fd指向命名管道/home/FIFO。

1)寫進程以只寫阻塞方式打開/home/FIFO管道:fd = open(/home/FIFO,O_WRONLY);

向管道中寫入nwrite字節(jié)數(shù)據(jù):nwrite = write(fd,buff,size);

2)讀進程以只讀阻塞方式打開/home/FIFO管道:fd = open(/home/FIFO,O_RDONLY);

從管道中讀走nread 字節(jié)數(shù)據(jù):nread = read(fd,buff,size)。

3 ?無名管道和命名管道的異同

無名管道的特點:1)只有血緣關(guān)系的進程才能訪問無名管道;2)無名管道通過控制文件描述符確定管道的讀、寫端;3)無名管道不是普通的磁盤文件,通信時傳輸?shù)臄?shù)據(jù)存放在內(nèi)存緩沖區(qū)。

命名管道的特點:1)命名管道可以在任何沒有關(guān)聯(lián)的兩個進程之間通信;2)命名管道以磁盤文件形式存在,通信過程中數(shù)據(jù)存放在內(nèi)存緩沖區(qū);3)不支持定位lseek()操作。

無名管道和命名管道的特點對比如表1所示。

4 ?結(jié) ?論

綜上所述,無名管道并不是位于外存的磁盤文件,實際是一個內(nèi)核緩沖區(qū)。無名管道只能應(yīng)用在有血緣關(guān)系的進程之間傳輸數(shù)據(jù),它們共享無名管道,通過控制文件描述符來實現(xiàn)對無名管道的訪問。

命名管道雖然被標(biāo)識成位于外存的一個磁盤文件,但它并不占用磁盤空間,而是與內(nèi)核緩沖區(qū)關(guān)聯(lián),利用命名管道通信的進程可以無任何關(guān)系,只要進程都能夠通過路徑訪問該命名管道就可以實現(xiàn)通信。不管無名管道還是命名管道在通信過程中,數(shù)據(jù)都存放在內(nèi)核緩沖區(qū)。無名管道和命名管道互為補充,這樣就讓管道通信體現(xiàn)了其獨有通信優(yōu)勢。

參考文獻:

[1] 劉玓,陳佳,肖堃,等.Linux操作系統(tǒng)應(yīng)用編程 [M].北京:人民郵電出版社,2021.

[2] 趙宏,龐偉業(yè),袁繼泉,等.Linux教學(xué)中進程之間通過特殊文件通信的解析 [J].計算機時代,2022(10):123-126.

[3] 趙宏,朱忠政,常兆斌.Linux系統(tǒng)教學(xué)中關(guān)于命名管道文件的解析 [J].軟件,2020,41(2):108-110.

[4] 喬靜,劉寶旨,屈志強,等.Linux中命名管道通信淺析 [J].中國科技信息,2009(20):97-98.

[5] 張龍.Linux下管道通信的實現(xiàn) [J].企業(yè)技術(shù)開發(fā),2010,29(19):8-9.

[6] 段瑩,管濤.Linux進程間管道通信的研究 [J].軟件導(dǎo)刊,2012,11(7):3-5.

作者簡介:鄧飛(1972—),男,漢族,四川眉山人,講師,碩士研究生,研究方向:云計算和信息安全;蔡波(1984—),男,漢族,四川南充人,助教,本科,研究方向:計算機網(wǎng)絡(luò)和信息安全方向。

孟津县| 宜宾县| 米泉市| 郧西县| 剑阁县| 日土县| 监利县| 泗洪县| 文水县| 民勤县| 孝昌县| 嵊州市| 武汉市| 塔河县| 普格县| 东丽区| 绵竹市| 大化| 锡林郭勒盟| 绥宁县| 丰原市| 金湖县| 姜堰市| 阳信县| 乳山市| 耒阳市| 铜梁县| 比如县| 黔江区| 南川市| 资兴市| 永吉县| 岚皋县| 石渠县| 剑阁县| 鄂托克前旗| 徐州市| 日喀则市| 宁波市| 从化市| 澄城县|