天天看點

linux中有名管道的使用

有名管道又稱為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信号,由使用者自行處理。