概念
不同進程之間共享的內存通常為同一段物理內存。進程可以將同一段物理內存連接到他們自己的地址空間中,所有的進程都可以訪問共享內存中的地址。共享內存是兩個正在運行的進程之間共享和傳遞數據的一種非常有效的方式。
原理
在Linux中,每個進程都有屬於自己的進程控制塊(PCB)和地址空間,並且都有一個與之對應的頁表,負責將進程的虛擬地址與物理地址進行映射,通過內存管理單元(MMU)進行管理。兩個不同的虛擬地址通過頁表映射到物理空間的同一區域,它們所指向的這塊區域即共享內存。
共享內存是在進程創建之前,考慮到數據通信的需要而創建的,進程的地址空間是在進程創建的時候分配的
1、進程的地址空間是在創建之初就分配好了
2、進程的地址空間是虛擬內存,32位機器上進程空間的大小為4G(0~3G是用戶空間,3~4G是內核空間)
3、如果某個進程向共享內存寫入數據,所做的改動將立即影響到可以訪問同一段共享內存的任何其他進程。
4、所以共享內存的進程之間 ,讀寫操作要互斥,確保一個進程在寫的時候不能被讀,因此我們使用信號量來實現同步與互斥
信號量
信號量的使用主要是用來保護共享資源,使得資源在一個時刻只有一個進程(線程)所擁有
信號量的值為正的時候,說明它空閑。
所測試的線程可以鎖定而使用它。若為0,說明它被占用,測試的線程要進入睡眠隊列中,等待被喚醒。
對信號量的操作
-
P(sv):如果sv的值大於零,就給它減1;如果它的值為零,就掛起該進程的執行
-
V(sv):如果有其他進程因等待sv而被掛起,就讓它恢復運行,如果沒有進程因等待sv而掛起,就給它加1.
進程的通信方式
管道、消息隊列、共享內存,信號量,socket,信號,文件鎖
管道
1、匿名管道:
概念:在內核中申請一塊固定大小的緩沖區,程序擁有寫入和讀取的權利,一般使用fork函數實現父子進程的通信。
2、命名管道:
概念:在內核中申請一塊固定大小的緩沖區,程序擁有寫入和讀取的權利,沒有血緣關系的進程也可以進程間通信。
3、特點:
1、面向字節流,
2、生命周期隨內核
3、自帶同步互斥機制。
4、半雙工,單向通信,兩個管道實現雙向通信。
消息隊列
概念:在內核中創建一隊列,隊列中每個元素是一個數據報,不同的進程可以通過句柄去訪問這個隊列。
消息隊列提供了⼀個從⼀個進程向另外⼀個進程發送⼀塊數據的⽅法。
每個數據塊都被認為是有⼀個類型,接收者進程接收的數據塊可以有不同的類型值
消息隊列也有管道⼀樣的不⾜,就是每個消息的最⼤⻓度是有上限的(MSGMAX),
每個消息隊 列的總的字節數是有上限的(MSGMNB),系統上消息隊列的總數也有⼀個上限(MSGMNI)
特點:
1、 消息隊列可以認為是一個全局的一個鏈表,鏈表節點鍾存放着數據報的類型和內容,有消息隊列的標識符進行標記。
2、消息隊列允許一個或多個進程寫入或者讀取消息。
3、消息隊列的生命周期隨內核。
4、消息隊列可實現雙向通信。
信號量
1、概念
在內核中創建一個信號量集合(本質是個數組),數組的元素(信號量)都是1,使用P操作進行-1,使用V操作+1,
1、P(sv):如果sv的值⼤大於零,就給它減1;如果它的值為零,就掛起該進程的執⾏ 。
2、V(sv):如果有其他進程因等待sv而被掛起,就讓它恢復運⾏,如果沒有進程因等待sv⽽掛起,就給它加1。
PV操作用於同一進程,實現互斥。
PV操作用於不同進程,實現同步。
2、功能:
對臨界資源進行保護。
共享內存
1、概念:
將同一塊物理內存一塊映射到不同的進程的虛擬地址空間中,實現不同進程間對同一資源的共享。
共享內存可以說是最有用的進程間通信方式,也是最快的IPC形式。
2、特點:
1、不用從用戶態到內核態的頻繁切換和拷貝數據,直接從內存中讀取就可以。
2、共享內存是臨界資源,所以需要操作時必須要保證原子性。使用信號量或者互斥鎖都可以。
3、生命周期隨內核。
總結
所有的以上的方式都是生命周期隨內核,不手動釋放就不會消失。