IPC對象的概念
IPC的標識符只解決了內部訪問一個IPC對象的問題,如何讓多個進程都訪問某一個特定的IPC對象還需要一個外部鍵(key),每一個IPC對象都與一個鍵相關聯。這樣就解決了多進程在一個IPC對象上匯合的問題。
創建一個IPC對象時需要指定一個鍵值,類型為key_t,在<sys/types.h>中定義為一個長整型。鍵值到標識符的轉換是由系統核心來維護的。當有了一個IPC對象的鍵值,如何讓多個進程知道這個鍵,可以有多種實現的辦法。● 可以使用檔案來做中間的通道,創建IPC對象進程,使用鍵IPC_PRIVATE成功建立IPC對象之後,將返回的標識符存儲在一個檔案中。其他進程通過讀取這個標識符來引用IPC對象通信。
● 定義一個多個進程都認可的鍵,每個進程使用這個鍵來引用IPC對象,值得注意的是,創建IPC對象的進程中,創建IPC對象時如果該鍵值已經與一個IPC對象結合,則應該刪除該IPC對象,再創建一個新的IPC對象。
● 多進程通信中,對於指定鍵引用一個IPC對象而言,可能不具有拓展性,並且在該鍵值已經被一個IPC對象結合的情況下。所以必須刪除這個存在對象之後再建立一個新的。這有可能影響到其他正在使用這個對象的進程。函式ftok可以在一定程度上解決這個問題,
函式ftok可以使用兩個參數生成一個鍵值,函式原型如下:
#include <sys/ipc.h>
key_t ftok( const char *path, int id );
函式中參數path是一個檔案名稱。函式中進行的操作是,取該檔案的stat結構的st_dev成員和st_ino成員的部分值,然後與參數ID的第八位結合起來生成一個鍵值。由於只是使用st_dew和st_ino的部分值,所以會丟失信息,不排除兩個不同檔案使用同一個ID,得到同樣鍵值的情況。
系統為每一個IPC對象保存一個ipc_perm結構體,該結構說明了IPC對象的許可權和所有者,每一個版本的核心各有不用的ipc_perm結構成員。若要查看詳細的定義請參閱檔案<sys/ipc.h>。
struct ipc_perm {
key_t key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
unsigned short mode;
unsigned short seq;
};
每一種版本的ipc_perm結構體定義至少要包含上述幾個域。當調用IPC對象的創建函式(semget msgget shmget )時,會對ipc_perm結構的每一個域賦值。在後續的操作中如需修改這幾個域則調用相應的控制函式(msgctl semctl shmctl)。
%注意:只有超級用戶或者創建IPC對象的進程有權改變ipc_perm結構的值。結構中的mode域類似於檔案的stat結構的mode域,但是不可以有執行許可權。mode值描述如表14-3所示。
ipc_perm的mode詳解表
操作者 | 讀 | 寫(更改 更新) | 操作者 | 讀 | 寫(更改 更新) |
用戶 | 0400 | 0200 | 其他 | 0004 | 0002 |
組 | 0040 | 0020 | ​ | ​ | ​ |
IPC對象的問題
IPC對象所存在的問題主要集中在以下幾點:
過於繁雜的編程接口,比起使用其他通信方式,IPC所要求的代碼量要明顯增多。
● IPC不使用通用的檔案系統,這也是飽受指責的原因。所以不能使用標準I/O操作函式來讀寫IPC對象。為此不得不新增加一些函式來支持必要的一些操作(例如msgget msgrev msgctl等)並且對於不同類型的IPC對象都有一系列特定的操作函式。由於IPC不使用檔案描述符,所以不能使用多路I/O監控函式select及poll函式來操作IPC對象。
● 缺少的資源回收機制。由於IPC對象在使用過程中並不保存引用計數,所以當出現一個進程創建了IPC對象然後退出時,則這個對象只有在出現後面幾種情況才會被釋放或者刪除,即由某一個進程讀出訊息,或者IPC的所有者或超級用戶刪除了這個對象。這也是IPC相對於管道或FIFO所欠缺的資源回收機制。
IPC對象系統命令
在shell下可以使用一些命令來操作IPC對象,下面通過幾個實際的例子來幫助理解IPC對象,使用ipcs可以顯示IPC的狀態。在shell中輸入:
$ipcs –a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 65536 root 600 393216 2 dest
0x00000000 2654209 root 666 4096 0
0x00000000 2752516 root 666 4096 0
------ semaphore Arrays --------
key semid owner perms nsems
0x00000000 294911 root 666 1
------ Message Queues --------
key msqid owner perms used-bytes messages
注意ipcs輸出的信息中的key 以及shmid,key標識的是IPC對象的外鍵,shmid標識的IPC對象的標識符。owner標識的是IPC所屬的用戶,perms標識許可權。可以使用ipcrm命令來刪除一個IPC對象,使用實例如下。在shell中輸入:
$ipcrm –m 2752516
$ipcs –a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 65536 root 600 393216 2 dest
0x00000000 2654209 root 666 4096 0
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 294911 root 666 1
------ Message Queues --------
key msqid owner perms used-bytes messages
在套用中,如果使用kill命令刪除程式後,發現系統資源例如記憶體的使用量仍然很高,則應檢查系統IPC狀態,並使用ipcrm命令刪除不使用的IPC。