帮助文档
专业提供香港服务器、香港云服务器、香港高防服务器租用、香港云主机、台湾服务器、美国服务器、美国云服务器vps租用、韩国高防服务器租用、新加坡服务器、日本服务器租用 一站式全球网络解决方案提供商!专业运营维护IDC数据中心,提供高质量的服务器托管,服务器机房租用,服务器机柜租用,IDC机房机柜租用等服务,稳定、安全、高性能的云端计算服务,实时满足您的多样性业务需求。 香港大带宽稳定可靠,高级工程师提供基于服务器硬件、操作系统、网络、应用环境、安全的免费技术支持。
服务器资讯 / 香港服务器租用 / 香港VPS租用 / 香港云服务器 / 美国服务器租用 / 台湾服务器租用 / 日本服务器租用 / 官方公告 / 帮助文档
【Linux】system V 共享内存
发布时间:2024-02-27 20:08:47   分类:帮助文档
【Linux】system V 共享内存 文章目录 system V1. 共享内存原理第一阶段原理第二阶段原理 2. 直接写代码--编写代码进行原理介绍shmget函数ftok函数key值用法 1. 创建key值2. 创建共享内存 获取共享内存3. 将自己和共享内存关联起来4. 将自己和共享内存取消关联5. 删除共享内存用指令删除调用系统调用 完整代码makefilecomm.hppserver.ccclient.cc system V system V 是一套标准,独立于文件系统之外的,专门为了通信设计出来的模块 让两个毫不相关的进程看到同一份资源 1. 共享内存原理 第一阶段原理 进程A和进程B都通过自己的页表映射到物理内存中的特定区域,进而找到该进程匹配的代码和数据 为了让进程A和进程B通信,前提是两者要看到同一份资源 假设在物理内存上开辟一块空间 进程A和进程B在自己的地址空间中都有自己的共享区 想办法把物理内存中新开辟空间 通过页表 映射到 进程A和进程B的共享区中 把地址空间的起始地址返回给用户 进程A和进程B就可以通过起始的虚拟地址,对应页表访问到内存 就完成了让进程A和进程B看到同一份资源,这份资源就被称为共享内存 第二阶段原理 系统中可以用ssh进行通信 ,是不是只能有一对进程使用共享内存呢? 可以,其他进程也可以通信 所以在任何时刻,可能有多个共享内存在被使用 系统中一定会存在很多共享内存同时存在 操作系统要不要整体管理所有的共享内存呢?要 操作性系统如何管理多个共享内存呢? 先描述,在组织 并不是在内存中开辟空间即可,系统为了管理共享内存,构建对应的描述共享内存的结构体对象 共享内存=共享内存的内核数据结构(伪代码:struct shm)+真正开辟的内存空间 2. 直接写代码–编写代码进行原理介绍 打开vscode,创建文件client.cc和server.cc(后缀为cc说明是c++)的文件 创建公共路径 comm.hpp shmget函数 创建共享路径接口 ,输入 man shmget 查看 申请一个 系统V的共享内存块 如果创建成功,则会返回共享内存标识符,失败返回-1 size代表申请内存块的大小 shmflg代表 选项 有两个最常用的选项,IPC_CREAT IPC_EXCL 转到定义就可以发现其实这两个都是宏 若单独使用 IPC_CREAT :创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,就获取已经存在的共享内存并返回 IPC_EXCL不能单独使用 ,一般都要配合 IPC_CREAT 若要将两个选项同时传进去 IPC_CREAT | IPC_EXCL 两个选项同时用: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,则立马出错返回 如果创建成功,对应的共享内存一定是最新的 获取共享内存时,需要有一个key值 ftok函数 输入 man ftok 根据路径和项目id进行算法结合,形成一个冲突概率低的key值 失败就返回-1,成功返回key值 key值用法 假设进程A创建了一个共享内存,但是进程B怎么知道那个共享内存是创建的吗? 就需要借助上述提到的 ftok 函数 刚开始约定好 A和B用同样的路径字符串和项目id 借助A形成一个key值,将key值放入A创建的共享内存描述结构体中 此时B也形成一个相同的key值,通过寻找key值来找到A所创建的共享内存 pathname 代表 用户自己设定的路径字符串 proj_id 代表 项目id key值意义为 让创建共享内存的进程可以给新共享内存设置key值 让获取共享内存的进程 通过key值 去找特定匹配的共享内存 1. 创建key值 comm.hpp 公共路径中构建一个函数 Getkey 用于返回key值 构建一个函数 tohex,用于将数转换为十六进制 通过server.cc与client.cc中分别调用Getkey 与tohex函数 两者的返回值key 是相同的,并且返回的都是十六进制数 2. 创建共享内存 获取共享内存 创建共享内存,调用shmget函数,通过两个选项 若共享内存不存在则创建,若存在则报错 而获取共享内存,调用shmget函数,则返回已有的共享内存 此时运行可执行程序,发现server与client的shmid(共享内存标识符)相同 3. 将自己和共享内存关联起来 输入 man shmat 指令 at代表 关联 将共享内存和目标值关联起来 返回值为 共享内存的虚拟地址的起始地址 我们不知道应该把共享内存放在虚拟空间的什么地址处,所以shmaddr设为NULL让系统自主去选择 shmflg 可以设置为 SHM_RDONLY 表示当前共享内存是只读的 一般设为0,默认为读写的 4. 将自己和共享内存取消关联 输入 man shmdt 指令 shmdt代表 虚拟地址 成功返回0,失败返回-1 5. 删除共享内存 创建共享内存的进程已经早就退出了,但是共享内存还存在 确认共享内存存在: ipcs ipc作为进程间通信的简写 ipc表示资源 s表示有多个资源 显出来的为ipc通信系统所支持的三种ipc通信策略 Message Queues 消息队列 Shared Memory Segments 共享内存段 Semaphore Arrays 信号量 ipcs - m 查看共享内存段 perms 代表权限 bytes 代表字节数 nattch 代表 有几个进程和当前进程是关联的 用指令删除 key是在操作系统中使用的,类似于文件的inode编号 shmid 类似于文件的fd 所以删除操作,是在用户层,应该用shmid ipcrm -m shmid值 就可以删除共享内存 此时就没有 shmid为0的共享内存 存在了 调用系统调用 输入 man shmctl 指令 shmid 代表 共享内存描述符 即想对那个共享内存操作 cmd 代表 选项 即想做什么操作 IPC_STAT 获取当前共享内存的属性 IPC_SET 设置共享内存属性 IPC_RMID 标记这个段被释放 buf 代表 共享内存的属性 在comm.hpp下 设置删除共享内存的函数,在server.cc中调用函数 即可删除共享内存 完整代码 makefile .PHONY:all all:server client server:server.cc g++ -o $@ $^ client:client.cc g++ -o $@ $^ .PHONY:clean clean: rm -f server client 如何使两个可执行程序运行,在上一篇文章提到过,点击查看:命名管道 comm.hpp #ifndef _COMM_HPP_ #define _COMM_HPP_ #include #include #include #include #include #include #include #include #include using namespace std; #define PATHNAME "."//.表示当前路径 路径字符串 #define PROJID 0x6666 //项目id const int gsize=4096; key_t getkey()//用于返回key值 { key_t k=ftok(PATHNAME,PROJID); if(k==-1)//失败 { cout< int main() { //1. 创建key值 key_t k=getkey();//获取key值 cout<<"server:"<