命名管道的主要用途:不相關的進程之間交換數據。 命令行上創建命名管道: 程式中創建命名管道: 備註:#include <sys/types.h>是Unix/Linux系統的基本系統數據類型的頭文件,含有Size_t,time_t,pid_t等類型。 #include<sys/stat.h>是Unix ...
命名管道的主要用途:不相關的進程之間交換數據。
命令行上創建命名管道:
$ mkfifo filename
程式中創建命名管道:
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *filename, mode_t mode);
備註:#include <sys/types.h>是Unix/Linux系統的基本系統數據類型的頭文件,含有Size_t,time_t,pid_t等類型。
#include<sys/stat.h>是Unix/Linux系統定義文件狀態所在的偽標準頭文件。
常式:創建一個FIFO命名管道
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> int main(int argc, char *argv[]) { int res; res = mkfifo("./FIFO", 0777); if(res == 0) { printf("FIFO created\n"); } exit(EXIT_SUCCESS); }
備註:文件許可權方面的知識有點模糊,需要回顧。
$ ls -lF(F選項會在顯示目錄條目時,在目錄後加一個符號“/”表示文件夾 “|”表示管道)
prwxr-xr-x 1 root root 0 12月 17 17:02 FIFO|
創建出來的FIFO管道如上圖所示,其中第一個字元p表示這是一個管道,其中最後一個|符號是由ls命令的-F選項所添加,也表示它是一個管道。
FIFO是以命名文件的形式存在,而不是打開的文件描述符,所以在對它進行讀寫操作之前必須先打開它。而且,對於FIFO來說,傳遞給open函數的第一個參數一定是一個FIFO的路徑名,而不是一個文件名。
使用open打開FIFO文件
1.FIFO命名管道不能以O_RDWR的模式打開,會產生二義性。(通常使用FIFO只是為了單向傳遞數據)
2.如果確定需要程式之間雙向傳遞數據。①最好使用一對FIFO或者管道,一個方向使用一個②採用先關閉再重新打開FIFO的方法來明確地改變數據流的去向(不常用)。
3.打開FIFO文件和打開普通文件的另一點區別是:對open_flag(open的第二個參數)的O_NONBLOCK的用法。
- open(const char *path, O_RDONLY);
在這種情況下,open調用將阻塞,除非有一個進程以寫方式打開一個FIFO,否則它是不會返回。
- open(const char *path, O_RDONLY | O_NONBLOCK);
即使沒有其他進程以寫方式打開FIFO,open調用也會成功並且立即返回。
- open(const char *path, WRONLY);
在這種情況下,open調用將阻塞,直到有一個進程以讀方式打開進程。
- open(const char *path, WRONLY | O_NONBLOCK);
這個函數調用總是立刻返回,但如果沒有進程以讀方式打開FIFO文件,open調用將返回一個錯誤-1並且FIFO也不會被打開。如果確實有一個進程以讀方式打開FIFO文件,那麼我們就我再可以通過它返回的文件描述符對這個FIFO文件進行寫操作。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> /* using string */ #include <fcntl.h> /* O_RDONLY in this file */ #define FILE_NAME "/home/test/readfifo" int main(int argc, char *argv[]) { int res; if(access(FILE_NAME, F_OK) == -1) { res = mkfifo(FILE_NAME, 0777); if(res != 0) { printf("the fifo file could not create\n"); exit(EXIT_FAILURE); } } printf("read fifo file create successfull \n"); open(FILE_NAME, O_RDONLY | O_NONBLOCK); printf("open the read fifo file is success \n"); exit(EXIT_SUCCESS); }
備註:string.h在使用到字元數組時需要使用。
fcntl.h是unix標準中通用的頭文件,其中包含相關函數有open,fcntl,shutdown,unlink,fclose等。與unistd.h相比,後者定義了更多的函數原型。
在open的函數調用中,如果是非阻塞。
read fifo file create successfull open the read fifo file is success
在open的函數調用中,如果是阻塞,即沒有使用O_NONBLOCK
read fifo file create successfull
就會阻塞在open函數上,然後等待寫進程打開這個函數,然後才會返回。
註意:Linux中進程被阻塞時,並不消耗CPU資源。
對FIFO進行讀寫操作
如果在open函數使用了O_NONBLOCK模式,會影響到對FIFO的read和write調用。
- 對一個空的、阻塞的FIFO(即沒有用O_NONBLOCK標誌打開的)的read調用將等待,直到有數據可以讀時才繼續執行。
- 對一個空的、非阻塞的FIFO的read調用將立刻返回0位元組。
- 對一個完全阻塞FIFO的write調用將等待,知道數據可以被寫入才繼續執行,如果FIFO不能接受所有寫入數據,將按照下麵的規則執行:①如果請求寫入的數據長度小於等於PIPE_BUF位元組,調用失敗,數據不能寫入。(表示有空間,但是不能寫入,出現問題)。②如果請求寫入的數據的長度大於PIPE_BUF位元組,將寫入部分數據,返回實際寫入的位元組數,返回值也可能是0(表示只是FIFO的空間不足,先寫入部分數據)。
註意:PIPE_BUF是系統對FIFO的一個數據長度的限制,通常在頭文件limits.h可以找到它,通常值為4096位元組,也有特例。系統規定:在一個以O_WRONLY方式(即阻塞方式)打開的FIFO中,如果寫入的數據長度小於等於PIPE_BUF,要麼全部一次性寫入,要麼一個位元組也不寫入。
基於“註意”中的描述,如果出現一種情況:多個程式向一個FIFO中寫入數據的時候,為了保證這些寫入的數據不會相互交錯重疊,那麼就要求每次寫入的數據長度要小於等於PIPE_BUF位元組。