管道和FIFO的特徵之一是它們的數據是一個字節流。這是UNIX的原生I/O模型。進程往其中寫入的是字節流,系統不對它做解釋。linux
FIFO不存數據,只是經過它找到內核文件。安全
一.創建有名管道函數
1.命令mknod :spa
mknod name p/s/m //建立管道文件/信號量/共享內存code
2.命令mkfifo 建立管道blog
mkfifo -m 664 k2 //建立一個訪問權限爲664的管道文件k2 進程
3做爲函數:mkfifoip
#include <sys/types.h>內存
#include <sys/stat.h>字符串
int mkfifo(const char *pathname, mode_t mode);
【注意】
mkfifo已隱含指定O_CREAT|O_EXCL。即它要麼建立一個新的FIFO,要麼返回一個EEXIST錯誤。若是隻是但願打開而不建立文件,那就應調用open而不是mkfifo。
要打開一個已存在的FIFO或建立一個新的FIFO,應先調用mkfifo,檢查它是否返回EEXIST錯誤,若返回則改成調用open。
另:open函數
open(const char *path, O_RDONLY);//1 open(const char *path, O_RDONLY | O_NONBLOCK);//2 open(const char *path, O_WRONLY);//3 open(const char *path, O_WRONLY | O_NONBLOCK);//4
一、就是程序不能以O_RDWR(讀寫)模式打開FIFO文件進行讀寫操做,而其行爲也未明肯定義,由於如一個管道以讀/寫方式打開,進程就會讀回本身的輸出,同時咱們一般使用FIFO只是爲了單向的數據傳遞。
二、就是傳遞給open的是FIFO的路徑名,而不是文件名。
3.第二個參數中的選項O_NONBLOCK,選項O_NONBLOCK表示非阻塞,加上這個選項後,表示open調用是非阻塞的,若是沒有這個選項,則表示open調用是阻塞的。
以只讀方式和只寫方式打開文件時要注意:
讀端打開,若是寫端已打開則打開操做成功返回,若是寫端沒打開,則讀端阻塞。若是是非阻塞函數,則成功返回,(讀到文件結束標誌)
寫端打開,若是讀端已打開則打開操做成功返回,若是讀端沒打開,則寫端阻塞。若是是非阻塞函數,則返回ENXIO錯誤(產生信號SIGPIPE)
從FIFO中讀取數據:
1. 讀端的阻塞標誌只對本進程第一個讀操做施加做用,若是本進程內有多個讀操做序列,則在第一個讀操做被喚醒並完成讀操做後,其它將要執行的讀操做將再也不阻塞,即便在執行讀操做時,FIFO中沒有數據也同樣(此時,讀操做返回0)。
2. 對於設置了阻塞標誌的讀操做說,形成阻塞的緣由有兩種:當前FIFO內有數據,但有其它進程在讀這些數據;另外就是FIFO內沒有數據。解阻塞的緣由則是FIFO中有新的數據寫入,不論寫入數據量的大小,也不論讀操做請求多少數據量。就是說讀操做同時只能夠有一個進程進行。
3. 若是有進程寫打開FIFO,且當前FIFO內沒有數據,則對於設置了阻塞標誌的讀操做來講,將一直阻塞。對於沒有設置阻塞標誌讀操做來講則返回-1,當前errno值爲EAGAIN,提醒之後再試。
向FIFO中寫入數據:
1.對於設置了阻塞標誌的寫操做:
2.對於沒有設置阻塞標誌的寫操做:
FIFO內核實現時能夠支持雙向通訊。(pipe單向通訊,由於父子進程共享同一個file 結構體)
先關閉只讀方式打開的文件,再以只寫方式打開文件。這樣就能夠實現雙向通訊了。但最好使用一對FIFO
驗證代碼:
先寫後讀:
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #define MSG "hello" int main() { int fd; fd = open("./fio",O_WRONLY); printf("w:send msg:%s\n",MSG); write(fd,MSG,sizeof(MSG)); sleep(5); close(fd); fd = open("./fio",O_RDONLY); char buf[1024]; memset(buf,0,sizeof(buf)); read(fd,buf,sizeof(buf)); printf("w,recv:%s\n",buf); }
先讀後寫:
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <fcntl.h> int main() { int fd; fd = open("./fio",O_RDONLY); char buf[1024]; memset(buf,0,sizeof(buf)); read(fd,buf,sizeof(buf)); printf("r:recv msg:%s\n",buf); sleep(5); close(fd); fd = open("./fio",O_WRONLY); printf("r:send:%s\n","fighting"); write(fd,"fighting",9); }
安全問題:
個FIFO文件,有多個進程同時向同一個FIFO文件寫數據,而只有一個讀FIFO進程在同一個FIFO文件中讀取數據時,會發生數據塊的相互交錯。
根據上面的知識咱們知道:
若是全部的寫請求都是發往一個阻塞的FIFO的,而且每一個寫記請求的數據長度小於等於PIPE_BUF字節,系統就能夠確保數據決不會交錯在一塊兒。
模型:
1-1
n-1
n-1-n
fgets,它讀取以換行符「\n」結尾的字符串.
小結:
管道文件。它佔用i節點塊和數據塊,在目錄文件中記載了文件和i節點對應關係的管道是有名管道,沒有記載的是無名管道。
管道文件一旦讀出,就從管道中刪除,因此它具備不可再現性。