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;   //当前共享内存被连接的次数
     ...
 };
#include <sys/ipc.h>
#include <sys/shm.h>
 
int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

shmget函数

功能:用来创建共享内存

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

参数

    key:这个共享内存段名字

    size:共享内存大小

    shmflg:用法类似msgget中的msgflg参数;

返回值:

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

 

 

shmat函数

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

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

连接到本进程地址空间, 成功连接之后,  而且如果这块内存中有数据, 则就可以直接将其中的数据取出来

参数:

   shmaddr:指定连接的地址(推荐使用NULL)

   shmflg:一般指定为0, 表示可读,可写; 而它的另外两个可能取值是SHM_RND和SHM_RDONLY(见下)

返回值:

   成功返回一个指针,指向共享内存起始地址;失败返回(void *) -1

shmaddr与shmflg组合说明

shmaddr为NULL

Linux内核自动为进程连接到进程的内存(推荐使用)

shmaddr不为NULL且shmflg无SHM_RND标记

以shmaddr为连接地址

shmaddr不为NULL且shmflg设置了SHM_RND标记

连接的地址会自动向下调整为SHMLBA的整数倍;

公式:shmaddr - (shmaddr % SHMLBA)

SHMLBA为内存页面的大小(4K)

shmflg=SHM_RDONLY

表示连接只能用来读共享内存, 

 

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.

 

//共享内存写
#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;
}

#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;
}
 

 

System V共享内存小结:

   1.共享内存被别的程序占用,则删除该共享内存时,不会马上删除(引用计数计数);

   2.此时会出现一个现象:该共享内存的key变为0x00000000,变为私有;

   3.此时还可以读,但必须还有办法获取该共享内存的ID(shmid),因为此时试图通过该共享内存的key获取该共享内存,是白费的

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值