一、共享内存之原理
1.是在物理内存中开辟了一片空间;
2.不同的进程通过页表将物理内存空间映射到自己的进程虚拟地址空间之中
3.不同的进程可以通过操作自己的虚拟地址空间中的虚拟地址去操作共享内存(物理地址)
共享内存是最快的进程之间的通信方式,所以很多进程之间的通信方式都是用共享内存:eg:守护进程和被守护的进程
二、共享内存的接口
1.创建、获取共享内存的接口
int shmget(key_t,size_t size, int shmflg) //shm shared memory
参数:
key:共享内存的标识符
size:共享内存的大小
shmflg:获取、创建共享内存时所传递的属性信息:
IPC_CREAT:若获取的共享内存不存在时就创建它
IPC_EXCL | IPC_CREAT: 若获取的共享内存存在,则函数报错;若获取的共享内存不存在则创建。
本质上,该组合是要获取重新创建的共享内存
按位或上权限
返回值:
成功:返回共享内存的操作句柄:
操作共享内存实质就是要操作其句柄
失败:返回-1;
2.将共享内存附加到进程的虚拟地址空间
void *shmat(int shmid,const void *shmaddi, int shmflg);
参数:
shmid:共享内存的操作句柄
shmaddr:将共享内存附加到共享区当中的第一个地址,一般让操作系统自己分配,传递NULL
shmflag:用什么权限将共享内存附加到进程中
SHM_RDONLY:只读
0:可读可写
返回值:
成功:返回附加到的虚拟地址
失败:-1
3.分离
int shmdt(const void *shmaddr)
参数:
shmaddr:附加到的虚拟地址(shmat函数执行成功的返回值)
返回值:
成功:0;
失败: -1;
4.操作共享内存的接口
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
参数:
shmid:共享内存的操作句柄;
cmd:告诉shmctl函数要完成的功能:
IPC_SET:设置共享内存属性信息,此时,buf是输入性参数,由程序员组织,传递给shmctl参数
IPC_STAT:获取共享内存的属性信息,此时,buf是输出型参数,由shmctl函数填充
IPC_RMID:删除共享内存,此时buf设置为NULL
buf:共享内存的数据结构
通过IPCS-M查看共享内存:
利用shmctl删除共享内存:
三、共享内存的代码
写入共享内存:
#include<stdio.h>
#include<unistd.h>
#include<sys/shm.h>
int main()
{
int ret=shmget(0x12345678,1024,IPC_CREAT | 0664);
if(ret<0)
{
perror("shmget \n");
return 0;
}
void *addr=shmat(ret,NULL,0); //得到附加到的虚拟地址
if(addr==NULL)
{
perror("shmat \n");
return 0;
}
printf("addr=%p\n",addr);
strcpy((char * )addr,"Love and peace \n" );
sleep(100);
shmdt(addr);
return 0;
}
从共享内存中读取:
#include<stdio.h>
#include<unistd.h>
#include<sys/shm.h>
int main()
{
int shmid=shmget(0x12345678,1024,IPC_CREAT);
if(shmid<0)
{
perror("shmget \n");
return 0;
}
void *addr=shmat(shmid,NULL,SHM_RDONLY);
if(addr==NULL)
{
perror("shmat \n");
return 0;
}
printf("read: %s : \n",(char *)addr );
shmdt(addr);
return 0;
}
四、共享内存的特性
1.生命周期跟随操作系统
2.共享内存是覆盖写的方式,读取共享内存时,是访问其地址,并没有将数据读取走
3.共享内存的删除特性:
1 ipcrm -m [shmid]:删除了共享内存
一旦共享内存被删除掉了,共享内存所在物理内存中的空间也同时被销毁了
如果删除的共享内存时,其附加的进程数量为0,则删除后,内核中描述该共享内存的结构体也被释放了。
若删除的共享内存的附加到进程数不为0,则会将该共享内存的key设置为0x00000000,表示该共享内存不可被其他的进程所附加,当附加的进程全部退出时,操作系统会将其在内核中的结构体释放。