system v 共享內存 相關函數及返回值 描述

共享內存—shmget參數shmflg詳解—IPC_CREAT、IPC_EXCL、0666(對內存的讀寫執行權限)

int shmget(key_t key, size_t size, int flag);
key:     標識符的規則
size:    共享存儲段的字節數
flag:    讀寫的權限還有IPC_CREATIPC_EXCL對應文件的O_CREAT或O_EXCL
返回值:  成功返回共享存儲的id,失敗返回-1

key_t key
-----------------------------------------------
    key標識共享內存的鍵值: 0/IPC_PRIVATE。 當key的取值爲IPC_PRIVATE,則函數shmget()將創建一塊新的共享內存;如果key的取值爲0,而參數shmflg中設置了IPC_PRIVATE這個標誌,則同樣將創建一塊新的共享內存。
    在IPC的通信模式下,不管是使用消息隊列還是共享內存,甚至是信號量,每個IPC的對象(object)都有唯一的名字,稱爲“鍵”(key)。通過“鍵”,進程能夠識別所用的對象。“鍵”與IPC對象的關係就如同文件名稱之於文件,通過文件名,進程能夠讀寫文件內的數據,甚至多個進程能夠共用一個文件。而在IPC的通訊模式下,通過“鍵”的使用也使得一個IPC對象能爲多個進程所共用。
    Linux系統中的所有表示System V中IPC對象的數據結構都包括一個ipc_perm結構,其中包含有IPC對象的鍵值,該鍵用於查找System V中IPC對象的引用標識符。如果不使用“鍵”,進程將無法存取IPC對象,因爲IPC對象並不存在於進程本身使用的內存中。
    通常,都希望自己的程序能和其他的程序預先約定一個唯一的鍵值,但實際上並不是總可能的成行的,因爲自己的程序無法爲一塊共享內存選擇一個鍵值。因此,在此把key設爲IPC_PRIVATE,這樣,操作系統將忽略鍵,建立一個新的共享內存,指定一個鍵值,然後返回這塊共享內存IPC標識符ID。而將這個新的共享內存的標識符ID告訴其他進程可以在建立共享內存後通過派生子進程,或寫入文件或管道來實現。


int size(單位字節Byte)
-----------------------------------------------
    size是要建立共享內存的長度。所有的內存分配操作都是以頁爲單位的。所以如果一段進程只申請一塊只有一個字節的內存,內存也會分配整整一頁(在i386機器中一頁的缺省大小PACE_SIZE=4096字節)這樣,新創建的共享內存的大小實際上是從size這個參數調整而來的頁面大小。即如果size爲1至4096,則實際申請到的共享內存大小爲4K(一頁);4097到8192,則實際申請到的共享內存大小爲8K(兩頁),依此類推。

 

 


int shmflg
-----------------------------------------------
    shmflg主要和一些標誌有關。其中有效的包括IPC_CREAT和IPC_EXCL,它們的功能與open()的O_CREAT和O_EXCL相當。
    IPC_CREAT   如果共享內存不存在,則創建一個共享內存,否則打開操作。
    IPC_EXCL     只有在共享內存不存在的時候,新的共享內存才建立,否則就產生錯誤。

    如果單獨使用IPC_CREAT,shmget()函數要麼返回一個已經存在的共享內存的操作符,要麼返回一個新建的共享內存的標識符。

    如果將IPC_CREAT和IPC_EXCL標誌一起使用,shmget()將返回一個新建的共享內存的標識符;如果該共享內存已存在,或者返回-1。

     IPC_EXEL標誌本身並沒有太大的意義,但是和IPC_CREAT標誌一起使用可以用來保證所得的對象是新建的,而不是打開已有的對象。

 

 

這個可以用,但最好不要用:

     對於用戶的讀取和寫入許可指定SHM_RSHM_W;

     (SHM_R>3)和(SHM_W>3)是一組讀取和寫入許可,而(SHM_R>6)和(SHM_W>6)是全局讀取和寫入許可

 

推薦使用這個:

           可以使用0666|IPC_CREAT,來作爲shmflg的值。

 


返回值
-----------------------------------------------
成功返回共享內存的標識符;不成功返回-1,errno儲存錯誤原因。
    EINVAL           參數size小於SHMMIN或大於SHMMAX。
    EEXIST           預建立key所致的共享內存,但已經存在。
    EIDRM            參數key所致的共享內存已經刪除。
    ENOSPC        超過了系統允許建立的共享內存的最大值(SHMALL )。
    ENOENT        參數key所指的共享內存不存在,參數shmflg也未設IPC_CREAT位。
    EACCES        沒有權限。
    ENOMEM       核心內存不足。


struct shmid_ds
-----------------------------------------------
    shmid_ds數據結構表示每個新建的共享內存。當shmget()創建了一塊新的共享內存後,返回一個可以用於引用該共享內存的shmid_ds數據結構的標識符。

include/linux/shm.h

    struct shmid_ds {
        struct ipc_perm    shm_perm;      /* operation perms */
        int                shm_segsz;     /* size of segment (bytes) */
        __kernel_time_t    shm_atime;     /* last attach time */
        __kernel_time_t    shm_dtime;     /* last detach time */
        __kernel_time_t    shm_ctime;     /* last change time */
        __kernel_ipc_pid_t shm_cpid;      /* pid of creator */
        __kernel_ipc_pid_t shm_lpid;      /* pid of last operator */
        unsigned short     shm_nattch;    /* no. of current attaches */
        unsigned short     shm_unused;    /* compatibility */
        void               *shm_unused2; /* ditto - used by DIPC */
        void               *shm_unused3; /* unused */
    };


struct ipc_perm
-----------------------------------------------
    對於每個IPC對象,系統共用一個struct ipc_perm的數據結構來存放權限信息,以確定一個ipc操作是否可以訪問該IPC對象。

    struct ipc_perm {
        __kernel_key_t   key;
        __kernel_uid_t   uid;
        __kernel_gid_t   gid;
        __kernel_uid_t   cuid;
        __kernel_gid_t   cgid;
        __kernel_mode_t mode;
        unsigned short   seq;
};
//----------------------------------------

 

 

 

shmat
void *shmat(int shmid, const void *addr, int flag);
shmid:共享存儲的id
addr:一般爲0,表示連接到由內核選擇的第一個可用地址上,否則,如果flag沒有指定SHM_RND,則連接到addr所指定的地址上,如果flag爲SHM_RND,則地址取整
flag:如前所述,一般爲0                //推薦值
返回值:如果成功,返回共享存儲段地址,出錯返回-1


shmdt
int shmdt(void *addr);
addr:共享存儲段的地址,以前調用shmat時的返回值
shmdt將使相關shmid_ds結構中的shm_nattch計數器值減1


shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
shmid:共享存儲段的id
cmd:一些命令,有:IPC_STAT,IPC_RMID,SHM_LOCK,SHM_UNLOCK

請注意,共享內存不會隨着程序結束而自動消除,要麼調用shmctl刪除,要麼自己用手敲命令去刪除,否則永遠留在系統中。

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