1. 程式人生 > >Linux 下IPC總結(全)

Linux 下IPC總結(全)

System V IPC

    System V IPC指的是AT&T在System V.2發行版中引入的三種程序間通訊工具:(1)訊號量,用來管理對共享資源的訪問 (2)共享記憶體,用來高效地實現程序間的資料共享 (3)訊息佇列,用來實現程序間資料的傳遞。我們把這三種工具統稱為System V IPC的物件,每個物件都具有一個唯一的IPC識別符號(identifier)。要保證不同的程序能夠獲取同一個IPC物件,必須提供一個IPC關鍵字(IPC key),核心負責把IPC關鍵字轉換成IPC識別符號。   

    System V IPC具有相似的語法,一般操作如下:

    (1)選擇IPC關鍵字,可以使用如下三種方式:

       a)IPC_PRIVATE。由核心負責選擇一個關鍵字然後生成一個IPC物件並把IPC識別符號直接傳遞給另一個程序。
       b)直接選擇一個關鍵字。
       c)使用ftok()函式生成一個關鍵字。

    (2)使用semget()/shmget()/msgget()函式根據IPC關鍵字key和一個標誌flag建立或訪問IPC物件。如果key是IPC_PRIVATE;或者key尚未與已經存在的IPC物件相關聯且flag中包含IPC_CREAT標誌,那麼就會建立一個全新的IPC物件。

    (3)使用semctl()/shmctl()/msgctl()函式修改IPC物件的屬性。

    (4)使用semctl()/shmctl()/msgctl()函式和IPC_RMID標誌銷燬IPC例項。

    System V IPC為每個IPC物件設定了一個ipc_perm結構體並在建立IPC物件的時候進行初始化。這個結構體中定義了IPC物件的訪問許可權和所有者:

    struct ipc_perm{
       uid_t uid;   //所有者的使用者id
       gid_t gid;   //所有者的組id
       uid_t cuid;  //建立者的使用者id
       gid_t cgid;  //建立者的組id
       mode_t mode; //訪問模式


       …
    };

    shell中管理IPC物件的命令是ipcs、ipcmk和ipcrm。

1、訊號量(Semaphores)

    System V的訊號量集表示的是一個或多個訊號量的集合。核心為每個訊號量集維護一個semid_ds資料結構,而訊號量集中的每個訊號量使用一個無名結構體表示,這個結構體至少包含以下成員:
    struct{
        unsigned short semval;//訊號量值,總是>=0
        pid_t sempid;  //上一次操作的pid
       …
    
};

    #include <sys/types.h>
    #include <sys/ipc.h>
    
#include <sys/sem.h>
    (1)建立或訪問訊號量
  * int semget(key_t key,int nsems,int flag); 
    nsems指定訊號量集中訊號量的個數,如果只是獲取訊號量集的識別符號(而非新建),那麼nsems可以為0。flag的低9位作為訊號量的訪問許可權位,類似於檔案的訪問許可權;如果flag中同時指定了IPC_CREAT和IPC_EXCL,那麼如果key已與現存IPC物件想關聯的話,函式將會返回EEXIST錯誤。例如,flag可以為IPC_CREAT|0666。

    (2)控制訊號量集
* int semctl(int semid,int semnum,int cmd,union semun arg);
    對semid訊號量集合執行cmd操作;cmd常用的兩個值是:SETVAL初始化第semnum個訊號量的值為arg.val;IPC_RMID刪除訊號量。

    (3)對一個或多個訊號量進行操作
* int semop(int semid,struct sembuf *sops,unsigned nsops);
        * struct sembuf{
              unsigned short sem_num;  //訊號量索引
              short   sem_op;     //對訊號量進行的操作,常用的兩個值為-1和+1,分別代表P、V操作
              short   sem_flag;   //比較重要的值是SEM_UNDO:當程序結束時,相應的操作將被取消;同時,如果程序結束時沒有釋放資源的話,系統會自動釋放
           
};

2、共享記憶體

    共享記憶體允許兩個或多個程序共享一定的儲存區,因為不需要拷貝資料,所以這是最快的一種IPC。

 #include <sys/ipc.h>
    
#include <sys/shm.h>
    (1)建立或訪問共享記憶體
        * int shmget(key_t key,size_t size,int shmflg);

    (2)附加共享記憶體到程序的地址空間
  * void *shmat(int shmid,const void *shmaddr,int shmflg);//shmaddr通常為NULL,由系統選擇共享記憶體附加的地址;shmflg可以為SHM_RDONLY

    (3)從程序的地址空間分離共享記憶體
        * int shmdt(const void *shmaddr); //shmaddr是shmat()函式的返回值

    (4)控制共享記憶體
        * int shmctl(int shmid,int cmd,struct shmid_ds *buf);
        * struct shmid_ds{
              struct ipc_perm shm_perm;
              …
          
}; 
    cmd的常用取值有:(a)IPC_STAT獲取當前共享記憶體的shmid_ds結構並儲存在buf中(2)IPC_SET使用buf中的值設定當前共享記憶體的shmid_ds結構(3)IPC_RMID刪除當前共享記憶體

3、訊息佇列

    訊息佇列儲存在核心中,是一個由訊息組成的連結串列。

 #include <sys/types.h>
    #include <sys/ipc.h>
    
#include <sys/msg.h>
    (1)建立或訪問訊息佇列
    * int msgget(key_t key,int msgflg);

    (2)操作訊息佇列
 * int msgsnd(int msqid,const void *msg,size_t nbytes,int msgflg);
    msg指向的結構體必須以一個long int成員開頭,作為msgrcv()的訊息型別,必須大於0。nbytes指的是msg指向結構體的大小,但不包括long int部分的大小
 * ssize_t msgrcv(int msqid,void *msg,size_t nbytes,long msgtype,int msgflg);
    如果msgtype是0,就返回訊息佇列中的第一個訊息;如果是正整數,就返回佇列中的第一個該型別的訊息;如果是負數,就返回佇列中具有最小值的第一個訊息,並且該最小值要小於等於msgtype的絕對值。

    (3)控制訊息佇列
  * int msgctl(int msqid,int cmd,struct msqid_ds *buf);
        * struct msqid_ds{
              struct ipc_perm msg_perm;
              …
           };