Linux: shm_xx系列函数使用详解

目录

  • 一、shmget/shmctl/shmat/shmdt函数
    • 1、shmget
    • 2、shmctl
    • 3、shmat
    • 4、shmdt
    • 5、补充:ftok函数
    • 6、示例代码
  • 二、shm_open/shm_unlink函数
    • 1、shm_open
    • 2、shm_unlink
    • 3、示例代码
  • 三、课外阅读

一、shmget/shmctl/shmat/shmdt函数

  shm_xx系列函数是用于操作共享内存的一组函数,它们通常包括shmget、shmctl、shmat和shmdt。下面对这些函数进行详细解释:

1、shmget

  • 功能:创建一个新的共享内存段或获取一个已经存在的共享内存段的标识符。
  • 原型int shmget(key_t key, size_t size, int shmflg)
  • 参数
    • key:用于识别共享内存段的键值,通常使用 ftok 函数生成。
    • size:共享内存段的大小。单位是字节。
    • shmflg:打开标志,用于指定操作的方式,比如创建共享内存段、获取共享内存标识符等。
  • 返回值:成功时返回共享内存段的标识符(非负整数),失败时返回-1。
    shmget 函数是用于创建共享内存段、获取共享内存标识符或者访问一个已存在的共享内存段的函数,其声明如下:

  shmget 函数的主要功能包括:

  • 如果指定的 key 对应的共享内存段不存在,并且设置了创建标志(IPC_CREAT),则会创建一个新的共享内存段,大小为 size 字节。
  • 如果指定的 key 对应的共享内存段存在,则会返回共享内存标识符。
  • 如果不希望创建共享内存段,可以不设置 IPC_CREAT 标志。此时若指定的 key 对应的共享内存段不存在,shmget 函数将会返回错误。

  shmget 函数的返回值是共享内存标识符(shmid),用于后续对共享内存段的访问操作,比如连接共享内存、获得共享内存的地址等。

  在使用 shmget 函数时,需要注意确保对共享内存的大小和权限的设置,避免潜在的问题,比如内存溢出或者权限不足等。同时,需要根据具体需求合理设置 shmflg 参数,确保对共享内存的访问操作符合预期。

2、shmctl

  • 功能:用于控制共享内存段。
  • 原型int shmctl(int shmid, int cmd, struct shmid_ds *buf)
  • 参数
    • shmid:是共享内存标识符,是由 shmget 函数返回的。
    • cmd:是控制命令,用于指定对共享内存的具体操作,比如删除共享内存段、获取共享内存信息等。
    • buf:是指向 shmid_ds 结构体的指针,用于传递或者获取共享内存的信息。
  • 返回值:成功时返回0,失败时返回-1。
    shmctl 函数是用于控制共享内存段的操作函数,主要用于对共享内存段进行控制操作,比如删除、获取信息等,其声明如下:

shmctl 函数的主要功能包括:

  • 获取共享内存段的信息,比如共享内存大小、关联进程数等。
  • 控制共享内存段的权限,比如修改共享内存的权限。
  • 删除共享内存段。

cmd 参数可以取以下值之一:

  • IPC_STAT:获取共享内存的状态信息,并将其存储在 buf 指向的结构体中。
  • IPC_SET:设置共享内存的状态信息,更新共享内存的权限等。
  • IPC_RMID:删除共享内存段,释放资源。

  需要注意的是,在使用 shmctl 函数时,要根据具体需求选择合适的控制命令,并确保传入正确的参数,以免出现意外的错误。同时,删除共享内存段时,需要注意确保所有关联进程已经分离了共享内存段,否则删除操作可能会失败。

