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

linux 共享内存操作(shm_open、mmap、编译链接库:-lz -lrt -lm -lc都是什么库)

文章目录

  • linux 共享内存操作(shm_open)
    • 一、背景
    • 二、函数使用说明
      • shm_open
      • ftruncate(改变文件大小)
      • mmap共享内存
    • 三、示例代码
      • 创建内存共享文件并写入数据
      • 打开内存共享文件读数据
    • 四、问题总结
      • shm_write.c:(.text+0x18): undefined reference to `shm_open'
        • 编译链接库:-lz -lrt -lm -lc都是什么库
    • 五、参考

linux 共享内存操作(shm_open)

一、背景

在linux系统开发当中,时常需要在多个进程之间交换数据,在多个进程之间交换数据,有很多方法,但最高效的方法莫过于共享内存。

共享内存并不是从某一进程拥有的内存中划分出来的;进程的内存总是私有的。共享内存是从系统的空闲内存池中分配的,希望访问它的每个进程连接它。这个连接过程称为映射,它给共享内存段分配每个进程的地址空间中的本地地址。

linux共享内存是通过tmpfs文件系统来实现的,tmpfs文件系的目录为/dev/shm,/dev/shm是驻留在内存 RAM 当中的,因此读写速度与读写内存速度一样,/dev/shm的容量默认尺寸为系统内存大小的一半大小,使用df -h命令可以看到。

root@i-3t537lcq:~# free -htotal        used        free      shared  buff/cache   available
Mem:          1.9Gi       226Mi       175Mi        20Mi       1.5Gi       1.5Gi
Swap:         2.0Gi        62Mi       1.9Gi
root@i-3t537lcq:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            952M     0  952M   0% /dev
tmpfs           199M  1.4M  198M   1% /run
/dev/vda2        50G   13G   35G  27% /
tmpfs           994M   16K  994M   1% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           994M     0  994M   0% /sys/fs/cgroup
tmpfs           199M     0  199M   0% /run/user/0
/dev/loop2       64M   64M     0 100% /snap/core20/1778
/dev/loop7       50M   50M     0 100% /snap/snapd/17950
/dev/loop8      138M  138M     0 100% /snap/lxd/24239
/dev/loop4      145M  145M     0 100% /snap/lxd/24323
/dev/loop5       56M   56M     0 100% /snap/core18/2679
/dev/loop3       64M   64M     0 100% /snap/core20/1822
/dev/loop1       50M   50M     0 100% /snap/snapd/18357
/dev/loop9       56M   56M     0 100% /snap/core18/2697
root@i-3t537lcq:~#

实际上它并不会真正的占用这块内存,如果/dev/shm/下没有任何文件,它占用的内存实际上就是0字节,仅在使用shm_open文件时,/dev/shm才会真正占用内存。

二、函数使用说明

Linux的共享内存提供了进程之间共享数据的一种方法,可以避免进程之间的数据复制。Linux的共享内存API有两套,即POSIX共享内存和System V共享内存。POSIX共享内存其实是基于mmap实现的。

共享内存一般基本操作流程如下:

  1. 使用shm_open来新建或者打开一个共享内存
  2. 如果是创建一个新的共享内存对象,那么调用ftruncate设置共享内存对象的最大大小
  3. 使用mmap将共享内存映射到进程的地址空间中,然后操作共享内存
  4. 操作完毕后,使用munmap解除映射。解除映射后,本进程就不能再访问共享内存,但共享内存对象依然还是存在的
  5. 调用close关闭shm_open返回的文件描述符。如果进程修改了共享内存,那么在close之前可一调用fsync来同步。
  6. 如果没有任何进程再访问共享内存对象,可以调用shm_unlink来删除共享内存对象

在Linux系统使用共享内存,POSIX 为创建、映射、同步和取消共享内存段提供五个入口点:

int shm_open(const char *name, int oflag, mode_t mode);
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);
int ftruncate(int fd, off_t length);
  • shm_open():创建共享内存段或连接到现有的已命名内存段。这个系统调用返回一个文件描述符。
    shm_open最主要的操作也是默认的操作就是在/dev/shm/下面,建立一个文件。
  • mmap():把共享内存段映射到进程的内存。这个系统调用需要 shm_open() 返回的文件描述符,它返回指向内存的指针。
  • shm_unlink():根据(shm_open() 返回的)文件描述符,删除共享内存段。实际上,这个内存段直到访问它的所有进程都退出时才会删除,这与在 UNIX 中删除文件很相似。但是,调用 shm_unlink() (通常由原来创建共享内存段的进程调用)之后,其他进程就无法访问这个内存段了。
  • munmap():作用与 mmap() 相反。
  • msync():用来让共享内存段与文件系统同步 — 当把文件映射到内存时
  • ftruncate(改变文件大小)
    参数fd为已打开的文件描述词,而且必须是以写入模式打开的文件。
    ftruncate函数是用来截断指定文件的一个系统调用,它可以改变指定文件的大小.当指定的文件的大小比原先的大时,那么多余的部分将会以0填充.
    如果原来的文件大小比参数length大,则超过的部分会被删去。

文件名字是用户自己输入的。另外一定要用ftruncate把文件大小于设置为共享内存大小。

shm_open

int shm_open(const char *name, int oflag, mode_t mode);

功能说明:shm_open 用于创建或者打开共享内存文件。shm_open 也许仅仅是系统函数open的一个包装,不同之处就是shm_open操作的文件一定是位于tmpfs文件系统里的,常见的Linux发布版的tmpfs文件系统的存放目录就是/dev/shm

用shm_open 创建的文件,如果不调用此函数(shm_unlink)删除,会一直存在于/dev/shm目录里,直到操作系统重启或者调用linux命令rm来删除为止。

返回值:成功返回fd>0, 失败返回fd<0

参数说明:

name:要打开或创建的共享内存文件名,由于shm_open 打开或操作的文件都是位于/dev/shm目录的,因此name不能带路径,例如:/var/myshare 这样的名称是错误的,而 myshare 是正确的,因为 myshare 不带任何路径。如果你一定要在name添加路径,那么,请在/dev/shm目录里创建一个目录,例如,如果你想创建一个 bill/myshare 的共享内存文件,那么请先在/dev/shm目录里创建 bill这个子目录,由于不同厂家发布的linux系统的tmpfs的位置也许不是/dev/shm,因此带路径的名称也许在别的环境下打开不成功。

oflag:打开的文件操作属性:O_CREAT、O_RDWR、O_EXCL的按位或运算组合

mode:文件共享模式,例如 0777

代码验证demo

yum install gcc

ftruncate(改变文件大小)

ftruncate(改变文件大小)
定义函数 int ftruncate(int fd,off_t length);

  • 函数说明
    ftruncate()会将参数fd指定的文件大小改为参数length指定的大小。
    参数fd为已打开的文件描述词,而且必须是以写入模式打开的文件。
    如果原来的文件大小比参数length大,则超过的部分会被删去。

  • 返回值
    执行成功则返回0,失败返回-1,错误原因存于errno。

  • 错误代码
    EBADF 参数fd文件描述词为无效的或该文件已关闭。
    EINVAL 参数fd 为一socket 并非文件,或是该文件并非以写入模式打开。

mmap共享内存

Linux的共享内存提供了进程之间共享数据的一种方法,可以避免进程之间的数据复制。Linux的共享内存API有两套,即POSIX共享内存和System V共享内存。POSIX共享内存其实是基于mmap实现的。

   #include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);int munmap(void *addr, size_t length);

mmap在调用进程的地址空间中映射一段内存。当参数文件描述符fd为-1时,并在flags中指定MAP_ANONYMOUS,就会生成匿名映射,这种内存映射没有后台文件,可在fork的父子继承中共享(子进程调用execl后不再共享),这也是常用的共享内存手段。当fd参数为某特定文件时,就产生文件映射,不同进程映射统一文件可实现映射区域内存共享的目的。进程对共享内存的操作会在msync调用或者munmap调用后同步到后台文件。

三、示例代码

创建内存共享文件并写入数据

shm_write.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>char buf[10];
char *ptr;int main()
{int fd;fd = shm_open("shm_region", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);if (fd < 0){printf("error open shm_region\n");return 0;}ftruncate(fd, 10);ptr = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (ptr == MAP_FAILED){printf("error map\n");return 0;}*ptr = 0x12;return 0;
}

编译:

gcc -lrt -o  shm_write  shm_write.c

使用hexdump读取共享内存内容:

hexdump /dev/shm/shm_region

打开内存共享文件读数据

shm_read.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
char buf[10];
char *ptr;
int main()
{int fd;fd = shm_open("shm_region", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);if (fd < 0){printf("error open shm_region\n");return 0;}ftruncate(fd, 10);ptr = mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (ptr == MAP_FAILED){printf("error map\n");return 0;}while (*ptr != 0x12);printf("ptr : %d\n", *ptr);return 0;
}

编译:

gcc -lrt -o  shm_read  shm_read.c

执行结果:

[root@dev c]# ./shm_read
ptr : 18
[root@dev c]#

四、问题总结

shm_write.c:(.text+0x18): undefined reference to `shm_open’

