进程A先申请一段内存空间,其页表映射到物理空间,进程B通过A的页表映射,将B的页表也同样映射到同一块物理空间。
释放共享内存
各自修改各自的页表指向并释放共享内存
头文件 comm.hpp
#pragma once#include
#include
#include //注意这个
#include
#include
#include
#include
#include //sleep()
#include "myLog.hpp"using namespace std;#define PATH_NAME "/home/chy" //这个路径随便 但要保证自己有权限去访问
#define PROJ_ID 0x66 //任意
#define SHM_SIZE 4096 //最好是页(4096)的整数倍
通过一定的算法形成唯一值给需要通信的两个进程使用
#include
#include
key_t ftok(const char* pathname,int proj_id)
pathname :给一个路径值
proj_id:随便给
ftok会将路径值得inode编号和proj_id值进行一定运算形成一个唯一值
#include "comm.hpp"
int main()
{//1.创建共享内存key_t k=ftok(PATH_NAME,PROJ_ID);//形成keyLog("创建key成功",Debug)<<"server key:"<
创建失败返回-1
#include #include int shmget(key_t key,size_t size,int shmflg);
key :一个随机数通过 ftok去创建 目的是让两个进程有一个相同的编号,以看到同一块共享内存。
size : 要申请多大的共享内存,最好是4096的整数倍
shmflg: 可以是 IPC_CREAT 创建共享内存,如果底层已经存在就获取它,如果不存在就创建它,并返回。
也可以是 IPC_CREAT | IPC_EXCL 底层不存在就创建,如果底层存在就出错返回。
返回值:共享内存的用户层标识符,类似fd
创建失败返回-1
int main()
{//2.创建共享内存-- 建议创建一个全新的共享内存int shmid=shmget(k,SHM_SIZE,IPC_CREAT| IPC_EXCL |0666);//带上权限if(shmid==-1){perror("shmget");exit(1);}
//...
}
当进程运行结束时,我们的共享内存依然存在。
system V IPC 资源,生命周期随内核只能通过手动删除或代码删除。
1.手动删除
bash: ipcs -m
查看共享内存
bash:ipcrm -m shmid
删除共享内存
2.代码删除
shmctl
#include
#include
int shmctl(int shmid,int cmd,struct shmid_ds * buf);
cmd有:IPC_STAT 获取共享内存的属性 IPC_SET设置共享内存的相关属性
IPC_RMID 标记共享内存被删除
buf :是一个数据结构的指针 删除时设为空就行
//删除共享内存int n=shmctl(shmid,IPC_RMID,nullptr);assert(n!=-1);(void)n;Log("删除共享内存成功",Debug)<<"shmid: "<
失败返回-1
关联挂接
#include
#incldue void* shmat(int shmid ,const void* shmaddr,int shmflg);
shmaddr 挂接到的虚拟地址位置(不推荐给参数)设为nulltpr 即可
shmflg 可以以只读等方式进行挂接 设为0即可
//3.将指定的共享内存挂接到自己的地址空间char* shmaddr=(char*)shmat(shmid,nullptr,0);Log("链接成功",Debug)<<"shmid: "<
返回值是虚拟地址,失败返回-1
去关联
#include
#include int shmdt(const void* shmaddr);
shmaddr 就是shmat的返回值
失败返回-1
./shmserver
#include "comm.hpp"
int main()
{//1.获取kkey_t k=ftok(PATH_NAME,PROJ_ID);//形成keyif(k<0){Log("创建key失败",Error)<<"client key: "<
./shmclient
shmat的返回值是虚拟地址,我们可以将它当成一个大字符串。
shmclient.cc
shmclient.cc
结论:
下一篇:服务器负载过高实例分析