linux共享内存的使用

news/2024/5/4 10:31:04/文章来源:https://blog.csdn.net/qq_34999565/article/details/128436515

共享内存可以由多个程序同时访问的内存,能够避免进程间通信过程中的冗余数据拷贝,是IPC中最快的一种,特别适合用来作大块数据的传输。共享内存可以映射到不同的进程空间,这些进程间的数据传递就不再涉及内核。这个过程其实是把同一块物理内存映射到不同进程的虚拟地址,这些进程可以同时对共享内存进行读写。
在这里插入图片描述
共享内存的使用主要分为以下三步:

  1. 创建一个共享内存
  2. 设置共享内存的大小
  3. 将共享内存映射到进程用户空间
    进行到第二步的时候就已经在内核空间创建了一块内存空间,只要再把它映射到进程用户空间就可以使用了。
    在Linux中主要提供了两套接口来使用共享内存,分别是posix接口和system V接口。其中posix接口的可移植性更好。

posix接口

int shm_open(const char *name, int oflag, mode_t mode);//打开一个共享内存文件
int ftruncate(int fildes, off_t length);//设置共享内存的大小
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);//将共享内存映射到进程地址空间,返回值是共享内存映射到进程空间的地址
int munmap(void *addr, size_t length);//取消内存映射                  
int shm_unlink(const char *name);//删除共享内存

shm_open() 创建并打开一个新的或打开一个现有的 POSIX 共享内存对象。 POSIX 共享内存对象实际上是一个句柄,不相关的进程可以使用它来 mmap(2) 共享内存的同一区域。 shm_unlink() 函数执行相反的操作,删除先前由 shm_open() 创建的对象。

shm_open() 的操作类似于 open。 name 指定要创建或打开的共享内存对象。
oflag 是一个位掩码,它通过将 O_RDONLY 或 O_RDWR 中的一个与以下列出的任意标志进行 OR 运算来创建:

O_RDONLY
以只读模式打开。 以这种方式打开的共享内存对象只能被 mmap(2) 用于读取 (PROT_READ) 访问。
O_RDWR
以读写模式打开。
O_CREATE
如果共享内存对象不存在,则创建它。 对象的用户和组所有权取自调用进程对应的有效ID,对象的权限位按照参数mode的低9位设置,不过在process file mode创建掩码中设置的那些位 (请参阅umask(2))会被清除。 open(2) 中列出了一组可用于定义mode的宏常量。 (这些常量的符号定义可以通过包含<sys/stat.h>来获得。)
一个新的共享内存对象最初的长度为零——对象的大小可以使用 ftruncate 设置。 共享内存对象新分配的字节会自动初始化为 0。
O_EXCL
如果同时指定了 O_CREAT,并且给定name的共享内存对象已经存在,则返回错误。 检查对象是否存在,以及不存在时创建新对象的过程是原子的。此标识是为了避免: 如果对象存在,但是制定了O_CREATE,那么默认的操作是打开该对象,这样就不知道是打开了原有的还是创建了新的,而O_EXCL确保,一定是创建一个新的,否则就要报错
O_TRUNC
如果对象存在,则将其长度大小截断为0

成功完成后,shm_open() 返回一个引用共享内存对象的新文件描述符。

文件描述符通常用于后续调用 ftruncate(用于新创建的对象)和 mmap。 调用 mmap 后,可能会关闭文件描述符而不影响内存映射。

shm_unlink() 的操作类似于 unlink:它删除一个共享内存对象名称,并且一旦所有进程都取消映射该对象(执行unmap),就释放并销毁相关内存区域的内容。 在成功 shm_unlink() 之后,尝试 shm_open() 具有相同名称的对象失败(除非指定了 O_CREAT,在这种情况下会创建一个新的、不同的对象)。

成功时,shm_open() 返回一个文件描述符(一个非负整数)。 成功时,shm_unlink() 返回 0。失败时,两个函数都返回 -1 并设置 errno 以指示错误。

system V 接口

int shmget(key_t key, size_t size, int shmflg);//打开一个共享内存文件
void *shmat(int shmid, const void *shmaddr, int shmflg)//将共享内存映射到进程地址空间
int shmdt(const void *shmaddr);//删除共享内存

