Linux之進程間通信之消息隊列,共享內存,信號量

消息隊列

消息隊列的結構有很多,但在這裏講的隊列的結構都是基於鏈表實現的.

進程間通信的實質是:讓不同的進程可以看到相同的資源.

消息隊列的特點:

  • 消息隊列的通信是通過發送有類型數據塊的方法.
  • 每個數據塊都有一個類型,接收方接受的數據塊可以有不同的類型值.
  • 消息隊列的最大長度有限制.(缺點,因爲消息隊列必定要佔用內存,而如果只發送不接受就會耗內存.)

所以:消息隊列提供了一個進程向另一個進程發送了有類型數據塊的方法.

實現消息隊列的相關函數:
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
函數作用:爲創建消息隊列的函數提供參數.
注意:對於這個函數,若函數的參數相同,則函數的返回值相同.

①創建消息隊列的函數:
int msgget(key_t key,int msgflg);
msgflg:與文件的權限mode是相同的.
常用的參數有:
IPC_CREAT:不存在就創建,若存在就打開.
IPC_EXCL:若存在,就失敗.與上面的搭配使用.
函數創建成功就返回非負整數

②消息隊列控制函數
int magctl(int msqid,int cmd,struct msqid_ds *buf);
參數:
    msqid_ds:表示消息隊列
    cmd:函數執行的作用:IPC_RMID(刪除消息隊列)
函數返回值:成功返回0失敗返-1;

③把消息添加到消息隊列中
int msgsnd(int msqid,const void* msgp,size_t msgsz,int msqflg);

④從一個消息隊列中接收消息
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
msgp:指向接受的消息的隊列.
msgsz:消息隊列的長度.
msgtyp:可以實現接收優先級.若爲0,就是普通的隊列.

查看消息隊列的指令:ipcs -q
手動刪除某個消息隊列:ipcrm -q 進程id

這裏是簡單的消息隊列的實現,若需要,請戳

總結消息隊列:
1. 全雙工的通信方式.
2. 面向數據塊.
3. 內置同步互斥機制.
4. 聲明週期隨內核.(可以通過手動刪除和重啓來刪除一個消息隊列).
5. 可以用於任意進程.

共享內存

每個進程都有自己的虛擬內存空間,而物理空間只有一份,當多個進程映射到相同的物理地址後,那麼就可以共同訪問這塊內存.即共享內存.
蹦蹦蹦:共享內存是最快的進程間通信的方式(省略了兩次內存拷貝).但是同時也是不穩定的,由於共同訪問同一塊內存,會產生不可預知的錯誤.

實現共享內存調用的相關函數:
int shmget(key_t key,size_t size,int shmget);
key:共享內存段的名字.
size:共享內存的大小.(按頁的大小向上取整.一般而言頁的大小爲4K)
shmflg:與消息隊列的那個參數相同.

void* shmat(int shmid,const void* shmaddr,int shmflg);
shmaddr:共享內存連接的地址.
成功返回一個指向共享內存的第一個指針,失敗返回-1.

int shmctl(int shmid,int cmd,struct_ds *buf);
cmd:與消息隊列中的那個參數相同.
buf:指向一個保存着共享內存的模式狀態和訪問權限的數據結構.

共享內存的簡單實現,若需要請戳

總結共享內存:
1. 雙向通信全雙工.
2. 用於任意進程間的通信方式.
3. 不存在”面向數據報”和”面向字節流”.
4. 沒有同步互斥機制.
5. 生命週期隨內核.

信號量

爲什麼要有信號量的通信方式?
消息隊列,共享內存以及管道都是可以同時又多個進程去訪問公共資源,可能會引發一系列的問題.而信號量是爲了通過控制其他的通信的公共資源來實現進程間通信.信號量則會負責數據操作的同步,互斥等.

信號量的同步指的是所有的進程按照一定的順序去執行任務,實現對資源的有序訪問.
信號量的互斥指的是當有一個進程在臨界區時,其餘的進程只能等待,等待那個進程出了臨界區.

信號量的PV操作
這裏的信號量指的是二元信號量,非0即1.
P操作:申請使用臨界資源,信號量減一;
V操作:釋放臨界資源,信號量加一.

簡單的實現信號量的代碼,若需要請戳

注意:消息隊列,共享內存以及信號量都是基於system V版本的進程間通信的方式.

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