【linux】mkfifo 命令创建命名管道实现进程之间通信

时间:2021-08-07 00:25:27

mkfifo 命令

  • mkfifo命令创建一个FIFO特殊文件,是一个命名管道(可以用来做进程之间通信的桥梁)
  • 管道也是一种文件,一般是linux中的一个页大小,4k,管道数据一旦被读取就没了。(管道大小和管道的buff大小理解有错误,请看 pipe-buffer-size-is-4k-or-64k?
  • 管道是单方向
  • mkfifo命令文档

使用命名管道

下面均是再OSX系统实验。

创建管道

liuzhizhi@lzz-rmbp|pipe # mkfifo log.pipe

查看管道

liuzhizhi@lzz-rmbp|pipe # ls -l
total 0
prw-r--r-- 1 liuzhizhi staff 0 10 14 22:21 log.pipe

仔细看下最前面的部分 开头是 p,表示这是一个管道

使用管道

  • 一对一的情况
#第一个窗口
# ls -l > log.pipe

#第二个窗口
# cat < log.pipe
total 0
prw-r--r-- 1 liuzhizhi staff 0 10 14 22:25 log.pipe

这里管道并不是水桶,当我们执行 ls -l > log.pipe 的时候,这里就开始阻塞了,只有当我们再第二个窗口执行 cat < log.pipe 的时候,第一个窗口的ls命令才执行完。

所以这里的管道非常形象,它只是负责传输,虽然它也能存点水,但只有实用的时候才能存住一点水,如果只有一端倒水或者只有一端接水,都是无法正常运行的。

  • 一个输入,多个接收的情况
#窗口1
cat < log.pipe

#窗口2
cat < log.pipe

#窗口3
echo "lzz" > log.pipe

执行的结果是窗口2输出了 lzz,第一个窗没有输出,说明接收方无论多个只能获取一份水,只要被一个接收方接受到,另外一个就无法获取了(所以他不是订阅型的),通过持续往管道输入可以看到,接收方应该是基于抢占式的。

  • 多个输入,一个接受的情况

这里写了一个python程序来做为持续的输入

#coding:utf-8
#logpipe.py
import time
import sys

word = sys.argv[1]

while 1:
    print >> sys.stdout, word
    time.sleep(1)

测试

#窗口1
cat < log.pipe

#窗口2
python logpipe.py win1 > log.pipe

#窗口3
python logpipe.py win2 > log.pipe

#输出
win2
win2
win2
win2
win1
win1

其实这种情况,比较好理解,有个下水道大家都往里面倒水,最后汇总到一个口流出来,由于有缓冲区,所以并不会马上读取到结果。

小结

当然我们这里是用bash 操作这个命名管道,其实基本所有的语言都可以使用这个工具,例如bash命令写入管道,python读取,lua读取。

为什么想到这个东西呢,例如实时读取和处理tcpdump抓包,用c来开发成本有点大,用其他语言当然也可以,但是硬件条件有不允许,所以只好通过管道的方式输出到一个非常廉价的小程序来处理喽。