Unix環境進程間通信(二)[轉]

1.1        共享內存

1.1.1   數據結構

struct shmid_ds {
struct ipc_perm  shm_perm;    /* 超作許可權數據結構指針 */

    int              shm_segsz;   /* 共享存儲段大小 (bytes) */

    time_t          shm_atime;   /* 最後調用shmat時間 */

    time_t          shm_dtime;   /* 最後調用shmdt的時間 */

    time_t          shm_ctime;   /* 最後調用shmctl的改變的時間 */

    unsigned short   shm_cpid;    /*創建者的進程ID */

    unsigned short   shm_lpid;    /* 最後對共享存儲段進行操作的進程ID */

short           shm_nattch;  /* 當前連接數 */
};

struct ipc_perm {

     key_t  key;
     ushort uid;   /* owner euid and egid */
     ushort gid;
     ushort cuid;  /* creator euid and egid */
     ushort cgid;
     ushort mode;  /* lower 9 bits of shmflg */
     ushort seq;   /* sequence number */
};

 

1.1.2   API

4.4 #include <sys/ipc.h>

#include <sys/shm.h>

打開創建存儲段

int shmget(key_t key, size_t size, int shmflg);

返回:失敗-1, 成功返回非負的共享存儲段id

 

第一個參數key是共享存儲關鍵字。它有特殊值IPC_PRIVATE表示總是創建一個進程私有的共享存儲段。

key值不等於IPC_PRIVATE時,shmget動作取決於最後一個參數shmflg標誌:

1. IPC_CREAT 單獨設置此標誌,當系統中不存在相同key時,創建一個新的共享存儲段,否則返回已存在的共享存儲段。

2. IPC_EXCL 單獨設置不起作用。與 IPC_CREAT同時設置時,當系統中存在相同key時,錯誤返回。保證不會打開一個已存在的共享存儲段。

如果沒有指定IPC_CREATE並且系統中不存在相同key值的共享存儲段,將失敗返回。

第三個參數也可以設置共享存儲段的訪問權限,用或於上面的值操作。

第二個參數size指明要求的共享存儲段的大小。當key指定的共享存儲段已存在時,取值範圍爲0和已存在共享段大小。或簡單指定爲0

成功後此函數返回共享存儲段id,同時創建於參數key相連的數據結構shmid_ds。此節構爲系統內部使用。

 

4.4 #include <sys/ipc.h>

#include <sys/shm.h>

存儲段控制函數。可獲得shmid_ds全部內容

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

返回:失敗-1並置errno, 成功返回0

第一個參數,必須由shmget返回的存儲段的idcmd爲指定要求的操作。

CMD

說明

參數

IPC_STAT

放置與shmid相連的shmid_ds結構當前值於buf所指定用戶區

buf

IPC_SET

buf指定的結構值代替與shmid相連的shmid_ds結構值

buf

IPC_RMID

刪除制定的信號量集合

 

SHM_LOCK

鎖住共享存儲段。只能由超級管理員使用

 

SHM_UNLOCK

unlock共享存儲段。只能由超級管理員使用

 

 

//創建/打開共享存儲段,連接他到用戶地址空間,返回他在用戶空間的地址

void* shminit(key_t key, char* mode_str, int target=1) {

       int shmid;

       int mode;

       void* retval;

       if (mode_str == NULL) {

              mode = 0660;

       } else {

              sscanf(mode_str, "%o", &mode);

       }

       if (target == 0 ) {

              if ((shmid = shmget(key, sizeof(exchange_T), mode | IPC_CREAT)) == -1)

                     perror("cannot create shm--");

       } else if (target == 1) {

              if ((shmid = shmget(key, sizeof(exchange_T), mode)) == -1)

                     perror("cannot get shm--");

       }

       if ((retval = shmat(shmid, (void *)0, 0)) == (void*)-1)

              perror("shmmat");

       return retval;

}

 

int rm_shm(key_t key) {

       int status, shmid;

      

       if ((shmid = shmget(key, sizeof(exchange_T), 0x660 | IPC_CREAT)) < 0)

                     perror("cannot get shm");

       if ((status = shmctl(shmid, IPC_RMID, NULL)) < 0)

              perror("shmctl IPC_RMID");

       return status;

}

 

4.5 #include <sys/types.h>

   #include <sys/shm.h>

存儲段連接

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

返回:失敗-1並置errno, 成功返回連接的實際地址

第一個參數,必須由shmget返回的存儲段的id

第二個參數指明共享存儲段要連接到的地址。0,系統爲我們創建一個適當的地址值。否則自己指定

第三個參數shmflg可以設成:SHM_RND, SHM_RDONLYSHM_RND爲自己指定連接地址時用。SHM_RDONLY說明此存儲段只讀。

 

4.6 #include <sys/types.h>

   #include <sys/shm.h>

存儲段分離

int shmdt(const void * shmaddr);

返回:失敗-1並置errno, 成功返回0

分離由shmaddr指定的存儲段。此值應該由shmat返回的值。

此函數不是刪除共享存儲段,而是從當前進程分離存儲段。

當進程推出時,系統會自動分離它連接的所有共享段。

1.1.3   Example

client.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>

#define SHMSZ 27
int main(void) {
       exchange_T* shm;
       int producer, consumer, i;
       key_t key1 = 123, key2 = 456;

       consumer = open_semaphore_set(key1, 1);
       procuder = open_semaphore_set(key2, 1);

       shm = (exchange_T*)shminit(ftock("shared", 0));

       for (i = 0; ; i++) {
              semaphore_V(consumer);
              semaphore_P(producer);

              printf("Data recieived:%s, sequence:%d/n", shm->buf, shm->seg);

              if (strncmp(shm->buf, "end", 3) == 0)
                     break;
       }

       rm_semaphore(producer);
       rm_semaphore(consumer);

       exit(0);
}

 

server.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
#include "outshm.h"

#define SHMSZ 27

int main(void) {

       exchage_T *shm, *s;
       int producer, consumer, i;
       char readbuf[BUFSIZE];
       key_t key1 = 123, key2 = 456;

       consumer = open_semaphore_set(key1, 1);
       init_a_semaphore(consumer, 0, 0);

       producer = open_semaphore_set(key2, 1);
       init_a_semaphore(producer, 0, 0);

       shm = (exchange_T*)shminit(ftok("shared", 0));

       for(i = 0; ; i++) {
              printf("Enter some text:");
              fgets(readbuf, BUFSIZE, stdin);
              semaphore_P(consumer);
              shm->seq = i;
              sprintf(shm->buf, "%s", readbuf);
              semaphore_V(producer);
              if(strncmp(readbuf, "end", 3) == 0)
                     break;
       }

       exit(0);
}

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