linux 進程管道

進程訪問機制,各個進程比較獨立,不能訪問對方的單元,但是進程不可能永遠時對立的,必須涉及到信息的交互。

進程間通信傳遞兩種信息,一種時標記、標誌也就是狀態(同步的狀態信號量,異步的狀態信號),另外一種是數據,即內容(傳送的文件,磁盤、內存(有序的消息隊列、共享內存,socket)、普通上鎖文件、管道(有名管道、無名管道)、mmap。

管道的實現原理:

文件實現進程間的通信,普通文件可以同時被多個進程訪問而無法相互感知,所以,不能使用普通文件來實現進程間通信(flock這個機制實際上是一個同步概念),因此出現了管道這個特殊的文件。由操作系統來維護的一段“內核內存空間”,類似與FIFO這種管道隊列,因此稱爲管道。

(1)上層應用時,它就是文件,可以使用read/write/close等操作。

(2)它是特殊的文件,操作時不能進行lseek.

(3)管道是單向的。如果要實現雙向,只能創建兩個管道。

具體編程

(1)創建無名管道。pipe

int pipe(int pipefd[2]);

pipefd在調用者是一個數組,用來存放管道的兩個返回文件描述符。

pipefd[0]用來讀,pipefd[1]用來寫。

(2)讀寫read/write函數。

read(fd[0],);

write(fd[1]);

(3)無名管道的限制

讀寫的限制

要進程讀,就一定要有人寫,要進行寫,就一定有人要讀。

(1)以阻塞方式讀無名管道,如果當前沒有一個進程(包括自己)與這個管道的寫端關聯,讀操作立即返回。

如果有數據,且大於欲讀出的數據量,讀出試圖讀取的數據大小。

如果有數據,但是小於欲讀出的數據量,讀出所有管道數據。

如果沒有數據,立即返回0.

(2)以阻塞方式讀無名管道,有一個及以上進程(包括自己)與這個管道的寫端關聯,讀操作做如下:

如果有數據,現有數據小於期望讀取的值,讀立即返回現有數據。

如果有數據,現有數據大於期望讀取的值,讀立即返回期望讀寫數據。

如果沒有 數據,則阻塞,當有數據寫入後,喚醒讀操作。

(3)以阻塞方式寫無名管道,如果有一個或者多個進程與這個管道的獨端關聯,如果當前管道已經滿,則阻塞,當有進程讀出數據,喚醒寫操作。

(4)以阻塞方式寫無名管道,如果沒有進程與這個管道的讀端關聯,黨有進程淨產生SIFPIPE的信號,而這個信號的默認操作時種植當前進程,因此很多時候測試無效果,需要安裝信號。

重定向及無名管道應用

<輸入重定向,要求這個輸入文件必須存在。

>輸出重定向,如果文件不存在,創建,否則覆蓋。

>>輸出重定向,如果文件不存在,創建,否則追加。

2>

2>以上時對錯誤輸出信息重定向到文件。

實現ps aux | grep test 或者 who | sort

(1)兩個通信進程,ps aux 用execX函數來執行,grep init 是另一個進程,用execX來執行。爲了方便,由一個父親進程來創建這兩個進程的通信。

(2)管道。這個管道要被兩個進程都訪問,父子進程。

(3)實現重定向。文件描述符複製。在ps aux中輸出重定向,即將fd[1]複製爲1,即以後寫入到1中的數據全部寫入到fd[1]中。默認情況下,一個進程的0,1,22三個文件描述符是默認打開的。因此,怎末來複制實現。

int dup(int oldfd);

複製oldfd爲當前進程中最小未使用的文件描述符。

close(1);

dup(fd[1]);

如果0是默認打開的,dup函數返回1,以後寫入到1的內容也就寫入到fd[1]中。

int dup2(int oldfd,int newfd);

更方便是使用dup2,將oldfd複製爲newfd,如果newfd關聯打開的一個文件,則關閉這個文件。再複製。

dup2(fd[1],1)

能夠保證fd[1]爲後續輸入出重定向的文件。

文件描述符的複製與新開文件是有本質區別的。複製文件描述時,兩個文件描述共享文件表項,即共享讀寫文件。

新打開一個文件,其實時額外的申請文件表項,兩者互不影響。

無名的管道,通信方向要了解創建的管道對應的文件描述符,因此,多用於父子進程或者親緣關係之間,因爲可以方便的實現文件描述符傳遞,

在重定向中還有流的重定向。popen/pclose.

 

 

 

 

 

 

 

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