Linux——共享内存

目录

一、共享内存概念

 二、共享内存的一些函数

2.1 shmget 创建共享内存

2.2 shmat 访问共享内存 

2.3 shmdt 解除共享内存的映射

2.4 shnctl 删除共享内存段

三、共享内存 

3.1 创建测试进程

3.2 使用循环测试

​编辑

3.3 共享内存写入程序

3.4 带有信号量的共享内存 


一、共享内存概念

共享内存是一种进程间通信的方式,允许多个进程访问和操作同一块内存区域。这样的内存区域被所有共享它的进程所拥有,进程可以将数据写入共享内存区域,也可以从中读取数据。共享内存在提高进程通信效率和降低开销方面具有优势,但也需要进行同步和互斥操作以避免数据竞争和冲突。

共享内存通常适用于需要高效地在进程间传递大量数据的场景,比如多个进程需要共享大型数据结构、图形图像处理或多媒体应用等。在使用共享内存时,需要注意管理内存的权限、同步访问和处理异常情况等问题,以确保数据的一致性和安全性。

 二、共享内存的一些函数

2.1 shmget 创建共享内存

它的函数原型如下:

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

参数含义:

1. key: 用于标识共享内存段的键值,不同的进程使用相同的 key 值可以获取到同一个共享内存
2. size: 创建共享内存时,指定要申请的共享内存空间大小
3. shmflg: 用于指定创建共享内存段的访问权限和其他标志,比如权限位和内存段的创建方式等。常见的标志包括IPC_CREAT(如果不存在则创建共享内存段)和 IPC_EXCL(如果存在则返回错误)。
shmget() 成功则返回共享内存的 ID, 失败返回-1
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}}

2.2 shmat 访问共享内存 

函数shmat()用于将共享内存段附加到调用进程的地址空间,并返回一个指向共享内存段起始地址的指针。

它的函数原型如下:

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

参数含义:

  1. shmid: 表示要附加的共享内存段的标识符,通常是由shmget()函数返回的共享内存标识符。

  2. shmaddr: 指定共享内存段连接到调用进程地址空间的地址。一般设置为 NULL,由系统自动选择映射的虚拟地址空间

  3. shmflg: 用以指定附加共享内存段的附加方式。常见的标志包括SHM_RDONLY(只读方式附加共享内存段)和 SHM_RND(指示共享内存段将在系统限定的地址范围内附加)。 一般给 0, 可以给 SHM_RDONLY 为只读模式,其他的为读写

返回值:

       函数的返回值是一个指针,指向共享内存段的起始地址。  shmat()成功则返回共享内存的首地址,失败返回 NULL
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}strcpy(s,"hello");shmdt(s);}

2.3 shmdt 解除共享内存的映射

当进程不再需要访问共享内存时,需要使用 shmdt 函数将共享内存段从进程地址空间中解除映射。其函数原型如下:

int shmdt(const void *shmaddr);
参数含义:
  1. shmaddr: 表示要分离的共享内存段的起始地址。通常是由shmat()函数返回的指针,指向共享内存段的起始位置。

返回值:

        当成功分离共享内存段时,函数返回0。如果出现错误,函数会返回-1,并且可以通过检查errno变量来获取错误信息。

2.4 shnctl 删除共享内存段

函数shmctl()用于控制共享内存段的属性

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

参数含义:

  1. shmid: 共享内存段的标识符,通常由shmget()函数返回。

  2. cmd: 控制命令,指定对共享内存段执行的操作类型。常见的命令有:

    • IPC_STAT: 获取共享内存段的状态信息,并将其存储在buf指向的shmid_ds结构体中。
    • IPC_SET: 设置共享内存段的权限模式,需要提供buf指向的shmid_ds结构体。
    • IPC_RMID: 从系统中删除共享内存段,同时释放其占用的资源。
  3. buf: 指向一个shmid_ds结构体的指针,用于存储或传递共享内存段的状态信息或权限设置。

返回值:

        函数成功执行时返回0,否则返回-1,并通过设置errno变量来指示错误类型。

三、共享内存 

3.1 创建测试进程

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}printf("s=%s\n",s);// 打印共享内存的地址shmdt(s);}

运行结果:

3.2 使用循环测试

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}while(1){if(strncmp(s,"end",3) == 0){break;}printf("s=%s\n",s);sleep(1);}shmdt(s);}

3.3 共享内存写入程序

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}while(1){printf("input\n");char buff[128]={0};fgets(buff,128,stdin);strcpy(s,buff);if( strncmp(buff,"end",3) == 0){break;}}shmdt(s);
}

3.4 带有信号量的共享内存 

首先要创建两个信号量,一个设为0,另一个设为1。

头文件代码sem.h

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/sem.h>enum INDEX{SEM1=0,SEM2};union semun
{int val;
};void sem_init();//创建并初始化信号量
void sem_p(int index);
void sem_v(int index);
void sem_destroy();

sem.c代码