3、shmat

  • 功能:将共享内存段连接到调用进程的地址空间。
  • 原型void *shmat(int shmid, const void *shmaddr, int shmflg)
  • 参数
    • shmid:是共享内存标识符,是由 shmget 函数返回的。
    • shmaddr:是一个指针,用于指定将共享内存段映射到进程地址空间的地址,通常设为 NULL
    • shmflg:参数用于指定连接共享内存段的标志,通常可以设置为 0。
  • 返回值:成功时返回指向共享内存段起始地址的指针,失败时返回-1。

  shmat 函数的主要作用是将共享内存段连接到当前进程的地址空间,实现进程对共享内存段的访问。连接成功后,shmat 函数将返回一个指向共享内存段起始地址的指针,进程可以通过该指针来访问共享内存段中的数据。

  一般情况下,shmaddr 参数设为 NULL,由系统自动选择合适的地址来映射共享内存段到进程地址空间中。shmflg 参数通常设为 0,表示默认的连接标志,除非有特殊需求,一般不需要修改。

  需要注意的是,在使用 shmat 函数时,要确保传入正确的共享内存标识符 shmid,避免出现连接错误。另外,在使用完共享内存后,要及时调用 shmdt 函数将共享内存段从当前进程地址空间中分离,避免资源泄漏。

4、shmdt

  • 功能:将共享内存段从调用进程的地址空间中分离。
  • 原型int shmdt(const void *shmaddr)
  • 参数
    • shmaddr:是共享内存段连接到进程地址空间的起始地址,通常是由 shmat 函数返回的。
  • 返回值:成功时返回0,失败时返回-1。

  shmdt 函数的主要作用是断开当前进程与共享内存段的连接,使得进程无法再访问共享内存段中的数据。调用 shmdt 函数后,共享内存段仍然存在,但当前进程无法再对其进行操作。

  在使用 shmdt 函数时,需要传入正确的共享内存段起始地址 shmaddr,确保将正确的共享内存段从当前进程中分离。另外,需要注意的是,分离共享内存段后,如果没有其他进程仍然连接着该共享内存段,系统会释放该共享内存段,从而释放相关资源。

  在使用共享内存时,需要注意合理地管理共享内存的连接和分离,避免出现资源泄漏或者错误的操作。

ftok 函数是一个用于生成一个 System V IPC(Inter-Process Communication,进程间通信)键值的函数,其声明如下:

5、补充:ftok函数

key_t ftok(const char *pathname, int proj_id);
  • pathname 参数是一个指向字符串的指针,用于指定一个已经存在的文件的路径名。
  • proj_id 参数是一个用户定义的整数,可以是 0 到 255 的范围内的任意值。

  ftok 函数会根据指定的 pathnameproj_id 生成一个唯一的键值,用于创建或访问 System V IPC 的资源,如共享内存、信号量和消息队列。

  实际上,ftok 函数根据 pathname 参数对应文件的 inode 号和 proj_id 参数生成一个 32 位的键值,最高 8 位存放 proj_id,低 24 位存放 pathname 对应文件的 inode 号的后 24 位。这样可以保证相同的 pathnameproj_id 参数生成相同的键值。

  需要注意的是,在使用 ftok 函数时要确保 pathname 参数是一个已经存在的文件的路径名,否则会导致生成的键值不唯一。另外,proj_id 参数的取值范围是 0 到 255,超出这个范围可能导致键值重复。

  综上所述,ftok 函数是用于生成 System V IPC 键值的一个实用工具函数,可以通过指定文件路径和项目标识来确保生成唯一的键值,用于进程间通信的各种资源的创建和访问。

6、示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_SIZE 1024 // 共享内存大小int main() {key_t key = ftok("shmfile", 'R'); // 创建共享内存的键值int shmid;// 创建共享内存段shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);if (shmid == -1) {perror("shmget");exit(1);}// 连接共享内存段char *shmaddr = (char *)shmat(shmid, NULL, 0);if (shmaddr == (char *)-1) {perror("shmat");exit(1);}// 写入数据到共享内存strcpy(shmaddr, "Hello, Shared Memory!");printf("Data written to shared memory: %s\n", shmaddr);// 分离共享内存段if (shmdt(shmaddr) == -1) {perror("shmdt");exit(1);}// 删除共享内存段if (shmctl(shmid, IPC_RMID, 0) == -1) {perror("shmctl");exit(1);}return 0;
}

