linux進程間通信

進程間通信:

每個人進程各自有不同的用戶地址空間,任何一個進程的全局變量在另一個進程中都看不到,所以進程之間要交換數據必須通過內核,在內核中開闢一塊緩存區,進程1將數據從用戶空間拷到內核緩衝區,進程2再從內核緩衝區把數據讀走,內核提供的這種機制叫做進程間通信(IPC)。

管道:

一種最基本的IPC機制,由pipe函數創建。

#include<unistd.h>

int pipe(int filedes[2]);

調用pipe函數時在內核中開闢一塊緩衝區(管道)用於通信,它有一個讀端一個寫端,通過filedes參數傳出給用戶程序兩個文件描述符,filedes[0]表示指向管道的讀端,filedes[1]表示指向管道的寫端。所以管道在用戶程序看起來就像打開文件一樣,通過read(filedes[0])或者write(filedes[1]);向這個文件讀寫數據其實是在讀寫內核緩衝區。pipe函數調用成功返回0;失敗返回-1.

管道通信的一般想法:

1、父進程調用pipe開闢管道,得到兩個文件描述符指向管道的兩端。

2、父進程調用fork創建子進程,那麼子進程也用兩個文件描述符指向同一個管道。

3、父進程關閉管道讀端,子進程關閉管道寫端。父進程向管道寫,子進程向管道讀,這樣就可以實現堅持間通信。

管道的限制:

兩個進程通過一個管道只能實現單向通信。

如果希望雙向通信可以再開闢一個管道。

管道的讀寫端通過打開的文件描述符來傳遞,因此要通信的兩個進程必須從他們大的公共祖先那裏繼承管道文件描述符。管道通信需要進程之間有關係。

使用管道需要注意的四種特殊情況:

1、如果所用指向管道寫端的文件描述符否關閉了(寫端的引用計數等於零),但仍然有進程從管道的讀端讀數據,那麼管道中剩餘的數據都被讀取後,再次read會返回0,就像讀到文件末尾一樣。

2、如果有指向寫端的文件描述符沒有關閉(寫端的引用計數大於0),但是沒有向管道寫入數據,這時用進程從管道讀數據,那麼管道剩餘的數據會被讀取,再次read會阻塞,直到管道中有數據可讀纔讀取數據返回。

3、如果所有指向管道讀端的文件描述符都關閉了(讀端的引用計數等於0)這時候有進程向管道的寫端write,那麼該進程會收到信號SIGPIPE,通常會導致進程異常終止。

4、如果有指向管道讀端的文件描述符沒關閉(讀端的引用計數大於0),但是讀端的進程不讀取數據,這時進程向管道寫入數據,那麼在管道寫滿時,再次write會阻塞,直到管道中有空位置纔再次寫入數據並返回。

命名管道概念:

命名管道是一個設備文件,只要可以訪問路徑,就能夠通過FIFO相互通信。(FIFO總是按照先進先出的原則工作,第一個被寫入的數據將首先從管道中讀出)。

命名管道和管道的使用方法基本相同。但因爲命名管道是一個存在於硬盤的文件,而管道是存在於內存的特殊文件,在使用命名管道前必須先調用open()函數打開命名管道。

要注意的是,調用open()打開命名管道的進程可能會被阻塞。但是用讀寫方式(O_RDWR)打開,一定不會阻塞;如果只用讀方式(O_RDONLY)打開,則調用open()函數的進程會被阻塞直到有寫方打開管道;同樣以寫方式(O_WRONLY)打開,也會阻塞直到有讀方式打開管道。


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