#include"sem.h"static int semid=-1;void sem_init()//创建并初始化信号量
{semid=semget((key_t)1234,2,IPC_CREAT|IPC_EXCL|0600);if(semid==-1){semid=semget((key_t)1234,2,0600);if(semid==-1){printf("semget err\n");}}else{int arr[2]={1,0};for(int i=0;i<2;i++){union semun a;a.val=arr[i];if(semctl(semid,i,SETVAL,a)==-1){printf("semctl init err\n");}}}
}void sem_p(int index)
{struct sembuf buf;buf.sem_num=index;buf.sem_op=-1;//pbuf.sem_flg=SEM_UNDO;if(semop(semid,&buf,1) == -1){printf("op p err\n");}
}void sem_v(int index)
{struct sembuf buf;buf.sem_num=index;buf.sem_op=1;//vbuf.sem_flg=SEM_UNDO;if(semop(semid,&buf,1) == -1){printf("op v err\n");}
}void sem_destroy()
{if(semctl(semid,0,IPC_RMID) == -1){printf("semctl del\n");}
}

使用信号量的main.c代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
#include"sem.h"int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}sem_init();//创建 初始化while(1){printf("input\n");char buff[128]={0};fgets(buff,128,stdin);sem_p(SEM1);//p  s1strcpy(s,buff);sem_v(SEM2);//v  s2if( strncmp(buff,"end",3) == 0){break;}}shmdt(s);
}

测试代码test.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/shm.h>
#include"sem.h"int main()
{int shmid = shmget((key_t)2345,128,IPC_CREAT|0600);if(shmid == -1){exit(1);}char* s=(char*)shmat(shmid,NULL,0);if(s==(char*)-1){exit(1);}sem_init();while(1){sem_p(SEM2);if(strncmp(s,"end",3) == 0){break;}printf("s=%s\n",s);sem_v(SEM1);}shmdt(s);sem_destroy();exit(0);
}

运行结果:

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

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

相关文章

数启新疆,智领未来!2025新疆数字经济发展战略研讨会在乌市启幕

2025年4月20日&#xff0c;由新疆维吾尔自治区数字经济联合会主办、中钧科技有限公司承办的"2025新疆数字经济发展战略研讨会"将在乌鲁木齐水磨沟区金正大厦三层会议中心隆重召开。 作为本年度新疆数字经济领域规格最高的行业盛会&#xff0c;会议将汇聚自治区14个厅…

Nginx:轻量级高性能的Web服务器与反向代理服务器

目录 一.引言 二.Nginx的核心特点 2.1高性能与高并发 2.2低资源消耗 2.3功能丰富 2.4高度扩展性 三.Nginx的应用场景 3.1静态资源服务器 3.2反向代理服务器 3.3API网关 3.4Nginx的配置与使用 四.总结 一.引言 在互联网高速发展的今天&#xff0c;Web服务器的性能与…

嵌入式Linux设备使用Go语言快速构建Web服务,实现设备参数配置管理方案探究

本文探讨&#xff0c;利用Go语言及gin框架在嵌入式Linux设备上高效搭建Web服务器&#xff0c;以实现设备参数的网页配置。通过gin框架&#xff0c;我们可以在几分钟内创建一个功能完善的管理界面&#xff0c;方便对诸如集中器&#xff0c;集线器等没有界面的嵌入式设备的管理。…

KALI搭建log4j2靶场及漏洞复现全流程

这里使用了两台KALI虚拟机&#xff0c;一台用于安装靶场环境&#xff0c;一台用于攻击 一、Docker的安装&#xff08;靶机&#xff09; 1、Linux内核版本查看 #安装docker要求内核版本kerner>3.10 #为此&#xff0c;先检查当前Linux系统的内核版本 uname -a 2、Linux apt…

学习笔记—C++—模板初阶

目录 模板初阶 泛型编程 函数模板 模版概念 函数模版格式 模版的原理 函数模板的实例化 模版参数的匹配规则 类模板 模板初阶 泛型编程 使用函数重载虽然可以实现&#xff0c;但是有一下几个不好的地方&#xff1a; 1. 重载的函数仅仅是类型不同&#xff0c;代码复…

Docker 中多个容器之间的通信

在 Docker 中&#xff0c;多个容器之间的通信可以通过以下几种主要方式实现&#xff0c;具体选择取决于网络需求、隔离性及管理复杂度&#xff1a; 一、自定义 Bridge 网络&#xff08;推荐&#xff09; 通过创建自定义的 Docker 网络&#xff0c;容器可以加入同一网络并通过容…

Day1-初次接触UFS

经过导师初次介绍&#xff0c;了解工作以芯片测试为主&#xff0c;需坚持学习&#xff0c;小白大致需3-6月入门。整体学习应分为3大块&#xff0c;UFS协议占40%&#xff08;3-4h&#xff09;,C技能占40%&#xff08;3-4h&#xff09;,工具或业务占20%&#xff08;1-2h&#xff…

【LeetCode 热题100】二叉树构造题精讲:前序 + 中序建树 有序数组构造 BST(力扣105 / 108)(Go语言版)

