嵌入式学习笔记--Linux系统编程阶段--DAY07进程间通信--存储映射和共享内存

1.存储映射

存储映射 I/O (Memory-mapped I/O) 使一个磁盘文件存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应字节。于此类似,将数据存入缓冲区则相应的字节就自动写入文件。这样,就可在不适用 read 和 write 函数的情况下,使用地址(指针)完成 I/O 操作。 使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap 函数来实现。
     这个文件仅仅是用来进程间通信的桥梁。

1.1mmap函数映射

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,不偏移)
返回值
        成功 返回映射区的首地址
        失败 返回 MAP_FAILED ((void *) -1)

1.2munmap函数

munmap函数:解除映射(断开当前进程和磁盘文件的映射关系,不影响其他进程的映射)

int munmap(void *addr, size_t length);
参数解释
        addr 映射区的首地址
        length 映射区的长度
返回值
        成功 返回 0
        失败 返回 -1

1.3truncate函数

truncate函数:拓展文件的大小
一般磁盘映射是新建一个文件,这个文件新建的时候,大小是0,因此里面无法存储数据,所以需要拓展文件的大小
int truncate(const char *path, off_t length);
参数解释
        path 要拓展的文件
        length 要拓展的长度

1.4代码案例

不相关的进程间通信

写代码:

#define _POSIX_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include <sys/mman.h>int main(int argc, char const *argv[])
{//1.通过open打开文件int fd = open("temp",O_RDWR |O_CREAT,0666);//新建的文件无大小//2.拓展文件的大小truncate("temp",16);//3.建立映射char *buff = (char *)mmap(NULL,16,PROT_READ | PROT_WRITE,MAP_SHARED ,fd,0);//4.使用内存区域strcpy(buff,"hello mmap");//5.断开映射munmap(buff,16);close(fd);return 0;
}

读代码:

#define _POSIX_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>int main(int argc, char const *argv[])
{//1.通过open打开文件int fd = open("temp",O_RDWR |O_CREAT,0666);//新建的文件无大小//2.拓展文件的大小truncate("temp",16);//3.建立映射char *buff = (char *)mmap(NULL,16,PROT_READ | PROT_WRITE,MAP_SHARED ,fd,0);//4.使用内存区域printf("收到数据%s\n",buff);printf("收到数据%s\n",buff);//5.断开映射munmap(buff,16);close(fd);return 0;
}

除非被覆盖,否则数据一直在

2.共享内存

2.1共享内存理论

共享内存允许两个或者多个进程共享给定的存储区域。(进程间通信的最快的方式)

共享内存的特点

1、 共享内存是进程间共享数据的一种最快的方法。 一个进程向共享的内存区域写入了数据, 共享这个内存区域的所有进程就可以立刻看到其中的内容。

2、 使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥若一个进程正在向共享内存区写数据, 则在它做完这一步操作前, 别的进程不应当去读、 写这些数据

在 ubuntu 部分版本中共享内存限制值如下 共享存储区的最小字节数:

1 共享存储区的最大字节数: 32M

共享存储区的最大个数: 4096

每个进程最多能映射的共享存储区的个数: 4096

2.2共享内存的API

shmget函数:创建或打开一块共享内存区,即获得一个共享内存标识符

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size,int shmflg);
功能:
        创建或打开一块共享内存区
参数:
        key:IPC 键值(需要ftok函数)
        size:该共享存储段的长度(字节)
        shmflg:标识函数的行为及共享内存的权限。
                参数:shmflg:
                        IPC_CREAT:如果不存在就创建
                        IPC_EXCL:如果已经存在则返回失败
                        位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式 和 open 函数的 mode_t 一样,但可执行权限未使用
返回值:
        成功:返回共享内存标识符。
        失败:返回-1

使用 shell 命令操作共享内存

查看共享内存

ipcs -m --内存

ipcs -q --队列

ipcrm -m shmid --删除shmid的共享内存

代码案例:

