趙宏 朱忠政 常兆斌



摘 ?要: 針對Linux系統相關內容教學中對于命名管道文件講述不夠詳細,導致學生對命名管道文件認識模糊的問題,基于Linux系統進程之間通信機制,講述了進程之間通過管道通信的原理、無名管道和命名管道的功能,并通過實例說明了命令方式和程序方式使用命名管道的方法。
關鍵詞:?Linux系統;文件權限;命名管道;Python
中圖分類號: TP301????文獻標識碼:?A????DOI:10.3969/j.issn.1003-6970.2020.02.023
【Abstract】: Most university students have the vague knowledge of named pipe file in Linux learning because the detailed explain about the named pipe is absent in Linux teaching files. Communicate principle between processes, functions of anonymous pipe and named pipe are discussed in detailed. Examples are presented in command and program modes to illustrate the usage of named pipe.
【Key words】: Linux system; File permission; Named pipe; Python
0??引言
Linux系統作為開放源代碼和自由軟件的代表,廣泛應用在各行各業,運行在各種機型和硬件平臺上[1,2]。Linux系統符合POSIX(Portable Operating System Interface)標準,功能強大,效率高,配置靈活,安全性高,且具有豐富的工具軟件和應用軟件,其相關內容在大多數高校信息類專業中作為專業基礎課開設[3,4],例如《Linux操作系統》、《Linux系統內核分析》、《Linux系統程序設計》等。
在Linux系統相關內容教學中,系統中的文件類型是基本內容,大多數教科書列舉了Linux中的文件類型,包括普通文件(-)、目錄文件(d)、字符設備文件(c)、塊設備文件(b)、符號鏈接文件(l)、命名管道文件(p)和套接字文件(s)等七種文件類型[1,4],對于前五種文件,一般都進行了詳細描述,并用實例加以說明,但對于后兩種文件,只是進行簡單的描述,也沒有實例的說明。學生在學習中,對于命名管道文件和套接字文件的認識很模糊,不利于對Linux系統的深刻理解。
本文基于Linux系統進程間通信機制,討論進程間通過管道通信的方法,并通過實例進行詳細說明,加深學生對命名管道文件的認識。
1??進程間管道通信方法
Linux系統中進程間通過管道通信時,將一個進程的輸出作為另一個進程的輸入。其本質是在內存中創建一個緩沖區,對緩存區中的數據以先進先出FIFO(First Input,First Output)的形式進行操作,就好像先進入管道的水會先流出,后進入管道的水會后流出,管道是對緩存區數據操作方式的形象稱謂。
實現管道功能的內存緩存區被設計成環形的數據結構,便于循環使用。當緩存區中沒有數據時,從緩存區讀取數據的進程會被阻塞,直到緩存區中有數據,同理,當緩存區中充滿數據時,給緩存區寫入數據的進程會被阻塞,直到緩存區中有空閑空間保存寫入的數據。當讀寫管道的進程結束時,為管道創建的緩存區也被系統回收。
1.1??無名管道
同一個用戶創建的多個進程之間利用管道進行通信時,由于為管道創建的內存緩存區供同一個用戶的進程訪問,不需要用戶身份和操作權限的鑒別,因此,對內存緩存區不需要進行特殊的標注,故稱為無名管道。
無名管道常用于Linux的命令中,用“|”表示,將一個命令的輸出結果作為另一個命令的輸入。例如“ls –l | more”,命令“ls -l”和“more”會各自創建一個進程,這兩個進程屬于執行命令的當前用戶,為命令“ls -l”創建的進程將命令的執行結果數據以管道的形式傳遞給為命令“more”創建的進程,后者進程對收到的數據在屏幕上進行分頁顯示,實現了前者命令結果分頁顯示的效果。
1.2??命名管道
不同用戶創建的進程之間利用管道進行通信時,由于為管道創建的內存緩存區要同時供不同用戶的進程進行操作,按照Linux系統嚴格的用戶身份和操作權限的規則,需要對操作內存緩存區的用戶身份和操作權限進行鑒別。
Linux的文件系統具有完善的用戶身份和操作權限的鑒權機制,將文件的操作分為讀(r, read)、寫(w, write)和執行(x, execute)等三種權限;將操作文件的用戶分為文件主(u, user)、同組用戶(g, group)和其他用戶(o, other)等三種角色。對一個文件而言,不同角色的用戶對文件具有不同的操作權限,保證了操作的安全性。
為不同用戶進程之間通信的管道,借鑒Linux文件系統的用戶身份和操作權限的鑒權機制,賦予管道一個文件名,按照文件系統的鑒權機制對管道操作,因此,稱為命名管道。
2??進程間管道通信方法
在Ubuntu 18.10系統中創建用戶user1和user2,在user1家目錄下創建子目錄named_pipe,在named_pipe子目錄下利用命令mkfifo創建命名管道文件a.pipe,如圖1所示。
圖1中,命名管道文件a.pipe的類型為“p”,表明該文件為命名管道文件;文件主為user1,文件主對該文件的操作權限為“rw-”,表示文件主可以對這個命名管道進行讀和寫;文件所屬組為user1,同組用戶對該文件的操作權限為“rw-”,表示屬于user1組的用戶對這個命名管道進行讀和寫;其他用戶對該文件的操作權限為“r--”,表示其他用戶對這個命名管道只能進行讀操作。命名管道文件為特殊的文件,其中不保存數據,所以,文件字節數為零。命名管道文件的操作權限,規定了系統中用戶對與該命名管道文件綁定的內存緩存區訪問的鑒權。
2.1??命令使用命名管道文件
為用戶user1和user2各打開一個終端命令窗口,在user1用戶的窗口中運行命令“ls -l>~/named_?pipe/a.pipe”,利用輸出重定向將命令的執行結果輸出給命名管道,其中,~代表用戶的家目錄;在user2用戶的窗口中運行命令“cat ~user1/named_pipe/?a.pipe”,利用命令cat讀取屬于user1的命名管道文件a.pipe。
先執行命令的窗口中的進程將被阻塞,直到另一個窗口中命令輸入完畢并回車。將在user2用戶的窗口中顯示user1窗口執行的命令的結果,如圖2所示。
該例利用命名管道實現了user1和user2進程之間的通信,其中,user1的進程向命名管道寫入數據,user2的進程從命名管道讀取數據;user1作為文件主對命名管道具有寫權限,user2作為其他用戶對命名管道具有讀權限,符合a.pipe的權限規定。
如果在user2用戶的窗口中運行命令“ls -l >~ user1/named_pipe/a.pipe”,則收到“權限不夠”的提示,如圖3所示,因為user2作為其他用戶,對a.pipe沒有寫權限。
如果將用戶user2加入user1組,使user2成為a.pipe的同組用戶,則user2運行命令“ls -l>~ user1/?named_pipe/a.pipe”會成果,因為同組用戶對a.pipe具有寫權限。
2.2??程序使用命名管道文件
Python語言語法簡潔,語義清晰,有非常豐富和強大庫的支持,廣泛應用在數據處理、科學計算、圖形圖像處理、機器學習、網絡編程、多媒體處理、系統運維、游戲服務器端開發等多個領域,是目前最流行的計算機編程語言之一[5]。本例選用Python編程語言實現。
在用戶user1家目錄下創建Python程序文件,pipe01.py,代碼如下。
1 ?#!/usr/bin/env
2 ?# coding: utf-8
3 ?#pipe01.py
4 ?f=open('/home/user1/named_pipe/a.pipe',?'w')
5 ?f.write('Hello, I am user1!')
6 ?f.close()
在用戶user2家目錄下創建Python程序文件,pipe02.py,代碼如下。
1 ?#!/usr/bin/env
2 ?# coding: utf-8
3 ?# pipe02.py
4 ?f=open('/home/user1/named_pipe/a.pipe',?'r')
5 ?info=f.read()
6 ?print(info)
7 ?f.close()
pipe01.py和pipe02.py中代碼前的行號是為敘述方便而加的,以#開頭的代碼為注釋,不執行。
pipe01.py的第4行代碼以寫的方式打開命名管道文件,第5行代碼給打開的文件寫入字符串“Hello,I am user1!”,第6行代碼關閉打開的文件。
pipe02.py的第4行代碼以讀的方式打開命名管道文件,第5行代碼從打開的文件讀取數據到變量info中,第6行代碼輸出變量info的內容,第7行代碼關閉打開的文件。
在user1用戶的窗口中運行命令“python pipe01.?py”,通過程序向命名管道文件寫入數據;在user2用戶的窗口中運行命令“python pipe02.py cat”,通過程序從命名管道文件讀取數據。在user2用戶的窗口中將會顯示“Hello, I am user1!”。
該例以程序的形式,利用命名管道實現了user1和user2進程之間的通信,其中,user1的進程向命名管道寫入數據,user2的進程從命名管道讀取數據;user1作為文件主對命名管道具有寫權限,user2作為其他用戶對命名管道具有讀權限,符合文件a.pipe的權限規定。
如果用戶user2要向a.pipe中寫入數據,必須要具備寫權限,否則,系統會給出沒有操作權限的提示。
3??結束語
命名管道文件是Linux系統的七種文件之一,也是不同用戶進程之間通信的一種手段,在Linux系統中具有重要作用。本文基于Linux系統進程之間通信的機制,討論了進程之間通過管道通信的本質,并給出利用命令和程序實現不同用戶進程之間通過命名管道通信的實例
參考文獻
鳥哥. 鳥哥的Linux私房菜基礎學習篇(第四版)[M]. 北京: 人民郵電出版社, 2018, 10.
Machtelt Garrels. Introduction to Linux[EB/OL]. (2010-05-?12) [2019-09-27]. http://tille.garrels.be/training/tldp/.
燕彩蓉, 朱黎華, 劉瑜琪, 等. 新工科背景下Linux系統課程教學研究[J]. 計算機教育, 2019(6): 152-156.
吳淑泉. 高校“Linux操作系統”課程教學研究與探索[J]. 教育理論與實踐, 2017, 37(33): 57-58.
趙宏, 包廣斌, 馬棟林. Python網絡編程(Linux)[M]. 北京: 清華大學出版社, 2018, 10.