目錄
共享內存空間
共享內存是在用戶空間還是內核空間?——用戶空間
共享內存的生命周期
如何使用共享內存
共享內存的權限
共享內存是進程間通信中,速度最快的方式:
共享內存的缺點:
進程間通信標準:
- system V---共享內存
- linux內核支持了這種標準,專門設計了一個IPC通信模塊,對于我們來說就是通信接口的設計
共享內存空間
共享內存是一種進程間通信的機制,即不同進程的虛擬內存空間(虛擬內存地址不需要相同),映射到相同的物理內存中。如果某個進程向共享內存寫入數據,所做的改動將【立即影響到】【同時訪問】(加了鎖的就不算“同時可以訪問")同一段共享內存的任何其他進程
在Linux中,每個進程都有屬于自己的進程控制塊(PCB)和地址空間(Addr Space),并且都有一個與之對應的頁表,負責將進程的虛擬地址與物理地址進行映射,通過內存管理單元(MMU)進行管理。兩個不同的虛擬地址通過頁表映射到物理空間的同一區域,它們所指向的這塊區域即共享內存
我們把將物理內存中的某段空間映射到多個進程的虛擬地址空間中的這種通信方式,叫做“共享內存”
在操作系統內,有多個共享內存同時存在,所以操作系統要將它們都管理起來
-
先描述再組織
-
共享內存一定會有對應的描述共享內存的內核結構。有這一點后,再加上物理內存。
-
進程與共享內存的關系就是內核數據結構之間的關系。進程的內核數據結構與共享內存的數據結構
在共享內存中,存在引用計數,當引用計數為0時,表示沒有進程在使用這塊共享內存,此時就會被操作系統釋放掉
共享內存是在用戶空間還是內核空間?——用戶空間
共享內存的接口,system V的特性
key:用來標識共享內存的唯一性
size:共享內存的大小
shmflg:共享內存創建的選項
怎么評估共享內存存在還是不存在?
怎么保證兩個不同的進程,拿到的就是同一個內存?
- 手動構建key
- 查看一個已經創建的共享內存
ipcs -m
- 刪除共享內存
ipcrm -m +共享內存id
能不能使用key來代替id?
不能。為什么?
key是要給內核進行區分唯一性的。用戶使用指令管理共享內存是在用戶層的,而指令內部是對系統調用進行了封裝的。也就是說,指令是運行在用戶層的,而key是給OS用的,所以不能使用key來代替id
- 代碼刪除共享內存
void Destroy(){if(_shmid == gdefaultid)return;int n=shmctl(_shmid,IPC_RMID,nullptr);if(n > 0){printf("shmctl delete shm: %d success!\n",_shmid);}else{EXR_EXIT("shmctl\n");}}
共享內存的生命周期
-
共享內存的生命周期隨內核。
-
如果進程沒有顯示的刪除對應的共享內存,即便進程退出了,ipc資源依舊被占用
如何使用共享內存
使用共享內存需要先把共享內存映射到進程的地址空間當中。
怎么映射的?
操作系統提供了一個系統調用shmat。調用這個系統調用的進程會把自己的堆棧之間的映射區和隊友的共享內存建立映射。
成功:返回共享內存起始的虛擬地址
失敗:-1
shmat,將共享內存掛接到進程的地址空間中
共享內存的權限
共享區屬于用戶空間
共享內存是進程間通信中,速度最快的方式:
-
兩個進程都映射了這塊空間,映射之后讀寫直接被對方看到
-
不需要進行系統調用進行讀取或者寫入內容,直接以指針地址的方式訪問空間
共享內存的缺點:
-
通信雙方沒有所謂的同步機制
-
因為沒有同步機制,所以會導致數據不一致
共享內存沒有保護機制
如果非得將共享內存保護起來呢?