posix接口使用示例

生产者消费者模型,一个进程写一个进程读
生产者代码:

/*** Simple program demonstrating shared memory in POSIX systems.** This is the producer process that writes to the shared memory region.** Figure 3.17** @author Silberschatz, Galvin, and Gagne* Operating System Concepts - Ninth Edition* Copyright John Wiley & Sons - 2013** modifications by dheller@cse.psu.edu, 31 Jan. 2014*/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>void display(char *prog, char *bytes, int n);int main(void)
{const char *name = "/shm-example";    // file nameconst int SIZE = 4096;        // file sizeconst char *message0 = "Studying ";const char *message1 = "Operating Systems ";const char *message2 = "Is Fun!";const char *msg_end  = "\n";int shm_fd;        // file descriptor, from shm_open()char *shm_base;    // base address, from mmap()char *ptr;        // shm_base is fixed, ptr is movable/* create the shared memory segment as if it was a file */shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);if (shm_fd == -1) {printf("prod: Shared memory failed: %s\n", strerror(errno));exit(1);}/* configure the size of the shared memory segment */ftruncate(shm_fd, SIZE);/* map the shared memory segment to the address space of the process */shm_base = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);if (shm_base == MAP_FAILED) {printf("prod: Map failed: %s\n", strerror(errno));// close and shm_unlink?exit(1);}/*** Write to the mapped shared memory region.** We increment the value of ptr after each write, but we* are ignoring the possibility that sprintf() fails.*/display("prod", shm_base, 64);ptr = shm_base;ptr += sprintf(ptr, "%s", message0);ptr += sprintf(ptr, "%s", message1);ptr += sprintf(ptr, "%s", message2);ptr += sprintf(ptr, "%s", msg_end);display("prod", shm_base, 64);/* remove the mapped memory segment from the address space of the process */if (munmap(shm_base, SIZE) == -1) {printf("prod: Unmap failed: %s\n", strerror(errno));exit(1);}/* close the shared memory segment as if it was a file */if (close(shm_fd) == -1) {printf("prod: Close failed: %s\n", strerror(errno));exit(1);}return 0;
}void display(char *prog, char *bytes, int n)
{printf("display: %s\n", prog);for (int i = 0; i < n; i++){ printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : '\n'); }printf("\n");
}

消费者:

/*** Simple program demonstrating shared memory in POSIX systems.** This is the consumer process** Figure 3.18** @author Gagne, Galvin, Silberschatz* Operating System Concepts - Ninth Edition* Copyright John Wiley & Sons - 2013** modifications by dheller@cse.psu.edu, 31 Jan. 2014*/#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>void display(char *prog, char *bytes, int n);int main(void)
{const char *name = "/shm-example";    // file nameconst int SIZE = 4096;        // file sizeint shm_fd;        // file descriptor, from shm_open()char *shm_base;    // base address, from mmap()/* open the shared memory segment as if it was a file */shm_fd = shm_open(name, O_RDONLY, 0666);if (shm_fd == -1) {printf("cons: Shared memory failed: %s\n", strerror(errno));exit(1);}/* map the shared memory segment to the address space of the process */shm_base = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);if (shm_base == MAP_FAILED) {printf("cons: Map failed: %s\n", strerror(errno));// close and unlink?exit(1);}/* read from the mapped shared memory segment */display("cons", shm_base, 64);    // first as bytes, then as a stringprintf("%s", shm_base);/* remove the mapped shared memory segment from the address space of the process */if (munmap(shm_base, SIZE) == -1) {printf("cons: Unmap failed: %s\n", strerror(errno));exit(1);}/* close the shared memory segment as if it was a file */if (close(shm_fd) == -1) {printf("cons: Close failed: %s\n", strerror(errno));exit(1);}/* remove the shared memory segment from the file system */if (shm_unlink(name) == -1) {printf("cons: Error removing %s: %s\n", name, strerror(errno));exit(1);}return 0;
}void display(char *prog, char *bytes, int n)
{printf("display: %s\n", prog);for (int i = 0; i < n; i++){ printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : '\n'); }printf("\n");
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_240066.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FMOC-PEG-COOH,FMOC-PEG-acid,芴甲氧羰基-聚乙二醇-羧基试剂供应

