首頁  >  文章  >  運維  >  linux管道是什麼

linux管道是什麼

青灯夜游
青灯夜游原創
2023-01-31 19:23:325073瀏覽

在linux中,管道是一種通訊機制,是把一個程式的輸出直接連接到另一個程式的輸入。從本質上來說,管道也是一種文件,但它又和一般的文件有所不同,管道可以克服使用文件進行通信的兩個問題,具體表現為:限制管道的大小、讀取進程可能工作得比寫進程快。

linux管道是什麼

本教學操作環境:linux7.3系統、Dell G3電腦。

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

有名管道叫named pipe或FIFO(先進先出),可以用函數mkfifo()來建立。

Linux管道的實作機制

在Linux中,管道是一種使用非常頻繁的通訊機制。從本質上來說,管道也是一種文件,但它又和一般的文件有所不同,管道可以克服使用文件進行通信的兩個問題,具體表現為:

  • 限制管道的大小。實際上,管道是一個固定大小的緩衝區。在Linux中,該緩衝區的大小為1頁,即4K字節,使得它的大小不像檔案那樣不加檢驗地增長。使用單一固定緩衝區也會帶來問題,例如在寫入管道時可能變滿,當這種情況發生時,隨後對管道的write()呼叫將預設被阻塞,等待某些資料被讀取,以便騰出足夠的空間供write()調用寫。

  • 讀取進程也可能運作得比寫入進程快。當所有目前進程資料已被讀取時,管道變空。當這種情況發生時,一個隨後的read()呼叫將預設被阻塞,等待某些資料被寫入,這解決了read()呼叫返回檔案結束的問題。

注意:從管道讀取資料是一次性操作,資料一旦被讀,它就從管道中被拋棄,釋放空間以便寫更多的資料。

1. 管道的結構

     在 Linux 中,管道的實作並沒有使用專門的資料結構,而是藉助了檔案系統的file結構和VFS的索引節點inode。透過將兩個 file 結構指向同一個臨時的 VFS 索引節點,而這個 VFS 索引節點又指向一個實體頁面而實現的。

2.管道的讀寫

      管道實現的原始程式碼在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);
}

推薦學習:Linux影片教學

以上是linux管道是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn