Linux中的Pipe和FIFO的原理淺析

以前從編程角度寫過Linux的Pipe和FIFO,主要側重於使用,附帶了簡單的原理介紹。(連接以下)node

http://my.oschina.net/u/158589/blog/54705 shell

http://my.oschina.net/u/158589/blog/55051 編程

今天在看Understanding The Linux Kernel時,發現本身對Pipe和FIFO的理解稍顯不足,這裏簡單的對其原理作一些補充。主要採用Question & Answer的形式。數據結構

1. 爲何要將FIFO和Pipe放在一塊兒講?他們間的區別是什麼?socket

緣由是他們的核心數據結構是同樣的,pipe_inode_info,而且,FIFO的讀寫函數和pipe的讀寫函數也一致。函數

關於區別,如下要稍微講一下。使用上的區別參見本文開頭的兩篇博文。spa

核心區別有兩點。.net

第一,fifo出如今系統目錄樹中,而pipe則在特殊文件系統pipefs中。blog

第二,fifo是雙向通訊管道,而pipe是單向的。繼承

 

2. Pipe和FIFO有對應的disk image嗎?有對應的indoe嗎?他們屬於同一個文件系統嗎?

pipe和fifo都沒有對應的disk image。

他們都是文件,因此確定有inode。同時,當建立一個pipe或者fifo時,其實是建立了一個inode和兩個file object.

pipe屬於pipefs文件系統,fifo不是。因此他們不屬於同一個文件系統。

值得注意的是如下兩點:

第一, pipefs這個特殊的文件系統在VFS的目錄中是沒有的,用戶不可見,它是在kernel初始化時進行建立而且掛載到VFS上的。

第二,雖然fifo在VFS的目錄樹下,可是它並不對應disk上的文件,有點像device文件。其核心的buffer是kernel中的buffer.

 

 

3. ls | more背後發生了什麼?

step1: shell建立一個pipe(假設其file descriptor是3和4,這樣方便討論)。

step2: shell fork出兩個子進程。此時,這兩個子進程同繼承了父進程的文件描述符,也就是說,他們一樣有3和4.

step3: 第一個子進程調用dup2(4, 1)。這就將1(標準輸出)的file object關閉了,而且,1這個文件描述符,此時指向了4文件描述符指向的file object,即pipe的寫端。子進程關閉3和4。子進程execve(), 執行ls命令。因爲execve也是用的同一個文件描述符表,因此此時ls的輸出其實是pipe的寫端。

step4: 第二個子進程調用dup2(3, 0)。如上,0(標準輸入)的file object關閉,而且,0這個文件描述符,指向了3這個文件描述符指向的file object,即pipe的讀端。子進程關閉3和4. 子進程execve(), 執行more命令。此時,more的輸入其實是pipe的讀端。

因而,ls的輸出就順利的重定向到more的輸入了。

 

4. Pipe和FIFO使用的多嗎?

Pipe就不用說了,shell中常常用到,實際編程中若是遇到重定向或者父子進程通訊,pipe也是一個不錯的選擇。就我目前看到過的代碼而言,shell中pipe使用較多,c中pipe也有用到,但明顯沒有semaphore,socket等廣泛。

FIFO的話,說實話,基本沒見過。我認爲緣由是他能作的,socket也必定能作,而且能作的更好。因此FIFO就有點累贅了。另外,從本文開頭的兩篇連接中,咱們能夠看到,FIFO的編程有點麻煩,要對讀寫進行比較精確的控制,防止死鎖或者競爭。

就到這裏吧。

相關文章
相關標籤/搜索