1. 程式人生 > >【linux】mkfifo 命令建立命名管道實現程序之間通訊

【linux】mkfifo 命令建立命名管道實現程序之間通訊

mkfifo 命令

  • mkfifo命令建立一個FIFO特殊檔案,是一個命名管道(可以用來做程序之間通訊的橋樑)
  • 管道也是一種檔案,一般是linux中的一個頁大小,4k,管道資料一旦被讀取就沒了。(管道大小和管道的buff大小理解有錯誤,請看 pipe-buffer-size-is-4k-or-64k?
  • 管道是單方向

使用命名管道

下面均是再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來開發成本有點大,用其他語言當然也可以,但是硬體條件有不允許,所以只好通過管道的方式輸出到一個非常廉價的小程式來處理嘍。