命名管道(FIFO)不一樣於無名管道之處在於它提供了一個路徑名與之關聯,以 FIFO 的文件形式存在於文件系統中,這樣,即便與 FIFO 的建立進程不存在親緣關係的進程,只要能夠訪問該路徑,就可以彼此經過 FIFO 相互通訊,所以,經過 FIFO 不相關的進程也能交換數據。linux
命名管道(FIFO)和無名管道(pipe)有一些特色是相同的,不同的地方在於:函數
一、FIFO 在文件系統中做爲一個特殊的文件而存在,但 FIFO 中的內容卻存放在內存中。測試
二、當使用 FIFO 的進程退出後,FIFO 文件將繼續保存在文件系統中以便之後使用。spa
三、FIFO 有名字,不相關的進程能夠經過打開命名管道進行通訊。blog
int mkfifo(const char *pathname, mode_t mode);用於建立一個管道進程
int open(const char *pathname, int flags);用於打開一個管道ip
打開FIFO文件和普通文件的區別有2點:內存
第一個是不能以O_RDWR模式打開FIFO文件進行讀寫操做。這樣作的行爲是未定義的。it
由於咱們一般使用FIFO只是爲了單向傳遞數據,因此沒有必要使用這個模式。pip
若是確實須要在程序之間雙向傳遞數據,最好使用一對FIFO或管道,一個方向使用一個。或者採用先關閉在從新打開FIFO的方法來明確改變數據流的方向。
第二是對標誌位的O_NONBLOCK選項的用法。
使用這個選項不只改變open調用的處理方式,還會改變對此次open調用返回的文件描述符進行的讀寫請求的處理方式。
O_RDONLY、O_WRONLY和O_NONBLOCK標誌共有四種合法的組合方式:
open函數調用中的參數標誌O_NONBLOCK會影響FIFO的讀寫操做。
規則以下:
注意這個限制的做用:
當只使用一個FIF並容許多個不一樣的程序向一個FIFO讀進程發送請求的時候,爲了保證來自不一樣程序的數據塊 不相互交錯,即每一個操做都原子化,這個限制就很重要了。若是可以包子全部的寫請求是發往一個阻塞的FIFO的,而且每一個寫請求的數據長父小於等於PIPE_BUF字節,系統就能夠確保數據毫不會交錯在一塊兒。一般將每次經過FIFO傳遞的數據長度限制爲PIPE_BUF是一個好辦法。
其中。PIPE_BUF是FIFO的長度,它在頭文件limits.h中被定義。在linux或其餘類UNIX系統中,它的值一般是4096字節。
上面都是網上找的資料,有時間再整理吧,下面是本身寫的一個測試代碼:
write.c
#include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define FIFO_NAME "/tmp/myfifo" int main(){ if(access(FIFO_NAME,F_OK) != 0){//若是文件存在 int err = mkfifo(FIFO_NAME,0777); if(err != 0){ perror("Create fifo failed"); return -1; } } printf("create fifo succeed!\n"); int fifo_fd = open(FIFO_NAME,O_WRONLY); printf("open fifo succeed!\n"); if(fifo_fd < 0){ printf("open fifo failed!\n"); return -1; } int i = 1; for(;i < 100; i++){ if(write(fifo_fd,&i,sizeof(int)) != -1) sleep(1); else perror("Write failed"); } printf("write succeed: %d\n",i); close(fifo_fd); return 0; }
read.c
#include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "/tmp/myfifo" int main(){ int fifo_fd = open(FIFO_NAME,O_RDONLY | O_NONBLOCK ); if(fifo_fd < 0){ printf("open fifo failed!\n"); return -1; } int i; sleep(5); while(1){ int size = read(fifo_fd,&i,sizeof(int)); if(size > 0) printf("讀到:%d\n",i); } close(fifo_fd); return 0; }
通訊過程當中,當全部讀進程退出後,寫進程向命名管道內寫數據時,寫進程也會(收到 SIGPIPE 信號)退出。
本例子中,寫進程退出後,讀進程繼續循環,當再次有寫進程啓動時,讀進程就會再次讀到數據。