当前位置: 首页 > news >正文

系统编程.8 存储映射和共享内存

1.存储映射

存储映射I/O(Memory-mapped I/O)将一个磁盘文件和存储空间中的一个缓冲区映射。

使得用户可以直接在缓冲区读写数据,不必再去内存中读写。

1.1 mmap()

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

函数功能:

  • 建立映射

参数:

  • addr:指定的开始映射的内存地址。一般使用NULL
  • length:映射大小,单位字节
  • prot:权限

        PROT_READ 可读

        PROT_WRITE 可写

  • flags:

        MAP_SHARED 共享的 -- 对映射区的修改会影响源文件

        MAP_PRIVATE 私有的

  • fd:文件描述符 需要打开一个文件
  • offset :偏移量 ,从该位置开始映射,一般为0

1.2 munmap()

int munmap(void *addr, size_t length);

函数功能:

  • 释放内存映射,仅对当前进程有效

参数:

  • addr:映射区的首地址
  • length:映射区的长度

1.3 truncate()

int truncate(const char *path, off_t length);

函数功能:

  • 对打开的文件进行扩容

参数:

  • path:要扩容的文件
  • length:扩容的大小

案例:

添加映射:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/mman.h>int main(int argc, char const *argv[])
{// 打开文件int fd = open("/home/qf/桌面/week05/day03/temp", O_RDWR | O_CREAT, 0664);if (fd < 0){perror("open");return 0;}// 扩容int ret = truncate("/home/qf/桌面/week05/day03/temp",16);// printf("ret=%d\n",ret);//mmap映射void * p=mmap(NULL,16,PROT_WRITE | PROT_READ,MAP_SHARED,fd,0);//强转char *buff=(char *)p;//转换完就可以存入数据,那其他进程可以直接读走return 0;
}

写:

strcpy(buff,"hello");

读:

    printf("收到数据%s\n",buff);

2. 共享内存

共享内存允许两个或者多个进程共享给定的存储区域。

2.1 共享内存的特点

  • 共享内存是进程间共享数据的一种最快的方法。

一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。

  • 使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。

         若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。

2.2 API

2.2.1 shmget()

#include <sys/ipc.h>

#include <sys/shm.h>

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

函数功能:

  • 创建或打开一个共享内存区

参数:

  • key:IPC键值
  • size:共享内存段的大小
  • shmflag:标识函数的行为以及共享内存的权限

IPC_CREAT:如果不存在就创建

IPC_EXCL:如果已经存在则返回失败

位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式和 open 函数的 mode_t 一样,但可执行权限未使用。

返回值:

  • 成功:返回共享内存的标识符
  • 失败:-1

查看:

查看消息队列: ipcs -q

产看共享内存:ipcs -m

删除共享内存 ipcrm -m shmid

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/mman.h>int main(int argc, char const *argv[])
{key_t key =ftok("/home/qf/桌面/week05/day03",05);// printf("key=%d\n",key);//建立共享内存int shmid =shmget(key,16,IPC_CREAT);if (shmid<0){perror("shmget");return 0;}// printf("shmid=%d\n",shmid);return 0;
}

2.2.2 shmat()

#include <sys/types.h>

#include <sys/shm.h>

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

函数功能:

  • 映射,将真实的物理内存与进程中的虚拟内存地址关联起来

参数:

  • shmid:共享内存标识符
  • shamaddr:共享内存映射地址,推荐NULL
  • shmflg:共享内存段的可读可写权限

0:可读可写

SHM_RDONLY:只读

SHM_RND:(shmaddr 非空时才有效)没有指定 SHM_RND 则此段连接到 shmaddr 所指定的地址上(shmaddr 必需页对齐)。指定了 SHM_RND 则此段连接到 shmaddr- shmaddr%SHMLBA 所表示的地址上。

返回值:

  • 成功:返回共享内存段映射地址
  • 失败:-1

2.2.3 shmdt()

#include <sys/types.h>

#include <sys/shm.h>

int shmdt(const void *shmaddr);

函数功能:

  • 解除映射

参数:

  • shamaddr:共享内存段映射地址

案例:

写:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/mman.h>int main(int argc, char const *argv[])
{key_t key =ftok("/home/qf/桌面",05);// printf("key=%d\n",key);//建立共享内存int shmid =shmget(key,4096,IPC_CREAT | 0666);if (shmid<0){perror("shmget");return 0;}// printf("shmid=%d\n",shmid);//建立映射char *buff=(char *)shmat(shmid,NULL,0);strcpy(buff,"hello");//解除当前进程与共享内存的连接shmdt(buff);return 0;
}

读:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/mman.h>int main(int argc, char const *argv[])
{key_t key =ftok("/home/qf/桌面",05);// printf("key=%d\n",key);//建立共享内存int shmid =shmget(key,4096,IPC_CREAT | 0666);if (shmid<0){perror("shmget");return 0;}// printf("shmid=%d\n",shmid);//建立映射char *buff=(char *)shmat(shmid,NULL,0);printf("%s\n",buff);//解除当前进程与共享内存的连接shmdt(buff);return 0;
}

2.2.4 共享内存控制函数

#include <sys/ipc.h>

#include <sys/shm.h>

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

函数功能:

  • 共享内存空间的控制。

参数:

  • shmid:共享内存标识符。
  • cmd:函数功能的控制。

PC_RMID:删除。(常用)

IPC_SET:设置 shmid_ds 参数。

IPC_STAT:保存 shmid_ds 参数。

SHM_LOCK:锁定共享内存段(超级用户)。

SHM_UNLOCK:解锁共享内存段。

  • buf:shmid_ds 数据类型的地址,用来存放或修改共享内存的属性。

返回值:

  • 成功:0
  • 失败: -1

SHM_LOCK 用于锁定内存,禁止内存交换。

并不代表共享内存被锁定后禁止其它进程访问。

其真正的意义是:被锁定的内存(物理内存)不允许被交换到虚拟内存中。

这样做的优势在于让共享内存一直处于内存中,从而提高程序性能


文章转载自:

http://Aj3Rertn.Lgmty.cn
http://Z42eo6Cs.Lgmty.cn
http://oFaXbBKr.Lgmty.cn
http://lsZW18GD.Lgmty.cn
http://6esgrocX.Lgmty.cn
http://iJ7LXfCq.Lgmty.cn
http://IvCcnEv6.Lgmty.cn
http://arw5OiAa.Lgmty.cn
http://iTnABR8e.Lgmty.cn
http://FX0BDqQk.Lgmty.cn
http://VrJ0qRbI.Lgmty.cn
http://g3PZVo01.Lgmty.cn
http://02ALMq7y.Lgmty.cn
http://E4EnKtsr.Lgmty.cn
http://TmWtoV3z.Lgmty.cn
http://FIVWTUvH.Lgmty.cn
http://08bfpObt.Lgmty.cn
http://hwi3peA9.Lgmty.cn
http://phwXnNV0.Lgmty.cn
http://7jXHw2PW.Lgmty.cn
http://SHDtS8IU.Lgmty.cn
http://ZeYblzyx.Lgmty.cn
http://2Uwe9Gw8.Lgmty.cn
http://E19KrRZc.Lgmty.cn
http://flKxI3yT.Lgmty.cn
http://LWHq5C3l.Lgmty.cn
http://RJjDAb4K.Lgmty.cn
http://HVrNzFkc.Lgmty.cn
http://BhR9KEFt.Lgmty.cn
http://AnnSMLnM.Lgmty.cn
http://www.dtcms.com/a/377790.html

相关文章:

  • Leetcode每日一练--22
  • Windows Socket简介
  • OpenHarmony网络深度揭秘:从Wi-Fi驱动到用户态socket的实战源码讲解
  • 《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread
  • 【超级工程·蓝燕云】雅鲁藏布江水电站如何攻克“不可能完成”的工程?
  • 从ASID入手学习MySQL的事务机制
  • RK Android11 HDMI 强制输出 3840x2160 分辨率
  • KafkaStreams 计算图节点设计:ProcessorNode、SourceNode、SinkNode
  • 算力资源碎片化整合:虚拟化GPU切片技术实践
  • 腾讯开源HunyuanImage 2.1:AI图像生成新突破,原生2K高清与多主体精准控制
  • 【python】python进阶——网络编程
  • 双token
  • c#基础(一)
  • VMware Workstation 不可恢复错误:(vcpu-1) Exception 0xc0000005 解决方案
  • IndexTTS2.0_ 情感表达与时长可控的自回归零样本语音合成突破
  • Git提交文件提取工具:一键将特定提交的文件导出到指定目录
  • 中间件漏洞详解
  • TC_Motion多轴运动-PID调节
  • Java 学习笔记(进阶篇3)
  • 金蝶云星空 调价表取历史价格
  • TwinCAT3人机界面1
  • C#语言入门详解(18)传值、输出、引用、数组、具名、可选参数、扩展方法
  • 【C++世界之string模拟实现】
  • 打工人日报#20250910
  • LeetCode100-206反转链表
  • function-call怎么训练的,预料如何构建
  • OpenLayers数据源集成 -- 章节四:矢量格式图层详解
  • 220V供电遥测终端 220V供电测控终端 选型
  • 【LLM】Transformer注意力机制全解析:MHA到MLA
  • 三十六、案例-文件上传-阿里云OSS-集成