C 語言編程 — 管道(Pipe)

目錄

Linux 的管道指令

如果你熟悉 Linux,那麼你對管道應該不會感到陌生,我們經常會使用 “|” 來使用管道。但是管道的真正定義是什麼呢?

  • 管道是一個進程連接數據流到另一個進程的通道,它通常用作把一個進程的輸出通過管道連接到另一個進程的輸入

例如:ls -l | grep string

C 語言的匿名管道

C 語言的匿名管道 pipe() 定義在頭文件 unistd.h 中。

int pipe(filedes[2]);
  • filedes[2]:用於接收 pipe 返回的兩個文件描述符:filedes[0] 爲讀管道、filedes[1] 誒寫管道。
  • 返回值:成功返回 0,失敗返回 -1,並設置了 errno。

匿名管道實質上是一個先進先出(FIFO)的隊列:filedes[0] 是隊頭(front),filedes[1] 則作爲隊尾(rear)。pipe() 創建的管道,本質是一個內核緩衝區,該緩衝區的大小一般爲一頁,即 4K 字節。

命名管道

通過匿名管道來在進程之間傳遞數據存在一個缺陷,就是這些進程都由一個共同的父進程啓動,這不便於我們在不相關的兩個進程之前交換數據,所以 C 語言進入了 “命名管道”,用於解決不相關進程間的通信問題;

命名管道也被稱爲 “FIFO 文件”,它是一種特殊類型的文件,在文件系統中以文件名的形式存在,它的行爲與匿名管道類似。因爲在 Linux 中一切皆文件,所以命名管道的使用與文件的操作方式基本一致,可以在命令行中使用。

可以使用以下兩個函數之一來創建一個命名管道:

  1. 頭文件 sys/types.h、sys/stat.h 中定義的:
int mkfifo(const char *filename, mode_t mode);
int mknod(const char *filename, mode_t mode | S_IFIFO, (dev_t)0);

這兩個函數都能創建一個 FIFO 文件,注意,是真的創建了一個真實存在於文件系統中的文件,filename 指定了文件名,而 mode 則指定了文件的讀寫權限。

  1. 可以直接在 Shell 中使用命令 mkfifo、mknod 來創建一個 FIFO 文件:
$ mkfifo fifo_file
$ mknod fifo_file p

匿名管道和命名管道的區別

使用匿名管道,通信的進程之間需要一個父子關係,通信的兩個進程一定是由一個共同的祖先進程啓動,匿名管道沒數據交叉的問題;

使用命名管道的兩個進程可不存在 “血緣” 關係,但爲了保證數據的安全,我們很多時候要採用阻塞的 FIFO,讓寫操作變成原子操作;

參考文檔

https://www.zfl9.com/c-ipc-pipe.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章