前面學習過(匿名)管道(見前面博客),匿名管道只能用於有親緣關係的各個進程之間,爲了解決這個限制,UNIX系統進而引入了FIFO,也稱爲有名管道(named pipe)。shell
FIFO(first in, first out),是一個半雙工數據流,也即一個半雙工管道。不一樣於匿名管道的是,每一個FIFO有一個路徑名(或文件名)與之關聯,也即FIFO的名字。有了名字,無親緣關係的進程間就能夠經過管道進行數據傳輸了。app
建立FIFO的方式:函數
使用shell命令 mkfifo建立一個有名管道學習
[infor@s123 FIFO]$ mkfifo npipe [infor@s123 FIFO]$ ls -l prw-r--r-- 1 infor app 0 Nov 13 11:32 npipe
上面咱們建立了一個有名管道npipe,咱們能夠看到有名管道實際上是一個文件,文件類型是「p」,管道類型。
咱們在開啓兩個終端,分別爲A和B。在A終端下將數據寫入管道,在B終端下將數據讀出來。spa
[infor@s123 FIFO]$ ping 10.4.123.124 >> npipe #會阻塞在這裏,等待另外一個進程讀
在終端A下將ping的結果寫入管道npipe,這裏會一直阻塞到另外一個進程將數據所有讀出或停止讀出。code
[infor@s123 FIFO]$ cat npipe PING 10.4.123.124 (10.4.123.124) 56(84) bytes of data. 64 bytes from 10.4.123.124: icmp_seq=0 ttl=128 time=0.838 ms 64 bytes from 10.4.123.124: icmp_seq=1 ttl=128 time=0.835 ms 64 bytes from 10.4.123.124: icmp_seq=2 ttl=128 time=0.843 ms 64 bytes from 10.4.123.124: icmp_seq=3 ttl=128 time=0.834 ms
在終端B下讀取npipe。
使用C庫函數mkfifo建立一個有名管道進程
#include <sys/types.h> #include <sys/stat.h> /* 函數說明:依參數pathname創建特殊的FIFO文件,該文件必須不存在,而參數mode爲該文件的權限 返回值:若成功則返回0,不然返回-1,錯誤緣由存於errno中 */ int mkfifo(const char *pathname, mode_t mode);
對於建立方式,mkfifo隱含指定O_CREAT|O_EXCL,也即mkfifo建立一個新的FIFO,若是該FIFO已經存在,則會返回EEXIST錯誤。ip
對於參數mode可有以下選項:
S_IRUSR:當前用戶可讀
S_IWUSR:當前用戶可寫
S_IRGRP:組成員可讀
S_IWGRP:組成員可寫
S_IROTH:其餘用戶可讀
S_IWOTH:其餘用戶可寫博客
下面經過例子看下如何使用。it
假若有這樣一個案例。進程A執行完將執行結果寫入管道,等待進程B將該結果讀出。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #define FIFO_NAME ("/tmp/fifo.1") // 設定FIFO的名字 #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 設定建立FIFO的權限 /*建立一個FIFO,等待另外一個進程讀取*/ int main() { int writefd; char status[] = "success"; size_t n = 0; // 建立FIFO if(mkfifo(FIFO_NAME, FILE_MODE) < 0) { if(EEXIST == errno) { printf("FIFO:%s已經存在,不能從新建立\r\n", FIFO_NAME); } else { perror("建立FIFO錯誤"); exit(1); } } // 打開FIFO writefd = open(FIFO_NAME, O_WRONLY, 0); if(-1 == writefd) { perror("打開FIFO失敗"); unlink(FIFO_NAME); exit(1); } // 寫入執行狀態 n = write(writefd, status, strlen(status)); if(n != strlen(status)) { perror("寫入FIFO失敗"); unlink(FIFO_NAME); exit(1); } if(-1 == close(writefd)) { perror("關閉FIFO失敗"); unlink(FIFO_NAME); exit(1); } return 0; }
編譯並執行:
[infor@s123 FIFO]$ gcc -o wnpipe wnpipe.c [infor@s123 FIFO]$ ./wnpipe #阻塞在這裏等待另一個進程讀取FIFO
這裏咱們看一下/tmp/fifo.1 是否生成:
[infor@s123 tmp]$ ls -l /tmp/fifo.1 prw-r--r-- 1 infor app 0 Nov 13 12:58 /tmp/fifo.1
咱們看到FIFO文件已經生成。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #define FIFO_NAME ("/tmp/fifo.1") // 設定FIFO的名字 #define MAXLINE (1024) /*讀取FIFO內容*/ int main() { int readfd; char status[MAXLINE]; size_t n = 0; // 打開FIFO readfd = open(FIFO_NAME, O_RDONLY, 0); if(-1 == readfd) { perror("打開FIFO失敗"); unlink(FIFO_NAME); exit(1); } // 讀取FIFO n = read(readfd, status, MAXLINE); if(-1 == n) { perror("讀取FIFO失敗"); exit(1); } printf("管道內容:%s\r\n", status); // 關閉FIFO if(-1 == close(readfd)) { perror("關閉FIFO失敗"); unlink(FIFO_NAME); exit(1); } // 刪除FIFO unlink(FIFO_NAME); return 0; }
編譯並執行:
[infor@s123 FIFO]$ gcc -o rnpipe rnpipe.c [infor@s123 FIFO]$ ./rnpipe 管道內容:success
這裏咱們再看一下/tmp/fifo.1 是否還存在:
[infor@s123 tmp]$ ls -l /tmp/fifo.1 ls: /tmp/fifo.1: No such file or directory
能夠看到文件已被刪除了。
2011-11-13 任洪彩 qdurenhongcai@163.com
轉載請註明出處。