進程間通信

這裏寫圖片描述
一、管道

管道的作用是在具有親緣關係的進程之間傳遞消息,所以管道並不是只可以用於父子進程通信,也可以在兄弟進程之間還可以用在祖孫之間等,反正只要共同的祖先調用了pipe函數,打開的管道文件就會在fork之後,被各個後代所共享。不過由於管道是字節流通信,沒有消息邊界,多個進程同時發送的字節流混在一起,則無法分辨消息,所有管道一般用於2個進程之間通信,另外管道的內容讀完後不會保存,管道是單向的,一邊要麼讀,一邊要麼寫,不可以又讀又寫,想要一邊讀一邊寫,那就創建2個管道。
這裏寫圖片描述

管道的本質是內核維護了一塊緩衝區與管道文件相關聯,對管道文件的操作,被內核轉換成對這塊緩衝區內存的操作。

int fd[2]; fd[0] ==>read ———– fd[1]==>write
可以用dup函數將管道作爲標準輸入輸出;
當寫數據的管道沒有關閉,而又沒有數據可讀時,read調用通常會阻塞,但是當寫數據的管道關閉時,read調用將會返回0而不是阻塞。注意,這與讀取一個無效的文件描述符不同,read一個無效的文件描述符返回-1。

二、有名管道

1.有名管道是創建一個真實的文件(存在於文件系統中),使用時打開文件open()/結束後關閉文件close();和普通文件不同的是open()時只能以讀/寫的方式打開,不能可讀可寫。
2.創建管道==》mkfifo filename
3.open()中可以設置管道是否爲非阻塞的(默認是阻塞的),

注:open調用的阻塞:

》對於以只讀方式(O_RDONLY)打開的FIFO文件,如果open調用是阻塞的(即第二個參數爲O_RDONLY),除非有一個進程以寫方式打開同一個FIFO,否則它不會返回;如果open調用是非阻塞的的(即第二個參數爲O_RDONLY | O_NONBLOCK),則即使沒有其他進程以寫方式打開同一個FIFO文件,open調用將成功並立即返回。
》對於以只寫方式(O_WRONLY)打開的FIFO文件,如果open調用是阻塞的(即第二個參數爲O_WRONLY),open調用將被阻塞,直到有一個進程以只讀方式打開同一個FIFO文件爲止;如果open調用是非阻塞的(即第二個參數爲O_WRONLY | O_NONBLOCK),open總會立即返回,但如果沒有其他進程以只讀方式打開同一個FIFO文件,open調用將返回-1,並且FIFO也不會被打開

有名管道的安全問題:
多個進程向一個fifo寫時,會發生錯亂,解決::在一個以O_WRONLY(即阻塞方式)打開的FIFO中, 如果寫入的數據長度小於等待PIPE_BUF,那麼或者寫入全部字節,或者一個字節都不寫入。如果所有的寫請求都是發往一個阻塞的FIFO的,並且每個寫記請求的數據長度小於等於PIPE_BUF字節,系統就可以確保數據決不會交錯在一起。

三、消息隊列

使用流程:
1、使用int msgget(key_t, key, int flg);創建/訪問消息隊列,key鍵值,flg是權限。
2、int msgsend(int id, const void *msg_ptr, size_t msg_sz, int msgflg);添加消息。
3、int msgrcv(int id, void *msg_ptr, size_t msg_st, long int type, int flg);獲取消息。
4、int msgctl(int msgid, int command, struct msgid_ds *buf);控制。

@消息隊列跟命名管道有不少的相同之處,通過與命名管道一樣,消息隊列進行通信的進程可以是不相關的進程,同時它們都是通過發送和接收的方式來傳遞數據的。在命名管道中,發送數據用write,接收數據用read,則在消息隊列中,發送數據用msgsnd,接收數據用msgrcv。而且它們對每個數據都有一個最大長度的限制。
@與命名管道相比,消息隊列的優勢在於,1、消息隊列也可以獨立於發送和接收進程而存在,從而消除了在同步命名管道的打開和關閉時可能產生的困難。2、同時通過發送消息還可以避免命名管道的同步和阻塞問題,不需要由進程自己來提供同步方法。3、接收程序可以通過消息類型有選擇地接收數據,而不是像命名管道中那樣,只能默認地接收。

四、共享內存

1、進程通過調用shmget(Shared Memory GET,獲取共享內存)來分配一個共享內存塊
2、shmat()將這個內存區映射到本進程的虛擬地址空間
3、當一個進程不再須要共享內存時,須要把它從進程地址空間中分離shamdt();
4、shmctl控制對這塊共享內存的使用

<1>共享內存是一種最爲高效的進程間通信方式,進程可以直接讀寫內存,而不需要任何數據的拷貝。
<2>爲了在多個進程間交換信息,內核專門留出了一塊內存區,可以由需要訪問的進程將其映射到自己的私有地址空間。進程就可以直接讀寫這一塊內存而不需要進行數據的拷貝,從而大大提高效率。
<3>由於多個進程共享一段內存,因此也需要依靠某種同步機制。

幾種IPC方式優缺點比較

1、如果用戶傳遞的信息較少,或者只是爲了出發某些行爲。信號是一種簡潔有效的通信方式。但若是進程間要求傳遞的信息量較大或者存在數據交換的要求,就需要考慮別的通信方式了。
2、無名管道與有名管道的區別在於單向通信以及有關聯的進程。
3、消息隊列允許任意進程通過共享隊列來進行進程間通信。並由系統調用函數來實現消息發送和接收之間的同步。從而使得用戶在使用消息緩衝進行通信時不再需要考慮同步問題,使用相對方便。
但是消息隊列中信息的複製需要耗費CPU時間,不適宜信息量大或頻繁操作的場合。
4、消息隊列與管道方式的區別在於,消息隊列可以實現多對多,並需要在內存中實現,而管道可以在內存或磁盤上實現。
5、共享內存無須複製,信息量大是其最大的優勢。但是需要考慮同步問題。

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