1. 程式人生 > >linux下程序間通訊的幾種主要方式簡介

linux下程序間通訊的幾種主要方式簡介

      共享記憶體是執行在同一臺機器上的程序間通訊最快的方式,因為資料不需要在不同的程序間複製。通常由一個程序建立一塊共享記憶體區,其餘程序對這塊記憶體區進行讀寫。共享記憶體往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。 
首先要用的函式是shmget,它獲得一個共享儲存識別符號。

#i nclude <sys/types.h> 
        #i nclude <sys/ipc.h> 
        #i nclude <sys/shm.h> 
        int shmget(key_t key, int size, int flag);

該函式為獲取一個共享記憶體的識別符號,其中key變數可以通過ftok()來獲得

Size為需要的共享記憶體大小,shmflg是共享記憶體標誌:IPC_CREAT、IPC_EXCL、;其中IPC_CREAT用於生成一個新的共享記憶體段,當IPC_CREAT與IPC_EXCL一起使用時,當所要建立的共享記憶體段已經存在時,將會返回一個EEXIST錯誤

   void *shmat(int shmid, const void *shmaddr, int shmflg);

該函式用於將一個共享記憶體段連線到地址空間中,其中shmid為共享記憶體段的識別符號;

shmaddr:

(1) 如果shmaddr為0,則此段連線到由核心選擇的第一個可用地址上。

(2) 如果shmaddr非0,並且沒有指定SHM_RND,則此段連線到shmaddr所指定的地址上。

(3) 如果shmaddr非0,並且指定了SHM_RMD,則此段連線到(shmaddr-(shmaddr mod SHMLBA))

所表示的地址上。SHM_RND命令的意思是:取整。SHMLBA的意思是:低邊界地址倍數,它總是2的乘方。該算式是將地址向下取最近1個SHMLBA的倍數。

除非只計劃在一種硬體上執行應用程式,否則不用指定共享段所連線到的地址。所以一般應指定shmaddr為0,以便由核心選擇地址。

五.訊號量

    訊號量又稱為訊號燈,它是用來協調不同程序間的資料物件的,而最主要的應用是前一節的共享記憶體方式的程序間通訊。本質上,訊號量是一個計數器,它用來記錄對某個資源(如共享記憶體)的存取狀況。一般說來,為了獲得共享資源,程序需要執行下列操作:

(1) 測試控制該資源的訊號量。

(2) 若此訊號量的值為正,則允許進行使用該資源。程序將進號量減1。

(3) 若此訊號量為0,則該資源目前不可用,程序進入睡眠狀態,直至訊號量值大於0,程序被喚醒,轉入步驟(1)。

(4) 當程序不再使用一個訊號量控制的資源時,訊號量值加1。如果此時有程序正在睡眠等待此訊號量,則喚醒此程序。

訊號量函式定義如下:
#include <sys/sem.h>
int semget(key_t key, int num_sems, int sem_flags);

semget函式建立一個新的訊號量或是獲得一個已存在的訊號量鍵值。 

  int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops)

key是一個建我們可以用ftok函式來獲得。key是一個整數值,不相關的程序將通過這個值去訪問同一訊號量。

函式semop用來改變訊號量的狀態,第一個引數,sem_id,是由semget函式所返回的訊號量識別符號。第二個引數,sem_ops,是一個指向結構陣列的指標,其中的每一個結構至少包含下列成員:

struct sembuf {
    short sem_num;
    short sem_op;
    short sem_flg;
}
      第一個成員,sem_num,是訊號量數目,通常為0,除非我們正在使用一個訊號量陣列。sem_op成員是訊號量的變化量值。(我們可以以任何量改變訊號量值,而不只是1)通常情況下中使用兩個值,-1是我們的P操作,用來等待一個訊號量變得可用,而+1是我們的V操作,用來通知一個訊號量可用。
       最後一個成員,sem_flg,通常設定為SEM_UNDO。這會使得作業系統跟蹤當前程序對訊號量所做的改變,而且如果程序終止而沒有釋放這個訊號量,如果訊號量為這個程序所佔有,這個標記可以使得作業系統自動釋放這個訊號量。
semop的所用動作會同時作用,從而避免多個訊號量的使用所引起的競爭條件。我們可以在手冊頁中瞭解關於semop處理更為詳細的資訊

 int semctl(int sem_id, int sem_num, int command, ...);

第一個引數,sem_id,是由semget所獲得的訊號量識別符號。sem_num引數是訊號量數目。

通常的command值為:

SETVAL:用於初始化訊號量為一個已知的值。所需要的值作為聯合semun的val成員來傳遞。在訊號量第一次使用之前需要設定訊號量。
IPC_RMID:當訊號量不再需要時用於刪除一個訊號量標識。