&#x1f331; 二叉树构造题精讲&#xff1a;前序 中序建树 & 有序数组构造 BST 本文围绕二叉树的两类构造类题目展开解析&#xff1a; 从前序与中序遍历序列构造二叉树 将有序数组转换为二叉搜索树 我们将从「已知遍历构造树」和「平衡构造 BST」两个角度&#xff0c;拆…

JMeter重要的是什么

重要特性 支持多种协议&#xff1a; JMeter支持对多种协议进行性能测试&#xff0c;包括HTTP、HTTPS、FTP、JDBC&#xff08;数据库&#xff09;、LDAP、JMS、SOAP、REST等。这使得它能够适应各种不同的测试场景。强大的负载模拟能力&#xff1a; JMeter能够模拟大量的虚拟用户…

一文读懂WPF系列之MVVM

WPF MVVM 什么是MVVMWPF为何使用MVVM机制WPFMVVM 的实现手段 INotifyPropertyChanged​数据绑定的源端通知​​原理 PropertyChanged事件双向绑定的完整条件常见疑惑问题 什么是MVVM 翻译全称就是 model-view-viewmodel 3部分内容 以wpf的概念角度来解释就是 数据库数据源模型…

OCR API识别对比

OCR 识别DEMO OCR识别 demo 文档由来 最开始想使用百度开源的 paddlepaddle大模型 研究了几天&#xff0c;发现表格识别会跨行&#xff0c;手写识别的也不很准确。最终还是得使用现成提供的api。。 文档说明 三个体验下来 腾讯的识别度比较高&#xff0c;不论是手写还是识别表…

嵌入式MCU常用模块

日后填坑。 无线通信模块 2.4G 基本介绍 以NRF24L01为例。 NRF24L01是一款2.4GHz的无线收发模块&#xff0c;支持SPI通信协议&#xff0c;具有低功耗、高数据速率&#xff08;250kbps-2Mbps&#xff09;和多设备通信能力。 它可以同时与最多6个其他模块通信&#xff0c;适合…

记一次InternVL3- 2B 8B的部署测验日志

测试效果&#xff1a; 问题和耗时如图 5、资源占用 不释放资源会一直涨显存。总体还算满意&#xff0c;我试了好多个图理解大模型&#xff0c;就属它牛一点 附图一张 补充&#xff0c;测试InternVL3-2B的结果 1、模型下载魔搭社区 2、运行环境&#xff1a; 1、硬件 RTX 30…

Java版本对应关系表

Java版本对应关系表 以下Java主要版本&#xff08;Major Version&#xff09;与公开大版本号的对应关系 公开大版本名称Major 版本号内部版本号格式示例&#xff08;java -version输出&#xff09;Java 8 (1.8)52 (0x34)1.8.0_XXX1.8.0_301Java 953 (0x35)9.0.X9.0.4Java 105…

2025最新版flink2.0.0安装教程(保姆级)

Flink支持多种安装模式。 local&#xff08;本地&#xff09;——本地模式 standalone——独立模式&#xff0c;Flink自带集群&#xff0c;开发测试环境使用 standaloneHA—独立集群高可用模式&#xff0c;Flink自带集群&#xff0c;开发测试环境使用 yarn——计算资源统一…

android11 配置默认电池优化白名单

目录 1.介绍 2.读取配置文件 3.默认配置一个白名单列表 1.介绍 在 Android 11 中,DeviceIdleController 是负责控制设备进入 Doze 模式(闲置模式) 的核心系统服务,其内部方法 readConfigFileLocked() 负责从配置文件中读取 Doze 模式的行为参数,包括 idle 阶段的时间间…

java中的Future的设计模式 手写一个简易的Future

案例 例如&#xff1a;今天是小妹的生日&#xff0c;需要一个蛋糕有点仪式感&#xff0c;于是去蛋糕店预定&#xff0c;预定完之后&#xff0c;店老板说蛋糕做好了&#xff0c;到时电话通知你&#xff0c;不可能在这傻傻的等着吧&#xff0c;还有其他事情要做啊&#xff0c;于…

【Redis】Redis C++使用

一、Redis的自定义网络协议 1.1 为什么可以编写出一个自定义的Redis客户端 为什么我们可以编写出一个自定义的Redis客户端&#xff1f;因为Redis公开了自己的自定义协议。而对于一些其他软件的客户端&#xff0c;我们无法编写出一个自定义的Redis客户端&#xff0c;因为他们没…

【软考系统架构设计师】软件工程知识点

1、 软件开发生命周期 软件定义时期&#xff1a;包括可行性研究和详细需求分析过程&#xff0c;任务是确定软件开发工程必须完成的总目标&#xff0c;具体分为问题定义、可行性研究、需求分析等 软件开发时期&#xff1a;软件的设计与实现&#xff0c;分为概要设计、详细设计、…

DeepSeek 与开源:肥沃土壤孕育 AI 硕果

当国产 AI DeepSeek 以其低成本推理和多模态能力在全球范围内引起轰动时&#xff0c;人们惊叹于中国技术的迅猛发展&#xff0c;却很少有人深究这一成就背后的根基。答案其实早已写在中国开源生态二十多年的发展历程中。 从倪光南院士提出“以开源打破技术垄断”的理念&#x…