问题描述:
执行编译,文件内容包含shm_open方法

 gcc -o shm_write  shm_write.c

报错:shm_write.c:(.text+0x18): undefined reference to `shm_open’

问题分析:
没有找到函数定义,需要 指定动态链接库。

man shm_open

解决方法:
编译参数添加 -lrt

gcc -lrt -o  shm_write  shm_write.c

编译链接库:-lz -lrt -lm -lc都是什么库

-lz 压缩库(Z)
-lrt 实时库(real time):shm_open系列
-lm 数学库(math)
-lc 标准C库(C lib)
-dl ,是显式加载动态库的动态函数库

五、参考

linux 共享内存 shm_open ,mmap的正确使用
原文链接:https://blog.csdn.net/ababab12345/article/details/102931841
Linux编程之共享内存
参考URL: https://blog.csdn.net/rangzh/article/details/112002554

相关文章:

linux 共享内存操作(shm_open、mmap、编译链接库:-lz -lrt -lm -lc都是什么库)

文章目录linux 共享内存操作&#xff08;shm_open&#xff09;一、背景二、函数使用说明shm_openftruncate&#xff08;改变文件大小&#xff09;mmap共享内存三、示例代码创建内存共享文件并写入数据打开内存共享文件读数据四、问题总结shm_write.c:(.text0x18): undefined re…...

做出改变:农业科技和区块链在为地球的未来而战中的力量

到2050年&#xff0c;全球有100亿人需要养活&#xff0c;全世界都在关注区块链和农业信息化&#xff0c;以推动发展中国家的技术革新。 自成立以来&#xff0c;区块链技术已经找到了多样化和有价值的应用&#xff0c;以帮助提高效率和激励社区在不同领域和行业的参与。 农业是…...

树莓派介绍

文章目录一.树莓派介绍二.树莓派分类一.树莓派介绍 树莓派&#xff0c;&#xff08;英语&#xff1a;Raspberry Pi&#xff0c;简写为RPi&#xff0c;别名为RasPi / RPI&#xff09;是为学习计算机编程教育而设计&#xff0c;只有信用卡大小的微型电脑&#xff0c;其系统基于L…...

[神经网络]基干网络之VGG、ShuffleNet

一、VGG VGG是传统神经网络堆叠能达到的极限深度。 VGG分为VGG16和VGG19&#xff0c;其均有以下特点&#xff1a; ①按2x2的Pooling层&#xff0c;网络可以分成若干段 ②每段之内由若干same卷积操作构成&#xff0c;段内Feature Map数量固定不变&#xff1b; ③Feature Map按2的…...

Java 日期时间与正则表达式,超详细整理,适合新手入门

目录 1、java.time.LocalDate类表示日期&#xff1b; 2、java.time.LocalTime类表示时间&#xff1b; 3、java.time.LocalDateTime类表示日期和时间&#xff1b; 4、java.time.format.DateTimeFormatter类用于格式化日期和时间&#xff1b; 5、创建正则表达式对象 6、匹配…...

用Netty实现物联网04:自定义通信协议

上一讲咱们澄清了Netty的一些基本概念,然后也写了一个服务端与客户端通信的简单应答程序。从这一讲开始,就来一步步搭建一个Netty物联网应用。 大多数硬件电子产品,都自带了嵌入式软件,或者说固件。这些嵌入式软件/固件基本上都是用C/C++编写的。由于这些小微电子设备资源极…...

「smardaten」上架钉钉应用中心!让进步再一次发生

使用钉钉的团队小伙伴们&#xff0c;smardaten给您送来福利啦~为了给更多团队提供更优质的应用开发体验&#xff0c;方便用户在线、快速使用无代码&#xff0c;数睿数据近期在【钉钉应用中心】发布smardaten在线版本。继与华为云、亚马逊云建立战略合作之后&#xff0c;smardat…...

3、Maven安装

前言&#xff1a;工具下载地址阿里云盘&#xff1a;Maven&#xff1a;https://www.aliyundrive.com/s/SgHKjQ5doSp提取码: ml40一、什么是maven?Apache Maven是个项目管理和自动构建工具&#xff0c;基于项目对象模型&#xff08;POM&#xff09;的概念。作用&#xff1a;完成…...

tkinter

# 隐藏控件 tl.pack_forget() tb.pack_forget() # 显示控件 tl.pack() tb.pack() 如果您使用 grid 布局管理器&#xff0c;则可以使用 grid_remove() 方法将控件隐藏&#xff0c;使用 grid() 方法将控件显示。例如&#xff1a; # 隐藏控件 tl.grid_remove() tb.grid_remove() #…...

Servlet笔记(6):HTTP状态码

1、状态码 代码消息描述100 Continue只有请求的一部分已经被服务器接收&#xff0c;但只要它没有被拒绝&#xff0c;客户端应继续该请求。101 Switching Protocols服务器切换协议。200 OK请求成功。201 Created该请求是完整的&#xff0c;并创建一个新的资源。202 Accepted该请…...

RocketMQ 延迟队列

什么是延迟队列指消息发送到某个队列后&#xff0c;在指定多长时间之后才能被消费。应用场景RocketMQ 延迟队列定时消息&#xff08;延迟队列&#xff09;是指消息发送到broker后&#xff0c;不会立即被消费&#xff0c;等待特定时间投递给真正的topic。broker有配置项messageD…...

【精准计时】北斗GPS卫星时钟同步改变精准计时年代

【精准计时】北斗GPS卫星时钟同步改变精准计时年代 【精准计时】北斗GPS卫星时钟同步改变精准计时年代 北斗GPS成精确计时先锋   北斗GPS精确时间自动校准技术&#xff0c;是一种简便的获取北斗GPS精确时间信息的专利技术&#xff0c;具有灵敏度高、不受时间及地域限制等特点…...

【C#基础】C# 面向对象编程

序号系列文章5【C#基础】C# 运算符总结6【C#基础】C# 常用语句讲解7【C#基础】C# 常用数据结构文章目录前言面向对象的 C#1&#xff0c;类的概念2&#xff0c;类的定义3&#xff0c;类成员4&#xff0c;对象5&#xff0c;继承6&#xff0c;多态性结语前言 &#x1f60a;大家好&…...

数据结构与算法入门

目录数据结构概述逻辑结构存储结构算法概述如何理解“大O记法”时间复杂度空间复杂度数据结构概述 数据结构可以简单的理解为数据与数据之间所存在的一些关系&#xff0c;数据的结构分为数据的存储结构和数据的逻辑结构。 逻辑结构 集合结构&#xff1a;数据元素同属于一个集…...

【OpenAI】基于 Gym-CarRacing 的自动驾驶练习项目 | 路径训练功能的实现 | GYM-Box2D CarRacing

限时开放&#xff0c;猛戳订阅&#xff01; &#x1f449; 《一起玩蛇》&#x1f40d; &#x1f4ad; 写在前面&#xff1a; 本篇是关于多伦多大学自动驾驶专业项目的博客。GYM-Box2D CarRacing 是一种在 OpenAI Gym 平台上开发和比较强化学习算法的模拟环境。它是流行的 Box2…...

亚马逊、沃尔玛测评自养号测评、退款、撸卡撸货怎么做?

大家好&#xff0c;有很多的测评工作室做亚马逊测评、沃尔玛测评自养号大额退款&#xff0c;撸卡撸货的找到我&#xff0c;问我有什么方式可以解决成本&#xff0c;效率&#xff0c;纯净度&#xff0c;便捷性等问题&#xff0c;测评养号系统从最早的模拟器&#xff0c;虚拟机到…...

Apollo 2.1.0最新版docker 部署多环境 与java spring boot 接入demo (附带一键部署脚本)

最新Apollo 版本发布2.1.0 https://www.apolloconfig.com/#/zh/design/apollo-design 环境说明 ecs 主机一台数据库mysql 8.0docker 环境 apollo 是内网可信应用&#xff0c;最好是部署在内网里面&#xff0c;外网不可使用&#xff0c;避免配置信息泄漏&#xff0c;这里为了方…...

分布式算法 - 一致性Hash算法

一致性Hash算法是个经典算法&#xff0c;Hash环的引入是为解决单调性(Monotonicity) 的问题&#xff1b;虚拟节点的引入是为了解决 平衡性(Balance) 问题。一致性Hash算法引入在分布式集群中&#xff0c;对机器的添加删除&#xff0c;或者机器故障后自动脱离集群这些操作是分布…...

OAuth2.0入门

什么是OAuth2.0 OAuth&#xff08;Open Authorization&#xff09;是一个关于授权&#xff08;authorization&#xff09;的开放网络标准&#xff0c;允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息&#xff0c;而不需要将用户名和密码提供给第三方移动应用或…...

【HTTP——了解HTTP协议及状态码】

一&#xff0c; 什么是通信通信&#xff0c;就是信息的传递和交换。通信三要素&#xff1a;通信的主体&#xff0c;通信的内容&#xff0c;通信的方式现实生活中的通信&#xff1a;我打电话叫小明来我家吃饭【其中通信的主体是&#xff0c;我&#xff0c;小明。通信内容是&…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...