二、shm_open/shm_unlink函数

1、shm_open

  shm_open 是 POSIX 标准中定义的用于创建或打开共享内存对象的函数。与传统的 shmget 函数类似,shm_open 提供了一种不同的方式来管理共享内存,使用文件描述符来标识共享内存对象。shm_open 的原型如下:

int shm_open(const char *name, int oflag, mode_t mode);
  • name 参数是一个指向表示共享内存对象名称的字符串的指针。共享内存对象通过名称在文件系统中标识。
  • oflag 参数指定了打开共享内存对象时的操作标志,可以是一组位或运算的标志,比如 O_CREAT(创建共享内存对象), O_RDWR(可读写方式打开)等。
  • mode 参数指定了新创建的共享内存对象的权限标志,通常与 open 系统调用中使用的 mode 参数一样。

  使用 shm_open 函数创建或打开共享内存对象后,可以通过标准的文件 I/O 函数(如 readwrite)对共享内存进行读写操作。共享内存对象在文件系统中以名字为标识,不同进程可以通过相同的名字打开同一个共享内存对象,从而实现进程间通信。

  在使用 shm_open 函数时,需要注意以下几点:

  • 共享内存对象的名称必须在当前系统中是唯一的,以避免命名冲突。
  • 在打开共享内存对象后,应谨慎进行读写操作,避免发生竞争条件和数据一致性问题。
  • 当不再需要共享内存对象时,应当使用 shm_unlink 函数来释放该共享内存对象,以防止资源泄漏。

  总的来说,shm_open 提供了一种基于文件描述符的共享内存对象管理方式,使得共享内存在不同进程之间的使用更加灵活和方便。

2、shm_unlink

  shm_unlink 是一个函数,用于删除由 shm_open 创建的共享内存对象的名称。在 POSIX 标准中,共享内存对象在文件系统中以名称标识,使用 shm_open 打开该共享内存对象后,可以通过 shm_unlink 函数删除该对象的名字,但不会立即释放共享内存本身。只有在所有进程都关闭该共享内存对象的文件描述符或调用 shm_unlink 之后,共享内存对象才会被彻底删除。shm_unlink 的原型如下:

int shm_unlink(const char *name);
  • name 参数是一个指向表示要删除的共享内存对象名称的字符串的指针。

  使用 shm_unlink 函数可以确保在不再需要共享内存对象时清理对象的名称,这样可以避免其他进程再次通过该名称打开共享内存对象。但需要注意的是,即使调用了 shm_unlink,只有当所有打开该共享内存对象的文件描述符都关闭,共享内存对象才会被系统真正删除。

  一般来说,在不再需要使用共享内存对象时,建议及时调用 shm_unlink,以便及时释放已不需要的资源。这样可以更好地管理共享内存,避免资源泄漏和冗余共享内存对象的存在。

3、示例代码

  以下是一个简单的示例代码,展示了如何使用 shm_openshm_unlink 函数来创建和删除共享内存对象的名称。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#define SHM_NAME "/my_shared_memory"
#define SHM_SIZE 1024int main() {const char *data = "Hello, this is shared memory demo!";// Create or open a shared memory objectint shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);ftruncate(shm_fd, SHM_SIZE);// Map the shared memory object into memorychar *shm_ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);// Write data to the shared memorystrcpy(shm_ptr, data);printf("Data written to shared memory: %s\n", shm_ptr);// Unmap the shared memorymunmap(shm_ptr, SHM_SIZE);// Close the shared memory objectclose(shm_fd);// Unlink the shared memory object nameshm_unlink(SHM_NAME);return 0;
}

  在这个示例代码中,首先使用 shm_open 函数创建或打开一个共享内存对象,并指定名称为 "/my_shared_memory"。然后使用 ftruncate 函数设置共享内存对象的大小为 SHM_SIZE 字节。

  接着,使用 mmap 函数将共享内存对象映射到当前进程的内存空间中,使得可以对其进行读写操作。将数据写入共享内存后,通过 munmap 函数解除共享内存的映射,并通过 close 函数关闭共享内存对象的文件描述符。

  最后,调用 shm_unlink 函数删除共享内存的名称,这样其他进程就无法再使用该名称打开共享内存对象。

