Linux系统教学中关于命名管道文件的解析

2020-06-09 12:20赵宏朱忠政常兆斌
软件 2020年2期

赵宏 朱忠政 常兆斌

摘  要: 针对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.