有名管道又稱為FIFO,是程序間通信的一種方式。FIFO具有以下特點: 1.全雙工的通信模式,資料先進先出; 2.可以用于任意的程序之間,通過指定相同的管道檔案進行通信; 3.檔案名存在檔案系統中,而管道中的内容存在于記憶體中。可通過open、read、write對其操作;
有名管道的總體操作:
建立管道mkfifo
打開管道open
讀管道read
寫管道write
關閉管道close
删除管道unlink
建立:
頭檔案
#include <sys/types.h>
#include <sys/stat.h>
函數原型:
int mkfifo(const char * pathname, mode_t mode)
函數參數:
pathname:FIFO檔案名
mode:同open類似。
傳回值:成功0,出錯-1
一旦建立了一個FIFO,就可用open打開它,一般的檔案通路函數(close、read、write等)都可用于FIFO
FIFO檔案在使用上和普通檔案有相似之處,但是也有不有
不同之處:
1. 讀取fifo檔案的程序隻能以”RDONLY”方式打開fifo檔案。
2. 寫fifo檔案的程序隻能以”WRONLY”方式打開fifo
3. fifo檔案裡面的内容被讀取後,就消失了。但是普通檔案裡面的内容讀取後還存在。
其他的都和檔案操作一樣,這裡不在重複贅述。
下面我們來看看例題:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"
main(int argc,char** argv)
{
char buf_r[100];
int fd;
int nread;
/* 建立管道 */
if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
printf("cannot create fifoserver\n");
printf("Preparing for reading bytes...\n");
memset(buf_r,0,sizeof(buf_r));
/* 打開管道 */
fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
if(fd==-1)
{
perror("open");
exit(1);
}
while(1)
{
memset(buf_r,0,sizeof(buf_r));
if((nread=read(fd,buf_r,100))==-1)
{
if(errno==EAGAIN)
printf("no data yet\n");
}
printf("read %s from FIFO\n",buf_r);
sleep(1);
}
pause(); /*暫停,等待信号*/
unlink(FIFO); //删除檔案
}
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"
main(int argc,char** argv)
{
int fd;
char w_buf[100];
int nwrite;
/*打開管道*/
fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
if(argc==1)
{
printf("Please send something\n");
exit(-1);
}
strcpy(w_buf,argv[1]);
/* 向管道寫入資料 */
if((nwrite=write(fd,w_buf,100))==-1)
{
printf("The FIFO has not been read yet.Please try later\n");
}
else
printf("write %s to the FIFO\n",w_buf);
}
需要注意的是,調用 open() 打開有名管道的程序可能會被阻塞。但如果同時以讀寫方式 ( O_RDWR ) 打開,則一定不會導緻阻塞;如果以隻讀方式 ( O_RDONLY ) 打開,則調用 open() 函數的程序将會被阻塞直到有寫方打開管道;同樣以寫方式 ( O_WRONLY ) 打開也會阻塞直到有讀方打開管道。
1. 在用open打開FIFO時有可能會阻塞,原因就是目前隻有讀端或寫端存在。換句話說,如果程式在打開FIFO時指定了隻讀方式/隻寫方式,那麼該程序對于打開的FIFO來說就是一個讀端/寫端。如果指定的是讀寫方式,那麼程序即是讀端又是寫端。
2. 從FIFO中讀資料時(用read函數),如果沒有資料,預設是阻塞等待,直到有資料被寫入FIFO。如果read函數傳回0,說明該FIFO所有的寫端都已關閉,程式要做相應的處理。向FIFO寫入資料時(使用write函數),如果FIFO有足夠空間,write函數會傳回寫入的位元組數;如果空間不夠,write函數會阻塞,直到寫完為止。當所有的讀端都關閉時,再向FIFO寫資料會出錯。核心會向寫程序發管道斷裂的信号(SIGPIPE), 進而終止該程序。處理的辦法有兩種:程式以讀寫方式打開FIFO或是在程式中捕捉SIGPIPE信号,由使用者自行處理。