英文名称&#xff1a;FMOC-PEG-COOH&#xff0c;FMOC-PEG-acid 中文名称&#xff1a;芴甲氧羰基-聚乙二醇-羧基 蛋白质、肽和其他材料通过氨基酸或其他酸活性化学组&#xff0c;增加溶解度和稳定性&#xff0c;降低免疫原性&#xff1b;药物修饰或缓释药物研发&#xff0c;新…

ARM_SMMU_下

SMMU驱动代码分析 本文主要分析linux kernel中SMMUv3的代码(drivers/iommu/arm-smmu-v3.c) linux kernel版本是linux 5.7, 体系结构是aarch64 SMMU的作用是把CPU提交给设备的VA地址&#xff0c;直接作为设备发出的地址&#xff0c;变成正确的物理地址&#xff0c;访问到物理内…

[~/vulhub]/log4j/CVE-2021-44228-20221225

[~/vulhub]/log4j/CVE-2021-44228 ┌──(kwkl㉿kwkl)-[~/vulhub] └─$ cd log4j/CVE-2021-44228 ┌──(kwkl㉿kwkl)-[~/vulhub/log4j/CVE-2021-44228] └─$ dir 1.png 2.png docker-compose.yml README.md README.zh-cn.md┌──(kwkl㉿kwkl)-[~/vulhub/log4j/CVE-2021…

_15LeetCode代码随想录算法训练营第十五天-C++二叉树

_15LeetCode代码随想录算法训练营第十五天-C二叉树 题目列表 110.平衡二叉树257.二叉树的所有路径404.左叶子之和 110.平衡二叉树 题目 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每…

SpringBoot-2 读取properties;自动加载127个类原理总结;全部加载,按需配置

读取properties 方式一&#xff1a;非配置类填写&#xff1a;ComponentConfigurationProperties 1)建立bean&#xff1a; /只有在容器中的组件才拥有springboot提供的强大功能 Component ConfigurationProperties(prefix "mycar") public class Car {private Stri…

NetSuite Decode函数

昨天是平安夜&#xff0c;小家伙仍然为圣诞老人的到来准备了礼物&#xff0c;这是他的传统。每年为了感谢圣诞老人和驯鹿的到来&#xff0c;他都会准备上点心、水果。今年&#xff0c;他认为驯鹿可能需要电力&#xff0c;所以准备了电池给它们享用。 真希望天真一直伴随他的成长…

互联网技术不再是统领,当下正在发生着一场深刻的变革

拥抱实体经济&#xff0c;绝对是当下互联网玩家们的首要选择。无论是头部的互联网企业来讲&#xff0c;还是新生的互联网玩家而言&#xff0c;它们都不约而同地将关注的焦点聚焦在了这样一个方向上。   透过这一点&#xff0c;我们可以非常明显地感受到&#xff0c;一个全新的…

蓝桥杯备赛Day4——多维数组

二维数组初始化 p[[0 for i in range(5)] for j in range(2)] #法一 p[[0]*5 for j in range(2)] #法二 s[[1,2,3],[4,5,6]] print(s) for i in range(2):for j in range(3):print(s[i][j],end ) 三维数组初始化 a[[[0 for _ in range(2)] for __ in…

CSDN每日一练最长递增的区间长度 C语言

题目名称&#xff1a;最长递增的区间长度 时间限制&#xff1a;1000ms 内存限制&#xff1a;256M 题目描述 给一个无序数组&#xff0c;求最长递增的区间长度。如&#xff1a;[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3 &#xff08;注意&#xff1a;测试用例仅做参考&#xff0c;…

windows@网络防火墙@软件联网控制

文章目录ref打开防火墙控制面板常用部分限制某个软件联网文档参考具体操作取消控制/禁用第三方软件控制ref (Windows) 创建出站端口规则 | Microsoft LearnWindows Defender Firewall with Advanced Security (Windows) | Microsoft Learn组策略 Windows) 高级安全性的 Window…

