Linux -- 進程間通信之管道

管道是Linux裏的一種文件類型,同時也是Linux系統下進程間通信的一種方式


創建一個管道文件有兩種方式:

1.  Shell 下命令 mkfifo + filename,即創建一個有名管道

2.  C語言裏調用 pipe( ) 函數,創建一個無名管道


有名管道 / 無名管道 

區別:

1.  有名管道在程序外部使用 mkfifo 命令生成,無名管道在程序內部調用 pipe( ) 函數創建;

2.  顧名思義,有名管道有文件名,無名管道沒有文件名;

3.  有名管道生成後直到刪除都存在,無名管道在程序退出時則生命週期結束;

4.  有名管道可以在任意兩個進程間傳輸數據,無名管道只能在父子進程間傳輸數據;

*有名/無名管道都是半雙工

(只能從一端向另一端發送數據,輸入端與輸出端在打開管道時是固定的)


管道文件的特性:

1.  打開管道必須有兩端(兩個進程)同時打開一個管道,分別爲讀(r)和寫(w);讀取端負責從管道中讀取數據,寫入端負責向管道中輸入數據;

2.  當讀端關閉,寫端會收到信號,終止程序;當寫端關閉,讀端不再進入阻塞;

3.  管道文件的大小始終爲0,打開管道文件時,在內存中爲其分配空間,管道關閉後數據消失;Linux默認PIPE_SIZE(一個管道最大存儲大小)爲64k,PIPE_BUF(管道緩衝區)爲4k;當對管道進行 write 操作時,若此時有多個進程同時寫入一個管道,且寫入的字節大小超過PIPE_BUF,則寫操作的數據有可能相互穿插。



管道文件的內存空間有兩個指針 head / tail ,head指針隨讀取數據向後移動,tail指針隨寫入數據向後移動,當指針到文件尾時,會造成讀阻塞 (讀取結束)/ 寫阻塞(空間已滿)


*注意*

當我們調用 pipe( ) 創建無名管道後 fork( ) 以實現父子進程間通信,此時 pipe( ) 生成的兩個 r / w 描述符引用都會加一,在父子進程中同時存在 r / w 兩個描述符,此時應當在父子進程中分別 close 不用的描述符,使 r / w 端只存在一個引用,這樣父子進程間通信時可以正常讀寫響應。


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main()
{	
	char buff[128] = {0};
	pid_t pid;
	int pipefd[2];
	pipe(pipefd);					// creat & open a fifo file

	pid = fork();
	if(pid == -1)
	{
		printf("fork error\n");
		exit(0);
	}
	else if(pid == 0)				// chid process
	{
		close(pipefd[1]);			// close 'w' 
		
		if( read(pipefd[0],buff,128) <= 0)
		{
			printf("read error\n");
			exit(0);
		}
		printf("child : %s\n",buff);
	}
	else						// parent process
	{
		close(pipefd[0]);			// close 'r' fd
		
		printf("input: ");
		fflush(stdout);
		gets(buff);
		if( write(pipefd[1],buff,127) <= 0)
		{
			printf("write error\n");
			exit(0);
		}
	}
	
	close(pipefd[0]);
	close(pipefd[1]);
	
	exit(0);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章