System V共享内存区

共享内存数据结构

 struct shmid_ds {
     struct ipc_perm shm_perm;     //IPC对象数据结构
     size_t          shm_segsz;    //共享内存段的大小
     time_t          shm_atime;    //最后一次映射共享内存的时间
     time_t          shm_dtime;    //最后一次解除映射的时间
     time_t          shm_ctime;    //最后一次共享状态发生改变的时间
     pid_t           shm_cpid;     //共享内存创建者的进程号
     pid_t           shm_lpid;     //
     shmatt_t        shm_nattch;   //当前共享内存被连接的次数
     ...
 };

共享内存函数

shmget函数

功能:

用来创建共享内存

原型:

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

参数

    key:这个共享内存段名字

    size:共享内存大小

    shmflg:由9个权限标志构成,用法和创建文件时使用的mode模式标志一样

返回值:

成功返回一个非负整数,即该共享内存段的标识码,失败返回-1

shmat函数

功能:

将共享内存段连接到进程地址空间

原型:

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

参数

    shmid:共享内存标识

    shmaddr:指定连接的地址

    shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

关于第三个参数:

1.如果shmaddr 是NULL,系统将自动选择一个合适的地址!  
2.如果shmaddr 不是NULL 并且没有指定SHM_RND则此段连接到addr所指定的地址上。  
3.如果shmaddr非0并且指定了SHM_RND,则此段连接到shmaddr -(shmaddr mod SHMLAB)所表示的地址上。这里解释一下SHM_RND命令,它的意思是取整,而SHMLAB的意思是低边界地址的倍数,它总是2的乘方,该算式是将地址向下取最近一个SHMLAB(一般为4096)的倍数。 除非只计划在一种硬件上运行应用程序(在现在是不太可能的),否则不用指定共享段所连接到的地址。所以一般指定shmaddr为0,以便由内核选择地址。
4.shmflg=SHM_RDONLY,表示连接操作用来只读共享内存

返回值:

成功返回一个指针,指向映射区的起始地址,失败返回-1。

shmdt函数

功能:

将共享内存段与当前进程脱离

原型:

int shmdt(const void *shmaddr);

参数

    shmaddr:由shmat所返回的值

返回值:

成功返回0,失败返回-1

注意:将共享内存与当前进程脱离不等于删除共享内存段

shmctl函数

功能:

用来创建和访问一个消息队列

原型:

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

参数

    shmid:由shmget返回的共享内存标识码

    cmd:将要采取的动作(有三个可取值)


    buf:指向一个保存着共享内存的模式状态和访问权限的数据结构(也就是动作命令带的参数)

返回值:

成功返回0,失败返回-1.

应用代码

shmwrite

#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)

typedef struct stu
{
	char name[32];
	int age;
}STU;

int main(int argc,char *argv[])
{
	//创建一个共享内存
	int shmid;
	//第二个参数是创建的共享内存的大小
	shmid=shmget(1234,sizeof(STU),IPC_CREAT | 0666);
	if(shmid==-1)
		ERR_EXIT("shmget");
	
	STU *p;
	//将这块内存连接到进程的地址空间中
	//0表示连接的这块内存既可读又可写
	p=shmat(shmid,NULL,0);
	if(p==(void*)-1)
		ERR_EXIT("shmat");
	
	strcpy(p->name,"wangkai");
	p->age=20;

	//判断数据是否被读走,若没有,则一直等待,不断开进程与共享内存区的连接
	while(1)
	{
		if(memcmp(p,"quit",4)==0)
			break;
	}
	//断开进程与共享内存区的连接
	shmdt(p);
	//从系统中删除由shmid标识的共享内存区并拆除它
	shmctl(shmid,IPC_RMID,NULL);
	return 0;
}

shmread

#include <unistd.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)

typedef struct stu
{
	char name[32];
	int age;
}STU;

int main(int argc,char *argv[])
{
	//创建一个共享内存
	int shmid;
	shmid=shmget(1234,0,0);
	if(shmid==-1)
		ERR_EXIT("shmget");
	
	STU *p;
	//将这块内存连接到进程的地址空间中
	//0表示连接的这块内存既可读又可写
	p=shmat(shmid,NULL,0);
	if(p==(void*)-1)
		ERR_EXIT("shmat");
	
	printf("name=%s age=%d\n",p->name,p->age);
	//读走以后将前4个字节置为quit,已提示发送方已收到,可以断开连接
	memcpy(p,"quit",4);

	shmdt(p);
	return 0;
}


猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/80514497