進程間通信的概念
每個進程各自有不同的用戶地址空間,任何一個進程的全局變量在另一個進程中都看不到。因此,進程之間要交換數(shù)據(jù)必須通過內(nèi)核,在內(nèi)核中開辟一塊緩沖區(qū),進程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進程2再從內(nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機制稱為進程間通信 IPC(InterProcess Communication)。
進程間通信的應用場景
(1)數(shù)據(jù)傳輸
一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程,發(fā)送的數(shù)據(jù)量在一個字節(jié)到幾兆字節(jié)之間。
(2)共享數(shù)據(jù)
多個進程想要操作共享數(shù)據(jù),一個進程對共享數(shù)據(jù)的修改,別的進程應該立刻看到。
(3)通知事件
一個進程需要向另一個或一組進程發(fā)送消息,通知它(它們)發(fā)生了某種事件。
(4)資源共享
多個進程之間共享同樣的資源,需要內(nèi)核提供鎖和同步機制。
(5)進程控制
有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。
1.管道
管道是通過調(diào)用 pipe 函數(shù)創(chuàng)建的,fd[0] 用于讀,fd[1] 用于寫。
#include <unistd.h>
int pipe(intfd[2]);
限制:①只支持半雙工通信(單向交替?zhèn)鬏敚虎谥荒茉诟缸舆M程或者兄弟進程中使用。
2.FIFO
FIFO也稱為管道,與上述管道不同的是沒有只能在父子進程中使用的限制。
#include<sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
FIFO 常用于客戶-服務器應用程序中,F(xiàn)IFO 用作匯聚點,在客戶進程和服務器進程之間傳遞數(shù)據(jù)。
3.消息隊列
消息隊列是存放在內(nèi)核中的消息鏈表,每個消息隊列由消息隊列標識符表示。
①?消息隊列允許一個或多個進程向它寫入與讀取消息。
②?管道和消息隊列的通信數(shù)據(jù)都是先進先出的原則
③消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。
4.信號量
信號量是是一個計數(shù)器,用于多個進程之間訪問共享數(shù)據(jù),即進程間同步。
工作機制:信號量的初值(>0),每當有進程申請使用信號量,通過一個P操作來對信號量進行-1操作。當計數(shù)器減到0的時候就說明沒有資源了,其他進程要想訪問就必須等待。當該進程執(zhí)行完之后,就會執(zhí)行V操作來對信號量進行+1操作。
5.共享內(nèi)存
多個進程可以直接讀寫同一塊內(nèi)存空間(最快的 IPC )。
工作機制:將不同進程的虛擬內(nèi)存地址映射到相同的物理內(nèi)存地址,實現(xiàn)共享內(nèi)存。內(nèi)核有一塊內(nèi)存區(qū),可以將進程的私有地址空間映射到該內(nèi)存區(qū),因此進程間可以直接讀寫這一塊內(nèi)存而不需要進行數(shù)據(jù)的拷貝。
6.套接字socket
套接字socket是一種通信機制,實現(xiàn)進程間(本地/跨網(wǎng)絡(luò))的通信。socket是應用層和傳輸層之間的橋梁。
socket通信的基本流程如下: