Linux 程序通訊之:命名管道 (FIFO)
阿新 • • 發佈:2018-12-21
一、簡介
由於管道(Pipe)只能應用於存在血緣關係的程序間通訊,為了突破這個限制,使用命名管道(FIFO)來實現 不相干程序間 的通訊。
FIFO 是 Linux 基礎檔案型別中的一種,它並不佔用磁碟上實際的資料塊,而僅僅是標識核心中的一條通道。各程序可以開啟這個檔案進行 read/write,實際上是在讀寫核心通道。
二、API 說明
1. 標頭檔案
#include <sys/types.h>
#include <sys/stat.h>
2. 建立一個 FIFO 檔案
int mkfifo(const char *pathname, mode_t mode);
3. 引數說明
pathname
: 指定建立的檔案路徑名mode
: 指定檔案的訪問許可權,實際為一個形如 “rwxrwxrwx” 的 int 值,分別表示 “所有者”、“所在組”、“其他組” 的使用者訪問許可權。r
為可讀,值為 1;w
為可寫,值為 2;x
為可執行,值為 4。通常使用八進位制數來表示許可權。例如0775
。
4. 返回值說明
成功返回 0,失敗返回 -1,並設定相應的 errno
。
注意 :如果檔案已存在,也會返回 -1,建立失敗的錯誤原因是:檔案已存在。
三、命名管道的開啟規則
1. 說明
注意,mkfifo
方法只是建立了一個這樣的檔案,可供其它程序操作。而其它程序想要使用該檔案進行通訊,還是需要像檔案操作一樣,開啟
2. 開啟規則
開啟 FIFO 檔案通常有四種方式,即:
open(const char *path, O_RDONLY); // 只讀的方式開啟(會堵塞)
open(const char *path, O_RDONLY | O_NONBLOCK); // 非堵塞的只讀方式開啟
open(const char *path, O_WRONLY); // 只寫的方式開啟(會堵塞)
open(const char *path, O_WRONLY | O_NONBLOCK); // 非堵塞的只寫方式開啟
3. 規則說明
O_RDONLY
和 O_WRONLY
我們已經很熟悉了,但 O_NONBLOCK
O_NONBLOCK
表示非堵塞的方式,預設情況下,開啟 FIFO 是會堵塞程序的。例如我們的 A 程序使用只讀的方式開啟檔案時,此時它會被堵塞住,直到有一個 B 程序以只寫的方式打開了同一個 FIFO 檔案。同理,先以只寫的方式開啟,也會堵塞住,直到有一個程序以只讀的方法開啟同一個 FIFO 檔案。
可能會覺得有點暈,下面通過一個實際例子,並給出執行的 gif 圖,來理解堵塞的含義。
示例
1. 寫程序
將一個 Hello World
寫到 FIFO 檔案中去。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char pathname[] = "my_fifo";
char buf[] = "Hello World\n";
mkfifo(pathname, 0775);
int fd = open(pathname, O_WRONLY);
if (fd == -1) {
perror("open failed\n");
exit(EXIT_FAILURE);
}
write(fd, &buf, strlen(buf));
printf("write done\n");
close(fd);
return 0;
}
2. 讀程序
讀取 FIFO 檔案中的資訊,並輸出到標準輸出流中。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char pathname[] = "my_fifo";
char buf[127] = { 0 };
mkfifo(pathname, 0775);
int fd = open(pathname, O_RDONLY);
if (fd == -1) {
perror("open failed\n");
exit(EXIT_FAILURE);
}
int n;
while ((n = read(fd, buf, 10)) > 0) {
write(STDOUT_FILENO, &buf, n);
}
close(fd);
return 0;
}
3. 執行示例
先執行讀的程式,open 會堵塞住等待讀入,再執行寫的程式,兩個程序都成功執行完畢。
同理反過來,先執行寫的程式,也會一直堵塞等待。
這裡展示的是先執行 讀 的程序,再執行 寫 的程序,可以觀察到確實會有堵塞的情況。
反過來也是一樣的會有先堵塞 寫 程序,直到 讀 程序執行時結束。