创建一个共享内存,获取标识符:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main(int argc, char const *argv[])
{ // 1.获取唯一key值key_t key = ftok("/home/qf/桌面", 2504);// 2.得到唯一共享内存标识(分配物理内存)int shm_id = shmget(key,16,IPC_CREAT | 0666) ;  printf("%d\n",shm_id);return 0;
}

shmat函数:将一个共享内存段映射到调用进程的数据段中,即建立进程与物理内存的映射

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr,int shmflg);
函数功能:
        将一个共享内存段映射到调用进程的数据段中。
参数:
        shmid:共享内存标识符。
        shmaddr:共享内存映射地址(若为 NULL 则由系 统自动指 定),推荐使用 NULL
        shmflg:共享内存段的访问权限和映射条件(映射时的读写关系)
                0:共享内存具有可读可写权限。
                SHM_RDONLY:只读。
                SHM_RND:(shmaddr 非空时才有效)(自己申请的虚拟地址来进行映射(例如malloc来的),建议shmaddr选NUMM)
                没有指定 SHM_RND 则此段连接到 shmaddr 所指定的地址上(shmaddr 必需 页对齐)。 指定了 SHM_RND 则此段连接到 shmaddr- shmaddr%SHMLBA 所表示的地址 上。
返回值:
成功:返回共享内存段映射地址
失败:返回 -1
代码案例:建立内存与进程间的映射
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main(int argc, char const *argv[])
{ // 1.获取唯一key值key_t key = ftok("/home/qf/桌面", 2504);// 2.得到唯一共享内存标识(分配物理内存)int shm_id = shmget(key,16,IPC_CREAT | 0666) ;  printf("%d\n",shm_id);//3.建立进程和物理内存间的映射char *p = (char *)shmat(shm_id,NULL,0);//4.断开映射,只断开自己return 0;
}

shmdt函数:将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
        将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)
参数:
        shmaddr:共享内存映射地址。
返回值:
成功返回 0
失败返回 -1

shmctl:共享内存控制函数

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd,struct shmid_ds *buf);
功能:
        共享内存空间的控制。
参数:
        shmid:共享内存标识符。
        cmd:函数功能的控制。
        buf:shmid_ds 数据类型的地址,用来存放或修改共享内存的属性。
                cmd:函数功能的控制
                        IPC_RMID:删除。
                        IPC_SET:设置 shmid_ds 参数。
                        IPC_STAT:保存 shmid_ds 参数。
                        SHM_LOCK:锁定共享内存段(超级用户)
                        SHM_UNLOCK:解锁共享内存段。
返回值:
成功返回 0
失败返回 -1
注意:
SHM_LOCK 用于锁定内存,禁止内存交换。并不代表共享内存被锁定后,禁止其它进程访问。其真正的意义是:被锁定的内存不允许被交换到虚拟内存中(即只针对当前进程)。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能

读写代码案例:

写:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main(int argc, char const *argv[])
{ // 1.获取唯一key值key_t key = ftok("/home/qf/桌面", 2504);// 2.得到唯一共享内存标识(分配物理内存)int shm_id = shmget(key,16,IPC_CREAT | 0666) ;  printf("%d\n",shm_id);//3.建立进程和物理内存间的映射char *p = (char *)shmat(shm_id,NULL,0);strcpy(p,"hello world!");//4.断开映射,只断开自己shmdt(p);return 0;
}

读:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>int main(int argc, char const *argv[])
{ // 1.获取唯一key值key_t key = ftok("/home/qf/桌面", 2504);// 2.得到唯一共享内存标识(分配物理内存)int shm_id = shmget(key,16,IPC_CREAT | 0666) ;  printf("%d\n",shm_id);//3.建立进程和物理内存间的映射char *p = (char *)shmat(shm_id,NULL,SHM_RDONLY);printf("收到数据:%s\n",p);//4.断开映射,只断开自己return 0;
}

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

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

相关文章

.Net程序员就业现状以及学习路线图(四)

