linux下進程間通信(2)

1.消息隊列

消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。

2.消息隊列結構定義

struct msqid_ds *msgque[MSGMNI]向量:
  • 1

msgque[MSGMNI]是一個msqid_ds結構的指針數組,每個msqid_ds結構指針代表一個系統消息隊列,msgque[MSGMNI]的大小爲MSGMNI=128,也就是說系統最多有MSGMNI=128個消息隊列。

3.創建一個消息隊列?

int msgget(key_t, key, int msgflg);  
  • 1

msgflg是一個權限標誌,表示消息隊列的訪問權限,它與文件的訪問權限一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的消息隊列不存在時創建一個消息隊列,如果key所命名的消息隊列存在時,IPC_CREAT標誌會被忽略,而只返回一個標識符。

4.將消息添加到消息隊列

int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);  
  • 1

msgid是由msgget函數返回的消息隊列標識符。
msg_ptr是一個指向準備發送消息的指針,但是消息的數據結構卻有一定的要求,指針msg_ptr所指向的消息結構一定要是以一個長整型成員變量開始的結構體,接收函數將用這個成員來確定消息的類型。所以消息結構要定義成這樣:

struct my_message{  

    long int message_type;  

    /* The data you wish to transfer*/  

};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

msg_sz是msg_ptr指向的消息的長度,注意是消息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型消息類型成員變量的長度。
msgflg用於控制當前消息隊列滿或隊列消息到達系統範圍的限制時將要發生的事情。
如果調用成功,消息數據的一分副本將被放到消息隊列中,並返回0,失敗時返回-1.

5.如何從一個消息隊列中獲取消息?

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
  • 1

msgid, msg_ptr, msg_st的作用也函數msgsnd函數的一樣。
msgtype可以實現一種簡單的接收優先級。如果msgtype爲0,就獲取隊列中的第一個消息。如果它的值大於零,將獲取具有相同消息類型的第一個信息。如果它小於零,就獲取類型等於或小於msgtype的絕對值的第一個消息。
msgflg用於控制當隊列中沒有相應類型的消息可以接收時將發生的事情。
調用成功時,該函數返回放到接收緩存區中的字節數,消息被複制到由msg_ptr指向的用戶分配的緩存區中,然後刪除消息隊列中的對應消息。失敗時返回-1.

6.共享內存

   共享內存是運行在同一臺機器上的進程間通信最快的方式,因爲數據不需要在不同的進程間複製。通常由一個進程創建一塊共享內存區,其餘進程對這塊內存區進行讀寫。得到共享內存有兩種方式:映射/dev/mem設備和內存映像文件。前一種方式不給系統帶來額外的開銷,但在現實中並不常用,因爲它控制存取的將是實際的物理內存,在Linux系統下,這隻有通過限制Linux系統存取的內存纔可以做到,這當然不太實際。常用的方式是通過shmXXX函數族來實現利 用共享內存進行存儲的。

7.函數是shmget有什麼作用

int shmget(key_t key, int size, int flag);
  • 1

   這個函數有點類似大家熟悉的malloc函數,系統按照請求分配size大小的內存用作共享內存。Linux系統內核中每個IPC結構都有的一個非負整數 的標識符,這樣對一個消息隊列發送消息時只要引用標識符就可以了。這個標識符是內核由IPC結構的關鍵字得到的,這個關鍵字,就是上面第一個函數的key。數據類型key_t是在頭文件sys/types.h中定義的,它是一個長整形的數據。在我們後面的章節中,還會碰到這個關鍵字。所以,函數shmget,它的作用是可以獲得一個共享存儲標識符。

8.當共享內存創建後,其餘進程該如何將共享存儲標識符接到自身的地址空間中?

當共享內存創建後,其餘進程可以調用shmat()將其連接到自身的地址空間中。

void *shmat(int shmid, void *addr, int flag);
  • 1

shmid爲shmget函數返回的共享存儲標識符,addr和flag參數決定了以什麼方式來確定連接的地址,函數的返回值即是該進程數據段所連接的實際地址,進程可以對此進程進行讀寫操作。
   使用共享存儲來實現進程間通信的注意點是對數據存取的同步,必須確保當一個進程去讀取數據時,它所想要的數據已經寫好了。通常,信號量被要來實現對共享存儲數據存取的同步,另外,可以通過使用shmctl函數設置共享存儲內存的某些標誌位如SHM_LOCK、SHM_UNLOCK等來實現。

9.何爲信號量?

  信號量又稱爲信號燈,它是用來協調不同進程間的數據對象的,而最主要的應用是前一節的共享內存方式的進程間通信。本質上,信號量是一個計數器,它用來記錄對某個資源(如共享內存)的存取狀況。

10.一般說來,爲了獲得共享資源,進程可以進行那些操作?

  (1) 測試控制該資源的信號量。
  (2) 若此信號量的值爲正,則允許進行使用該資源。進程將信號量減1。
  (3) 若此信號量爲0,則該資源目前不可用,進程進入睡眠狀態,直至信號量值大於0,進程被喚醒,轉入步驟(1)。
  (4) 當進程不再使用一個信號量控制的資源時,信號量值加1。如果此時有進程正在睡眠等待此信號量,則喚醒此進程。

發佈了38 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章