1 管道(pipe)
Linux 中的管道可用于不同进程之间的通信,其操作符为 “|”。 通常管道只能在具有新缘关系(父子或拥有相同祖先)的进程间通信。而有名管道克服了管道没有名字的限制,因此它可允许无亲缘关系进程间的通信。
1.1 实现机制
管道是由内核管理的一个缓冲区,管道的一端连接一个进程的输出,这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。
管道的利用POSIX系统中的fork机制建立的。fork机制会将原进程复制到新进程,并且将原进程对其缓冲区的连接也一块复制过来。这样原进程和新进程都拥有了对同一缓冲区的(即管道)的读写能力,同时,每个进程关闭自己不需要的一个连接,一个只留读连接,一个只留写连接,这样就形成了管道。
1.2 操作举例
显示前三个文件的文件名:
- ls | head -3
- barry.txt
- bob
- example.png
将一个程序的输出传递给less命令使其易于查看:
- ls -l /etc | less
- (Full screen of output you may scroll. Try it yourself to see.)
列出当前目录下所有具写权限的文件:
ls -l | grep '^.....w'
drwxrwxr-x 3 ryan users 4096 Jan 21 04:12 dropbox
1.3 命名管道
由于基于fork机制的限制,管道只能用于父进程和子进程之间,或者有相同祖先的两个子进程之间的通信。为了解决这一问题,Linux提供了FIFO方式连接进程。FIFO又叫做命名管道(named PIPE)。
FIFO (First in, First out)为一种特殊的文件类型,它在文件系统中有对应的路径。FIFO只是借用了文件系统来为管道命名。当一个进程以读(r)的方式打开该文件,而另一个进程以写(w)的方式打开该文件,那么内核就会在这两个进程之间建立管道,当删除FIFO文件时,管道连接也随之消失。所以FIFO实际上也由内核管理,不与硬盘打交道。之所以叫FIFO,是因为管道本质上是一个先进先出的队列数据结构,最早放入的数据被最先读出来,从而保证信息交流的顺序。命名管道的好处在于我们可以通过文件的路径来识别管道,从而让没有亲缘关系的进程之间建立连接。
用ls命令查看所创建的管道:
$ ls -lF /tmp/my_fifo
prwxr-xr-x 1 root root 0 05-08 20:10 /tmp/my_fifo|
2 fork
2.1 进程
在说fork之前,我们先来复习一下操作系统中进程的相关内容:
进程可以看做程序的一次执行过程,且是拥有资源的最小单位和调度单位(在引入线程的操作系统中,线程是最小的调度单位)。在linux中,每个进程有唯一的PID(进程标识符)标识。PID是一个从1到32768的正整数,其中1是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。
Linux中有一个叫进程表的结构用来存储当前正在运行的进程。可以使用“ps aux”命令查看所有正在运行的进程。
进程在linux中呈树状结构,init为根节点,其它进程均有父进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。