一、.Net程序员就业现状分析 1. 市场需求与岗位分布 2025年数据显示&#xff0c;.Net开发岗位在全国IT岗位中占比约0.009%&#xff0c;主要集中在一线城市如深圳、上海等地 2 4。行业分布呈现以下特点&#xff1a;‌软件行业‌&#xff1a;占比43.3% ‌研发领域‌&#xff1a;占…

Monorepo 是什么?如何使用并写自己的第三方库

1. 什么是 Monorepo&#xff1f; Monorepo&#xff08;单仓库&#xff09;指的是把多个项目/包放在一个代码仓库里统一管理。常见结构&#xff1a; /repo-root/packages/ui-lib/utils/apps/web-apppackage.jsonpnpm-workspace.yaml好处&#xff1a; 内部库能直接共享&#xff0…

使用CI/CD部署后端项目(gin)

写在前面&#xff1a;使用CI/CD部署gin项目到服务器中 前端可以参考&#xff1a;使用CI/CD部署nextjs项目 使用 GitHub Actions 配置后端 CI/CD&#xff08;含部署到服务器&#xff09; 本文档介绍如何在 GitHub 仓库中配置 CI/CD&#xff0c;将 PROJECT_NAME 项目自动构建并…

Coze添加知识库解析的Embedding和PaddleOCR模型配置

1. Embedding模型配置 使用ollama模型&#xff0c;导入qwen3的embedding-8B模型&#xff0c;导入流程参考&#xff1a; Ollama离线部署模型 qwen3-Embedding模型文件可从魔塔社区下载&#xff1a; Qwen3-Embedding-8B 1.2 Coze配置 在coze_studio/docker目录下输入: vim .en…

02-Media-6-rtsp_server.py 使用RTSP服务器流式传输H264和H265编码视频和音频的示例程序

rtsp_server.py 是使用k230的板载摄像头和WIFI联网功能,使用RTSP服务器流式传输视频和音频的程序示例。程序核心是创建了一个RtspServer类,该类用于初始化、启动、停止RTSP服务器,并进行视频和音频的流传输。 一、首先,程序导入必要的模块,包括视频编码、传感器、媒体处理…

13-Java-面向对象-封装和this关键字

文章目录封装this关键字封装 告诉我们&#xff0c;如何正确设计对象的属性和方法。原则&#xff1a;对象代表什么&#xff0c;就得封装对应的数据&#xff0c;并提供数据对应的行为 package common;/*** Author: 大海* Date: 2025-09-06*/public class GirlFriend {/*private…

三高项目-缓存设计

三高项目-缓存设计 分流、并发 导流&#xff1a;将原本复杂操作的请求&#xff0c;引导到简单的操作上。以后再来查&#xff0c;不需要经过复杂的计算。 成本&#xff1a;空间&#xff0c;收益&#xff1a;节省了时间。 不要以为仅仅是 redis&#xff0c;map等。 对应。kv…

happen-before原则

什么是 happen-before 原则&#xff1f; happen-before 是一个逻辑关系&#xff0c;用于描述两个操作之间的 “先后顺序”—— 如果操作 A happen-before 操作 B&#xff0c;那么 A 的执行结果必须对 B 可见&#xff0c;且 A 的执行顺序在逻辑上先于 B。也就是保证指令有序性和…

4.1 机器学习 - 评估指标

模型评估是判断 “模型是否有效” 的核心环节&#xff0c;需结合任务类型&#xff08;分类 / 回归&#xff09;、数据分布&#xff08;如类别不平衡&#xff09;和商业目标选择指标。本节聚焦分类任务的核心评估指标&#xff0c;从定义、计算逻辑到适用场景逐一拆解&#xff0c…

雅菲奥朗SRE知识墙分享(七):『可观测性的定义与实践』

在分布式系统日益复杂的当下&#xff0c;故障不再是“是否发生”&#xff0c;而是“何时爆发”。SRE可观测性正是应对不确定性的“显微镜”与“导航仪”&#xff1a;通过指标、日志、追踪三大数据血脉&#xff0c;实时外化系统黑盒&#xff0c;让每一次抖动、每一行报错、每一次…

C++ 详细讲解vector类