三、课外阅读

推荐阅读:进程间通信–共享内存篇

  欢迎大家指导和交流!如果我有任何错误或遗漏,请立即指正,我愿意学习改进。期待与大家一起进步!

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

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

相关文章

SpringBoot整合JdbcTemplate

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合JdbcTemplate 📚个人知识库: Leo知识库,欢迎大家访问 目录 …

设置文字之间的间距应该如何实现

设置文字之间的间距&#xff0c;通常指的是字母之间&#xff08;字符间距&#xff09;或单词之间的间距。在CSS中&#xff0c;这可以通过letter-spacing和word-spacing属性来实现。 字符间距&#xff08;letter-spacing&#xff09; letter-spacing属性用于调整字符之间的间距…

【Git学习笔记】提交PR

step1 克隆一个仓库 git clone .....step2 创建一个分支 (Creating a branch) # 创建并切换到本地新分支&#xff0c;分支的命名尽量简洁&#xff0c;并与解决的问题相关 git checkout -b delete-unused-linkstep3 做出修改 (Make changes) step4 提交修改 # 保存本地修…

DDR5内存相比DDR4内存的优势和区别?选择哪一个服务器内存配置能避免丢包和延迟高?

根据幻兽帕鲁服务器的实际案例分析&#xff0c;选择合适的DDR4与DDR5内存大小以避免丢包和延迟高&#xff0c;需要考虑以下几个方面&#xff1a; 性能与延迟&#xff1a;DDR5内存相比DDR4在传输速率、带宽、工作电压等方面都有显著提升&#xff0c;但同时也伴随着更高的延迟。D…

PostgreSQL开发与实战(4)查询性能Top SQL

作者&#xff1a;太阳 一、查询当前正在运行的Top SQL 查询当前正在运行的会话中耗时最长的Top SQL&#xff0c;where条件可按需修改SELECT pgsa.datname AS database_name, pgsa.usename AS user_name, pgsa.client_addr AS client_addr, pgsa.application_name AS applicat…

你知道什么是回调函数吗?

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

Unity3D外包 北京动点软件:基于U3D开发自动驾驶技术分析

在Unity3D中开发自动驾驶AI是一个充满挑战和潜力的领域。以下是一些关键步骤和考虑因素&#xff1a; 来百度APP畅享高清图片 1. 创建虚拟环境&#xff1a; 使用Unity3D创建一个逼真的虚拟环境&#xff0c;模拟现实世界的道路、交通标志、车辆和障碍物等。 确保场景具有真实的…

4款免费且实用的.NET反编译工具

.NET 反编译工具的作用 .NET反编译工具能够将已经编译好的.NET程序集转换为易于理解的源代码&#xff0c;它们可以帮助开发人员恢复丢失的源代码、理解和分析第三方组件dll、学习其他人的代码、更好的查找修复 bug 或进行逆向工程等&#xff08;注意&#xff1a;请在法律允许范…

【C++ 标准流,文件流】

C 标准流&#xff0c;文件流 ■ 标准输入&#xff0c;输出流&#xff0c;■ 文件流&#xff08;ofstream写入&#xff0c;ifstream读取&#xff0c;fstream创建-写入-读取&#xff09;■ open()■ ofstream■ ifstream■ 流插入<<■ 文件位置指针 ■ 标准输入&#xff0c…

SpringBoot系列(一):SpringBoot介绍

SpringBoot系列(一)&#xff1a;SpringBoot介绍 1. SpringBoot介绍 SpringBoot是由Pivotal团队提供的一套用于构建微服务的基础框架&#xff0c;它旨在简化Spring应用程序的创建和开发过程。 SpringBoot通过设计大量的自动化配置等方式来简化Spring原有样板化的配置&#xff…

