简介
共享内存是进程间通讯的一种机制,在数据量较大时,比较合适。每个共享内存对象都有一个
shmid_ds结构体与之对应,代表共享内存的一些信息。
因为shm是SYSV子系统的一种机制,所以有SYSV的一些特性,
1、引用标识符:用来访问对象
2、键:定位引用标识符
3、ipc_perm结构:记录一些状态信息

要引入的文件

#i nclude <sys/types.h>
#i nclude <sys/ipc.h>
#i nclude <sys/shm.h>

创建共享内存与打开
int shmget(key_t key, int size, int flag);

int newshm()
{
  int shmid;
  shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE); //创建
  //shmid = shmget(88, SHM_SIZE, SHM_MODE|IPC_CREAT);//如果88存在-打开,如果88不存在-创建
  //shmid = shmget(88, SHM_SIZE, SHM_MODE|IPC_CREAT|IPC_EXCL);//如果88存在-失败,如果88不存在-创建
  //shmid = shmget(0x90, SHM_SIZE, SHM_MODE|IPC_CREAT|IPC_EXCL);//同上,但key用16进制
  if(shmid == -1)
    printf("newshm error/n");
  return shmid;
}

key为IPC_PRIVATE时代表创建,size为大小,此时flag不起作用
key不为IPC_PRIVATE时,如果flag有IPC_CREAT但没有IPC_EXCL时,如果key已经存在代表打开(size不起作用),否则代表创建
key不为IPC_PRIVATE时,如果flag有IPC_CREAT且有IPC_EXCL时,代表创建,如果key已经调用失败

成功返回引用标识符,失败返回-1

附加共享内存

void * shmat(int shmid, void *addr,int flag);

char * getshm(int shmid)
{
  char *ptr;
  ptr = shmat(shmid, 0, 0);
  if(ptr == (void*) -1)
    printf("getshm error/n");
  return ptr;
}

调用方法按例子简单调用即可,更多参数说明可以查看网上资料,此时可以用strcpy向ptr中写数据,即是写到共享内存中。

分离共享内存

int shmdt(void *addr);

void dtshm(char * ptr)
{
  int ret = shmdt(ptr);
  if(ret<0)
    printf("dtshm error/n");
}

将getshm取得的共享内存地址传入即可

控制共享内存
int shmctl(int shmid, int cmd, shmid_ds *buf);
具体做什么控制由cmd决定:
SHM_LOCK:上锁共享内存,只能由超级用户执行
IPC_RMID:删除共享内存
IPC_SET:设置共享内存,由buf决定
IPC_STAT:取得共享内存shmid_ds结构体
SHM_UNLOCK:解锁

删除:
void delshm(int shmid)
{
  int ret;
  ret = shmctl(shmid, IPC_RMID, 0);
  if(ret<0)
    printf("delshm error/n");
}

取shmid_ds结构体:
struct shmid_ds shmds;
void getstat(int shmid)
{
  int ret;
  ret = shmctl(shmid, IPC_STAT, &shmds);
  if(-1 == ret)
    printf("getstat error/n");
}
注意:删除与分离的区别
如果分离,本进程或其它进程还可以附加,并且分离后引用地址失效
如果删除,引用地址不立即失效,但不可以再附加。(进程结束或断开连接时才真正删除)

下面是一个测试程序:

#i nclude <sys/types.h>
#i nclude <sys/ipc.h>
#i nclude <sys/shm.h>

#define ARRAY_SIZE 400
#define BUF_SIZE 400
#define SHM_SIZE 1000
#define SHM_MODE SHM_W|SHM_R

int newshm();
char* getshm(int);
void getstat(int);
void delshm(int);
void printstat(struct shmid_ds *);
void dtshm(char*);

struct shmid_ds shmds;

int main()
{
  int shmid;
  char *shmptr;
  shmid = newshm();
  shmptr = getshm(shmid);
  printf("%s/n", shmptr);

 // getstat(shmid);
 // printstat(&shmds);
  //delshm(shmid);
  //dtshm(shmptr);

  //shmptr = getshm(shmid);
  //strcpy(shmptr, "bbb");
  //printf("%s/n", shmptr);
}

int newshm()
{
  int shmid;
  //shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE);
  //shmid = shmget(88, SHM_SIZE, SHM_MODE|IPC_CREAT);
  //shmid = shmget(88, SHM_SIZE, SHM_MODE|IPC_CREAT|IPC_EXCL);
  shmid = shmget(0x90, SHM_SIZE, SHM_MODE|IPC_CREAT|IPC_EXCL);
  if(shmid == -1)
    printf("newshm error/n");
  return shmid;
  }

char * getshm(int shmid)
{
  char *ptr;
  ptr = shmat(shmid, 0, 0);
  if(ptr == (void*) -1)
    printf("getshm error/n");
  return ptr;
}

void getstat(int shmid)
{
  int ret;
  ret = shmctl(shmid, IPC_STAT, &shmds);
  if(-1 == ret)
    printf("getstat error/n");
}

void dtshm(char * ptr)
{
  int ret = shmdt(ptr);
  if(ret<0)
    printf("dtshm error/n");
}

void delshm(int shmid)
{
  int ret;
  ret = shmctl(shmid, IPC_RMID, 0);
  if(ret<0)
    printf("delshm error/n");
}

void printstat(struct shmid_ds *buf)
{
  printf("struct ipc_perm:/n");
  printf("uid=%d/n", buf->shm_perm.uid);
  printf("gid=%d/n", buf->shm_perm.gid);
  printf("cuid=%d/n", buf->shm_perm.cuid);
  printf("cgid=%d/n", buf->shm_perm.cgid);
}

 

Logo

更多推荐