用戶空間、內(nèi)核空間
Linux分為內(nèi)核進(jìn)程和用戶進(jìn)程:
1、內(nèi)核進(jìn)程共享一塊內(nèi)存空間,稱為內(nèi)核空間。
2、內(nèi)核進(jìn)程不能訪問(wèn)用戶空間。
3、用戶進(jìn)程有自獨(dú)立的地址空間,彼此隔離。
4、用戶進(jìn)程通過(guò)系統(tǒng)調(diào)用,從用戶態(tài)陷入內(nèi)核態(tài),可以訪問(wèn)到內(nèi)核空間。

進(jìn)程通信的手段
1、共享內(nèi)存
獲取一塊內(nèi)存區(qū)域,兩個(gè)用戶進(jìn)程都能夠訪問(wèn),便可實(shí)現(xiàn)進(jìn)程間通信。

2、系統(tǒng)調(diào)用
借用內(nèi)核態(tài)可以訪問(wèn)內(nèi)核空間的特性,通過(guò)內(nèi)核空間進(jìn)行數(shù)據(jù)傳輸:
用戶進(jìn)程A通過(guò)系統(tǒng)調(diào)用,進(jìn)入內(nèi)核態(tài),向內(nèi)核空間寫(xiě)入數(shù)據(jù);
用戶進(jìn)程B通過(guò)系統(tǒng)調(diào)用,進(jìn)入內(nèi)核態(tài),從內(nèi)核空間讀取數(shù)據(jù)。

進(jìn)程通信的本質(zhì):找到這樣一塊區(qū)域(如內(nèi)存、磁盤(pán)、其他設(shè)備等),兩個(gè)進(jìn)程都能訪問(wèn)到,再通過(guò)這塊區(qū)域進(jìn)行數(shù)據(jù)交互。
Linux中的進(jìn)程通信
linux中主要的進(jìn)程通信包括以下幾種:
| 通信方式 | 性能/拷貝 | 安全性 | 穩(wěn)定性 | 用途 |
|---|---|---|---|---|
| 信號(hào)(signal) | - | - | - | 事件通知,不適用于信息交換 |
| 信號(hào)量(Semaphore) | - | - | - | 計(jì)數(shù)器,常被用作鎖機(jī)制 |
| 管道(pipe) | 低/2 | - | 1對(duì)1 | - |
| 消息隊(duì)列(Message queues) | 低/2 | - | - | - |
| 套接字(Socket) | 低/2 | 高 | C/S架構(gòu) | - |
| 共享內(nèi)存(Share Memory) | 高/0 | 考慮并發(fā) | 用戶維護(hù) | - |
| Binder | 中/1 | 高:進(jìn)程UID標(biāo)識(shí),鑒別身份 | C/S架構(gòu) | - |
管道
管道是利用內(nèi)核空間進(jìn)行進(jìn)程通信的,當(dāng)進(jìn)程創(chuàng)建一個(gè)管道之后,會(huì)返回兩個(gè)文件描述符Fd[0]、Fd[1];Fd[0]用來(lái)讀數(shù)據(jù),F(xiàn)d[1]用來(lái)寫(xiě)數(shù)據(jù)。
![]() 當(dāng)進(jìn)程創(chuàng)建一個(gè)管道之后的連接情況
|
![]() 當(dāng)父進(jìn)程創(chuàng)建子進(jìn)程之后的連接情況
|
|---|
此時(shí),如果想通過(guò)父進(jìn)程向子進(jìn)程通信,可以關(guān)閉父進(jìn)程的Fd[0]和子進(jìn)程的Fd[1];反之亦然。
![]() 父進(jìn)程寫(xiě)、子進(jìn)程讀
|
![]() 父進(jìn)程讀、子進(jìn)程寫(xiě)
|
|---|
管道的兩次拷貝分別發(fā)生在Fd[1]寫(xiě)(將數(shù)據(jù)從用戶空間拷貝到內(nèi)核空間)、Fd[0]讀(將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間)。管道通信需要滿足幾個(gè)條件:
1、互斥:讀寫(xiě)操作必須互斥進(jìn)行
2、同步:讀寫(xiě)進(jìn)程等待與喚醒
3、對(duì)方存在:只有判斷對(duì)方存在時(shí)才能通信
消息隊(duì)列
消息隊(duì)列在內(nèi)核空間維護(hù)了一個(gè)msgque鏈表。


通過(guò)wait-signal實(shí)現(xiàn)send原語(yǔ)
Procedure Send(rec, a); { rec為接收進(jìn)程, a為發(fā)送區(qū)}
Begin
Getbuf(a.size, i); {從自由區(qū)中申請(qǐng)空緩沖區(qū)i}
i.sender:=a.sender; {把消息從a處copy到緩沖區(qū)i}
i.size:=a.size;
i.text:=a.text;
i.next:=0;
GetID(PCB set, rec.j); {獲接收進(jìn)程內(nèi)部標(biāo)識(shí)符j}
wait(j.mutex);
insert(j.mq , i); {把緩沖區(qū)i掛到進(jìn)程rec消息鏈尾}
signal(j.mutex);
signal(j.sm);
END
關(guān)于Socket相關(guān)資料,推薦以下文章:
1、Socket與內(nèi)核調(diào)用深度分析
2、Linux中本機(jī)和本機(jī)Socket通信會(huì)走網(wǎng)卡嗎?