二叉树经典算法题目

1.二叉树的前中后序遍历&#xff08;简单&#xff09; 省略 2.二叉树的深度(简单) 输入一棵二叉树的根节点&#xff0c;求该树的深度。从根节点到叶节点依次经过的节点&#xff08;含根、叶节点&#xff09;形成树的一条路径&#xff0c;最长路径的长度为树的深度。 例如&a…

VS coda C++、python运行与Dbug配置

首先新建终端 一次性使用C方法 检查C编译器是否存在 which g可见位置存在于&#xff1a;/usr/bin/g 一次性命令格式&#xff1a; 使用json配置文件 运行C方法&#xff08;推荐&#xff09;&#xff1a; 根据你查找的g的位置来决定 使用配置好的tasks.json&#xff08;C的…

Java window多环境配置

目录JDK版本下载配置内容描述创建JAVA_HOME在Path配置版本切换效果JDK版本下载 Java8 Download address 这个是Java8 的下载地址&#xff0c;下载是要登录的&#xff0c;自己花费一点时间去注册。如果想要下载其它版本的JDK&#xff0c;请看下面的图&#xff0c;然后你就可以看…

SSD_学习笔记记录

one-steage VGG16模型的修改 VGG16的模型输出&#xff0c;其中224.。。为特征图的大小。 SSD模型中对VGG网络的修改&#xff1a; SSD模型是对VGG中的第四个卷积块中的最后一个Conv2d进行第一个输出&#xff0c;在这里简称为Conv4-3。以及第五个卷积块中的最后一个Conv2d进行…

前端开发:Vue封装通过API调用的组件的方法

前言 在前端开发中&#xff0c;关于Vue的使用相比大家并不陌生&#xff0c;而且Vue框架的优势也是其他框架所不能比的&#xff0c;尤其是Vue的封装思想更是堪称一绝&#xff0c;还有就是组件化的运用实践过程也是亮点。所以关于Vue框架的使用想必看官都不陌生&#xff0c;而且常…

干货 | 关于PCB中的“平衡铜”,一文全部说明白

平衡铜是PCB设计的一个重要环节&#xff0c;对PCB上闲置的空间用铜箔进行填充&#xff0c;一般将其设置为地平面。 平衡铜的意义在于&#xff1a; 对信号来说&#xff0c;提供更好的返回路径&#xff0c;提高抗干扰能力&#xff1b;对电源来说&#xff0c;降低阻抗&#xff0c;…

8 NP完全性理论

8 NP完全性理论 p问题 NP问题 NP完全问题 NPC(complete ) NP难问题NP-hard p问题 是一类能够用**(确定的)算法**在多项式时间内求解的可判定问题 ●这种问题类型也称为多项式类型 NP问题 是一类能够用不确定算法在多项式时间内求解的可判定问题 在确定性计算模型下多项式时…

Web前端105天-day64-HTML5_CORE

HTML5CORE04 目录 前言 一、复习 二、WebSocket 三、服务器搭建 四、聊天室 五、defineProperty 5.1.初识defineProperty 5.2.配置多个属性 5.3.可配置 5.4.赋值监听 5.5.练习 5.6.计算属性 总结 前言 HTML5CORE04学习开始 一、复习 SVG: 利用HTML的 DOM 来绘制图…

juc-4-synchronized原理

目录 1、synchronized 作用于静态方法 总结 ​编辑 案例 静态成员变量 (synchronized锁非静态方法) 案例 静态成员变量 (synchronized锁静态方法 或 直接锁类) 2、监视器锁(monitor) 2.1 synchronized怎么实现的线程安全呢&#xff1f; 3、JDK6 synchronized 的优化 3.1 C…

6.s081 学习实验记录(二)xv6 and unix utilities

文章目录一、boot xv6二、sleep三、pingpong四、primes五、find六、xargs该实验主要用来熟悉xv6以及其系统调用 一、boot xv6 实验目的&#xff1a; 启动xv6系统&#xff0c;并使用提供的命令ls&#xff0c;列出系统所有的文件ctrl p&#xff0c;打印当前运行的进程ctrl a…