C語言-Linux shared memory

shared memory on linux
實作function有shmget和mmap

而shmget主要的function有
shmget()
shmat()
shmdt()
shmctl()

refer
http://baike.baidu.com/view/3838033.htm
http://blog.csdn.net/wlh_flame/article/details/6328380

shmget()
用來得到一個shared memory id或建立一個shared memory object。
格式如下
 shmget(key_t key, size_t size, int shmflg)
參數說明如下
Key:0表示建立新的shared memory object,>0表示根據shmflag的值操作。
Size:0表示只取得share memory,>0則表示要指定的shared memory大小。
shmflag:使用IPC_CREAT時,若沒有shared memory object則建立一個,若有則回傳shared memory id。
ex:
shm_id=shmget(key,0, 0);
shm_id=shmget(key,4096,IPC_CREAT|IPC_EXCL|0600)
shm_id=shmget(SHMKEY, MAXBUF+1, 0666)
shm_id=shmget(SHMKEY, MAXBUF+1, IPC_CREAT | 0666)
refer
http://man7.org/linux/man-pages/man2/shmget.2.html


shmat()
透過shmget()產生的shared memory id將shared memory object映射到memory,之後會回傳可直接存取的shared memory address。
格式如下
 shmat(int shmid, const void *shmaddr, int shmflg)
參數說明如下
 shmid:使用那一個shared memory id。
 shmaddr:指定shared memory要出現的位置,直接指定null可讓作業系統自己決定。
 shmflag:直接使用0即可。
ex:
shm = shmat(shm_id, NULL, 0)
shm =(people*)shmat(shm_id,NULL,0)
refer
http://man7.org/linux/man-pages/man2/shmat.2.html


shmdt()
將shared memory的address關閉,成功會傳回0
格式如下
 shmdt(const void *shmaddr)
參數說明如下
 shmaddr:shared memory的address
ex:
shmdt(shm);
refer
http://man7.org/linux/man-pages/man2/shmdt.2.html


shmctl()
管理shared memory
格式如下
 shmctl(int shmid, int cmd, struct shmid_ds *buf)
參數說明如下
cmd:有以下三種參數可選
 IPC_STAT:得到shared memory的狀態
 IPC_SET:改變shared memory的狀態
 IPC_RMID:刪除shared memory
buf:shared memory結構
ex:
shmctl(shmid, IPC_RMID, NULL);
refer
http://man7.org/linux/man-pages/man2/shmctl.2.html

…………………………………………………………………………………………………………………………..

shared memory在linux常用的指令 

顯示目前的Shared Memory Segments
#ipcs -m
—— Shared Memory Segments ——–
key shmid owner perms bytes nattch status
0x50494f4e 0 nobody 666 2016 1
0x000004d2 2064385 root 666 1025 0

刪除指定的Shared Memory Segments
#ipcrm -m < shmid>
ex:
删除key=0x000004d2 shmid=2064385的共享内存
#ipcrm -m 2064385

………………………………………………………………………………………………………………………….

以shared memory實作簡易聊天程式範例

執行方式為
#chat < username>

#vi chat.c
程式碼如下

#include < sys/types.h>
#include < sys/ipc.h>
#include < sys/shm.h>
#include < stdio.h>
#include < stdlib.h>
#include < string.h>
#include < unistd.h>

#define PERMS 0666
#define SHMKEY ((key_t) 1234)  
#define MAXBUF 2048

int inputchat(char *username){
 int shmid, str_len;
 key_t key;
 char *shm;
 char str_buf[MAXBUF]="";
 char str2_buf[MAXBUF]="";
 char speaker[100];
 if ((shmid = shmget(SHMKEY, MAXBUF+1, PERMS)) < 0) {
  perror("shmget");
  exit(1);
 }
 if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
  perror("shmat");
  exit(1);
 }
 strcpy(speaker,username);
 strcat(speaker,":");
 printf("Hello %s, Enter Words: n",username);
 while (1) {
  strcpy(str_buf, "");
  fgets(str_buf,2000, stdin);
  strncpy(str2_buf,speaker,30);
  strcat(str2_buf,str_buf);
  str_len = strlen(str2_buf);
  strcpy(shm,str2_buf);
 }
}

int outputchat(){
 int shmid;
 key_t key;
 char *shm, *s;
 if ((shmid = shmget(SHMKEY, MAXBUF+1, IPC_CREAT | PERMS)) < 0) {
  perror("shmget");
  exit(1);
 }
 if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
  perror("shmat");
  exit(1);
 }
 while(1){
  shm[MAXBUF] = 1;
  while(strstr(shm, "n") == NULL){
   if(shm[MAXBUF] == 1){
    continue;
   }
  }
  printf("%s ", shm);
  sleep(1);
  strcpy(shm,"");
 }
}

int main(int argc, char **argv){
 pid_t fpid;
 fpid=fork();
 if(fpid < 0)
  printf("error in fork!");
 else if (fpid == 0) {
  outputchat();
 }else {
  inputchat(argv[1]);
 }
 return 0;
}