linux 管道--轉

linux 管道 

管道是Linux中很重要的一種通訊方式,是把一個程序的輸出直接鏈接到另外一個程序的輸入,常說的管道可能是指無名管道,無名管道只能用於具備親緣關係的進程之間,這是它與有名管道的最大區別。node

有名管道叫named pipe或者FIFO(先進先出),能夠用函數mkfifo()建立。linux

Linux管道的實現機制數組

在Linux中,管道是一種使用很是頻繁的通訊機制。從本質上說,管道也是一種文件,但它又和通常的文件有所不一樣,管道能夠克服使用文件進行通訊的兩個問題,具體表現爲:數據結構

·      限制管道的大小。實際上,管道是一個固定大小的緩衝區。在Linux中,該緩衝區的大小爲1頁,即4K字節,使得它的大小不象文件那樣不加檢驗地增加。使用單個固定緩衝區也會帶來問題,好比在寫管道時可能變滿,當這種狀況發生時,隨後對管道的write()調用將默認地被阻塞,等待某些數據被讀取,以便騰出足夠的空間供write()調用寫。函數

·      讀取進程也可能工做得比寫進程快。當全部當前進程數據已被讀取時,管道變空。當這種狀況發生時,一個隨後的read()調用將默認地被阻塞,等待某些數據被寫入,這解決了read()調用返回文件結束的問題。spa

注意:從管道讀數據是一次性操做,數據一旦被讀,它就從管道中被拋棄,釋放空間以便寫更多的數據。.net

1. 管道的結構線程

     在 Linux 中,管道的實現並無使用專門的數據結構,而是藉助了文件系統的file結構和VFS的索引節點inode。經過將兩個 file 結構指向同一個臨時的 VFS 索引節點,而這個 VFS 索引節點又指向一個物理頁面而實現的。code

2.管道的讀寫blog

      管道實現的源代碼在fs/pipe.c中,在pipe.c中有不少函數,其中有兩個函數比較重要,即管道讀函數pipe_read()和管道寫函數pipe_wrtie()。管道寫函數經過將字節複製到 VFS 索引節點指向的物理內存而寫入數據,而管道讀函數則經過複製物理內存中的字節而讀出數據。固然,內核必須利用必定的機制同步對管道的訪問,爲此,內核使用了鎖、等待隊列和信號。

     當寫進程向管道中寫入時,它利用標準的庫函數write(),系統根據庫函數傳遞的文件描述符,可找到該文件的 file 結構。file 結構中指定了用來進行寫操做的函數(即寫入函數)地址,因而,內核調用該函數完成寫操做。寫入函數在向內存中寫入數據以前,必須首先檢查 VFS 索引節點中的信息,同時知足以下條件時,才能進行實際的內存複製工做:

 

       ·內存中有足夠的空間可容納全部要寫入的數據;

       ·內存沒有被讀程序鎖定。

 

若是同時知足上述條件,寫入函數首先鎖定內存,而後從寫進程的地址空間中複製數據到內存。不然,寫入進程就休眠在 VFS 索 引節點的等待隊列中,接下來,內核將調用調度程序,而調度程序會選擇其餘進程運行。寫入進程實際處於可中斷的等待狀態,當內存中有足夠的空間能夠容納寫入 數據,或內存被解鎖時,讀取進程會喚醒寫入進程,這時,寫入進程將接收到信號。當數據寫入內存以後,內存被解鎖,而全部休眠在索引節點的讀取進程會被喚 醒。

     管 道的讀取過程和寫入過程相似。可是,進程能夠在沒有數據或內存被鎖定時當即返回錯誤信息,而不是阻塞該進程,這依賴於文件或管道的打開模式。反之,進程可 以休眠在索引節點的等待隊列中等待寫入進程寫入數據。當全部的進程完成了管道操做以後,管道的索引節點被丟棄,而共享數據頁也被釋放。

   由於管道的實現涉及不少文件的操做,所以,當讀者學完有關文件系統的內容後來讀pipe.c中的代碼,你會以爲並不難理解。

Linux 管道的建立和使用都要簡單一些,惟一的緣由是它須要更少的參數。實現與 Windows 相同的管道建立目標,Linux 和 UNIX 使用下面的代碼片斷:

建立 Linux 命名管道
int fd1[2];

         if(pipe(fd1))

        { printf("pipe() FAILED: errno=%d",errno);

              return 1;

         }

Linux 管道對阻塞以前一次寫操做的大小有限制。 專門爲每一個管道所使用的內核級緩衝區確切爲 4096 字節。 除非閱讀器清空管道,不然一次超過 4K 的寫操做將被阻塞。 實際上這算不上什麼限制,由於讀和寫操做是在不一樣的線程中實現的。

Linux 還支持命名管道。對這些數字的早期評論員建議我,爲公平起見,應該比較 Linux 的命名管道和 Windows 的命名管道。我寫了另外一個在 Linux 上使用命名管道的程序。我發現對於 Linux 上命名的和未命名的管道,結果是沒有區別。

Linux 管道比 Windows 2000 命名管道快不少,而 Windows 2000 命名管道比 Windows XP 命名管道快得多。

例子:

#include<stdio.h>
#include<unistd.h>


int main()
{
int n,fd[2];                         // 這裏的fd是文件描述符的數組,用於建立管道作準備的
pid_t pid;
char line[100];
if(pipe(fd)<0)                     //   建立管道
   printf("pipe create error/n");

if((pid=fork())<0)              //利用fork()建立新進程
    printf("fork error/n");

else if(pid>0){                   //這裏是父進程,先關閉管道的讀出端,而後在管道的寫端寫入「hello world"
    close(fd[0]);
    write(fd[1],"hello word/n",11);
}
else{
    close(fd[1]);                 //這裏是子進程,先關閉管道的寫入端,而後在管道的讀出端讀出數據
   n= read(fd[0],line,100);
    write(STDOUT_FILENO,line,n);
}
exit(0);
}

來源不可知,轉載地址:http://blog.csdn.net/mtv0312/article/details/6183583

管道通訊,就是在2個進程間創建一個管道

相關文章
相關標籤/搜索