用Visual Studio 2015成功编译、发布UMDF驱动到目标机!!

开发工具&#xff1a;Visual Studio 2015企业版 主 机&#xff1a;windows10 X64企业版&#xff0c;主机是安装了Visual Studio 2015的操作系统&#xff0c;主要进行驱动开发和调试。 目 标 机&#xff1a;windows10 X86企业版&#xff0c;目标机是安装和调试驱动的操作…

阿里巴巴面试必备:数据库集群知识全面解读!

大家好,我是小米。今天,我们将深入探讨阿里巴巴面试题中一个备受关注的话题:数据库集群。作为技术领域中的一项重要实践,数据库集群不仅是企业架构中的核心组成部分,更是保障系统稳定性和数据可靠性的关键一环。让我们一起来揭秘数据库集群的奥秘吧! 主从复制过程 主从…

文件操作(超详细版本)

本章重点 为什么使用文件什么是文件文件的打开和关闭文件的顺序读写文件的随机读写文件读取结束的判定 为什么使用文件 我们前面学习结构体时&#xff0c;写通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c;可以给通讯录中增加、删除数 据&#xff0c;此时数据是…

手势识别应用介绍

目录 一、功能介绍 二、安装部署说明 2.1 文件目录说明 2.2 手势识别部分 一、功能介绍 这是一个通过摄像头捕获手势&#xff0c;根据不同的手势来做出不同操作的计算机程序。目前可以识别9种手势&#xff0c;可以根据识别到的手势&#xff0c;进行打开应用、增大音量、减小音量…

[AIGC] 请举例说明在运行时读取注解的应用场景。

很高兴你对于在运行时读取注解的应用场景感兴趣。以下是我为你整理的一些典型场景&#xff1a; 1. Spring框架 Spring框架广泛地使用了运行时注解。例如Autowired注解&#xff0c;它可以在运行时实现依赖注入的功能。Spring在启动时&#xff0c;会通过反射机制寻找到被Autowi…

mkfs.ext4 --- 对磁盘设备进行Ext4格式化

mkfs.ext4命令来自于英文词组“make filesystem Ext4”的缩写&#xff0c;其功能是用于对磁盘设备进行Ext4格式化的操作。 mkfs.ext4 参数-b block-size 块大小&#xff08;1k,2k,4k&#xff09; -c 坏块测试 -l filename从文件读坏块列表 -C cluster-size 簇大小 (大块分配持性…

交友社交软件开发-php交友聊天系统-

为了开发一个高效的交友系统&#xff0c;需要一个完善的信息管理和筛选机制。这个系统应该能够根据用户的个人信息、兴趣爱好、价值观等标准进行筛选&#xff0c;并向用户提供符合他们要求心仪的人的信息。为了实现这个目标&#xff0c;系统可以利用人工智能技术&#xff0c;分…

MySQL基础-----SQL语句之DDL语句

目录 前言 开启登录数据库 一、数据库操作 1.查询所有数据库 2.切换使用数据库 3.查询当前使用的数据库 4.创建数据库 创建一个hello数据库, 使用数据库默认的字符集。 创建一个itheima数据库&#xff0c;并且指定字符集 5.删除数据库 二、表操作 1.查询当前数据库所有…

JAVA的学习日记

JAVA的学习日记&#xff08;2024.3.1&#xff09;&#xff08;b站韩顺平老师课程学习笔记版&#xff09; ps:捡起忘光光的Java语言 Sublime //1. public是公有&#xff0c;class是类 //2. public class Hello表示Hello是一个类&#xff0c;是一个public公有的类 //3. Hello{…

解决Unable to load class ‘org.gradle.api.attributes.VerificationType‘

在使用AdnroidStudio开发过程中难免会遇到Unable to load class org.gradle.api.attributes.VerificationType报错&#xff0c;可以尝试清理缓存重启解决 打开 File-》Invalidate Caches... 重启AndroidStudio后&#xff0c;重新加载即可&#xff0c;但也不是百分百解决。