Linux:簡單理解System V -- 共享內存、消息隊列、信號量


共享內存

本質原理: 多個進程要是映射同一塊物理內存,就可以通過這塊內存實現數據共享

  1. 在物理內存上開闢一塊內存空間
  2. 多個進程可以將這塊物理內存映射到自己的虛擬地址空間
  3. 通過虛擬地址進行頁表映射直接訪問這塊物理內存,實現數據共享

特性:

  1. 最快的進程間通信方式
  2. 生命週期隨內核

注意事項:

共享內存的操作是不安全的(並不會自動具備同步與互斥關係,需要操作用戶進行控制)

操作: 代碼操作流程/具體的接口+命令操作ipcs/ipcrm

爲什麼共享內存是最快的進程間通信方式?

對於管道這種通信方式,涉及到兩次用戶態與內核態之間的數據拷貝,將數據寫入管道,從管道讀取數據;對於共享內存這種通信方式,它是直接通過虛擬地址訪問物理內存實現數據共享,相較於管道少了兩次用戶態與內核態之間的數據拷貝操作,因此速度最快。

注意: 共享內存沒有同步和互斥特性,操作會存在安全隱患!!!

共享內存的生命週期:

隨內核,在物理內存開闢空間,信息存儲在內核;共享內存是屬於內核的一個進程間通信的資源;不會隨着進程的退出而退出;內核重啓或者手動釋放會釋放該空間,否則一直存在於內核。

共享內存的操作流程:

  1. 創建共享內存(開闢物理空間—具有標識符)
  2. 將共享內存映射到各個進程的虛擬地址空間
  3. 直接通過虛擬地址進行內存操作
  4. 解除映射關係
  5. 刪除共享內存

共享內存函數

  1. shmget函數
int shmget(key_t key, size_t size, int shmflg)

功能: 用來創建共享內存

參數:

  • key: 內核中共享內存的標識符,多個進程通過相同的標識符可以打開同一塊共享內存
  • size: 共享內存大小 — 以內存頁爲單位進行分配
  • shmflg: IPC_CREAT - 存在則打開,不存在則創建 | IPC_EXCL 與 IPC_CREAT 同時使用,若存在則報錯,不存在則創建 | 權限

返回值: 返回一個非負整數 - 共享內存的操作句柄,失敗返回-1

生成一個key值:

key_t futon(const char *pathname, int prom_id) - 通過inode節點號與projid合成一個key
  1. shmat函數
void *shmat(int shmid, void *shmaddr, int shmflg);

功能: 將共享內存段連接到進程地址空間

參數:

  • shmid: shmget反回的共享內存標示
  • shmaddr:映射到虛擬地址空間的首地址,通常置 NULL,(指定連接地址)
  • shmflg: 映射成功之後對共享內存可以進行的操作 SHM_RDONLY-只讀(前提是有讀的權限)/ 0-默認可讀可寫

返回值: 成功返回共享內存映射的虛擬空間的首地址,通過這個地址對內存進行操作,失敗返回-1

  1. shmdt函數
int shmdt(const void *shmaddr);

功能: 解除映射關係

參數:

  • shmaddr:映射到虛擬地址空間的首地址(shmat所返回的指針)

返回值: 成功返回0,失敗返回-1

注意:

當刪除共享內存的時候,共享內存並不會立即被刪除,(因爲有可能會造成正在訪問的進程崩潰),只是將其狀態置爲被銷燬狀態,移除標示。(表示這塊共享內存不再繼續接受映射鏈接,當這塊共享內存的映射鏈接數爲0的時候,則纔會真正被刪除)

  1. shmctl函數
int shmctl(int shmid,int cmd, struct shmid_ds *buf)

**功能:**用於控制共享內存

參數

  • shmid:由shmget返回的共享內存標識碼
  • cmd:對共享內存想要進行的操作 — IPC_RMID-刪除共享內存
  • buf:用於獲取/設置共享內存信息的結構,不使用則置NULL

返回值: 成功返回0;失敗返回-1
在這裏插入圖片描述

操作系統中進程間通信資源的命令操作:

  • ipcs 查看進程間通信資源
  • -m 共享內存
  • -q 查看消息隊列
  • -s 查看信號量
  • ipcrm 刪除進程間通信資源(ipcrm -m shmid)

消息隊列

本質:

內核中的一個具有標識符的優先級隊列,多個進程通過向同一個隊列中添加節點和獲取節點實現通信

  • 消息隊列提供了一個從一個進程向另外一個進程發送一塊數據的方法
  • 每個數據塊都被認爲是有一個類型,接收者進程接收的數據塊可以有不同的類型值

特性:

  1. 自帶同步與互斥
  2. 生命週期隨內核
  3. 數據傳輸自帶優先級

注意事項:

struct msgbuf{ int type; char buf[***]}; 這個結構體需要用戶自己定義
msgget     創建隊列
msgsnd     添加節點
msgrcv     獲取節點 

信號量

用於實現進程間的同步與互斥(共享內存本身是不提供同步與互斥的,操作存在安全隱患,因此需要使用信號量搭配)

  • 互斥:保證同一時間只有一個進程訪問臨界資源實現臨界資源的互斥訪問保證安全性
  • 同步:通過一種條件的判斷,不能訪問則等待,能訪問再喚醒,實現對臨界資源訪問的合理性

本質:

內核中的計數器+pcb等待隊列(對資源進行計數

同步的實現: 信號量是一個對資源的計數,可以通過計數判斷是否能夠獲取一個資源進行處理;若計數 <= 0,則表示不能獲取,則需要等待(加入pcb隊列),這時候若其他進程生產一個資源,再喚醒;若計數 > 0表示能獲取

互斥的實現: 通過只有0/1的計數器,實現對臨界資源訪問狀態的標記;在訪問臨界資源之前先獲取信號量,計數-1;若計數<0則使進程等待(將進程pcb加入隊列中);否則則可以對臨界資源進行訪問並且在訪問完畢之後,則對計數+1,喚醒一個進程(將一個pcb出隊,置位運行狀態)


如果本篇博文幫助到了您,留個贊吶~~

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