目录 1. 什么是vector? 2. vector的使用 1. 构造函数---初始化 1. 默认构造函数(无参构造&#xff09; 2. 填充构造函数(指定数量和初始值&#xff09; 3. 范围构造函数(通过迭代器拷贝其他容器元素&#xff09; 4. 拷贝构造函数(直接拷贝另一个vector&#xff09; 注…

Windows Server2012 R2 安装.NET Framework 3.5

Windows Server2012 R2 安装.NET Framework 3.5 虚拟机系统是Windowsserver 2012R2&#xff0c;在安装SQlserver2012时候警告未安装.NET Framework 3.5。于是找了个.NET Framework 3.5的安装包&#xff0c;但是由于系统原因无法正常安装。按照提示从控制面板-程序-启动或关闭Wi…

IDEA中Transaction翻译插件无法使用,重新配置Transaction插件方法

原因 由于Transaction默认的翻译引擎为谷歌翻译&#xff0c;由于一些原因&#xff0c;这个翻译无法使用&#xff0c;因此导致插件无法使用。 解决办法 更换Transaction插件翻译引擎即可。 方法步骤 1.进入Idea的设置里&#xff0c;找到Tool下的Transaction选项2.更改翻译引擎&a…

外置flash提示音打包脚本

批处理脚本说明文档 - 音频资源打包与分发 一、脚本功能概述 本批处理脚本&#xff08;.bat 文件&#xff09;用于将指定目录下的多个音频文件&#xff08;.wtg 和 .mp3 格式&#xff09;打包为音频资源配置文件&#xff08;tone.cfg&#xff09;&#xff0c;进一步将配置文件与…

Go语言设计模式(三)抽象工厂模式

抽象工厂模式与工厂模式类似,被认为是工厂方法模式的另一层抽象.抽象工厂模式围绕创建其他工厂的超级工厂工作.1.角色:1.1抽象产品:构成产品系列的一组不同但相关的产品的声明接口.1.2具体产品:实现抽象产品接口的类,主要用于定义产品对象,由相应的具体工厂创建.1.3抽象工厂:创…

大狗王 DG1+ 13.6G矿机详细参数解析与性能评测

近年来&#xff0c;随着加密货币挖矿行业的不断发展&#xff0c;越来越多的矿机厂商推出了高性能、低功耗的矿机设备。大狗王&#xff08;DG1&#xff09;13.6G矿机便是其中一款备受关注的设备&#xff0c;特别是在LTC&#xff08;莱特币&#xff09;、Doge&#xff08;狗狗币&…

Python 算术运算练习题

计算数字特征值题目描述 编写一个程序&#xff0c;接收用户输入的两个整数 a 和 b&#xff08;a > b > 0&#xff09;&#xff0c;计算并输出以下结果&#xff1a;a 与 b 的和的平方a 除以 b 的商和余数a 与 b 的平均数&#xff08;保留 2 位小数&#xff09;示例请输入整…

OS项目构建效能改进策划方案

一、现状分析与问题定位构建稳定性问题&#xff1a; 表现&#xff1a;非代码变更引发的构建失败&#xff08;如环境依赖、工具链版本、第三方库更新、资源竞争等&#xff09;“幽灵构建”时有发生。影响&#xff1a;严重破坏开发流程的顺畅性&#xff0c;耗费大量开发/测试人员…

Ai8051 2.4寸320*240 ILI9341 I8080接口驱动

/*---------------------------------------------------------------------*/ /* --- Web: www.STCAI.com ---------------------------------------------*/ /* 液晶屏驱动程序参考wiki技术网站提供的开源源码&#xff0c;仅供学习使用 */ /*----------------------…

最大似然估计:损失函数的底层数学原理

引言当你第一次看到线性回归时&#xff0c;你是否注意到了作为参数优化关键的损失函数&#xff08;均方损失&#xff09;&#xff0c;你是否能够理解它的本质和由来。其实&#xff0c;在我第一次接触时&#xff0c;我是感到有些惊讶的&#xff0c;然后试着去强行理解它&#xf…