【探索Linux】—— 强大的命令行工具 P.15(进程间通信 —— system V共享内存)

news2024/11/24 15:23:01

在这里插入图片描述

阅读导航

  • 引言
  • 一、system V的概念
  • 二、共享内存
    • (1) 概念
    • (2) 共享内存示意图
    • (3) 共享内存数据结构
  • 三、共享内存的使用
    • 1. 共享内存的使用步骤
      • (1)包含头文件
      • (2)获取键值(ftok函数)
      • (3)创建共享内存段(shmget函数)
      • (4)将共享内存连接到当前进程的地址空间(shmat函数)
      • (5)访问共享内存
      • (6)分离共享内存(shmdt函数)
    • 2. 共享内存的使用示例
      • 进程1:创建共享内存并写入数据
      • 进程2:连接共享内存并读取数据
  • 四、共享内存的优缺点
  • 温馨提示

引言

在多进程编程中,进程间通信(IPC)是一项关键技术,它使得不同的进程能够相互交换数据和协调行为。而在众多的IPC机制中,System V共享内存是一种高效且强大的通信方式。通过使用共享内存,我们可以将数据从一个进程快速地传递给另一个进程,避免了复制数据的开销,提高了数据传输的效率。同时,由于共享内存是在进程之间共享的内存区域,进程可以直接在该内存区域进行读写操作,从而实现了高效的数据交换。本文将深入探讨System V共享内存的原理、使用方法以及相关函数,并结合实际场景介绍如何利用共享内存进行进程间通信。无论您是初学者还是有经验的开发者,本文都将为您提供全面的指导,帮助您更好地掌握System V共享内存,并应用于您的项目中。让我们一起深入研究进程间通信的精髓,开启高效、协同的多进程编程之旅吧!😍

一、system V的概念

System V是指AT&T公司开发的一系列UNIX操作系统版本,它是UNIX历史上最著名和广泛使用的一个分支。System V在1979年发布,其名称中的“V”代表着罗马数字5,表明它是UNIX的第五个主要版本。

System V引入了许多重要的功能和概念,其中之一就是System V IPC(进程间通信)。System V IPC是一组用于在不同进程之间传递数据和协调行为的机制。它包括三种主要的IPC机制:共享内存(Shared Memory)、消息队列(Message Queues)和信号量(Semaphores)

二、共享内存

(1) 概念

🍁在Linux系统中,System V共享内存是一种用于进程间通信的机制,它允许多个进程访问同一块物理内存,从而实现数据共享

🍁共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

(2) 共享内存示意图

在这里插入图片描述

(3) 共享内存数据结构

struct shmid_ds {
	struct ipc_perm shm_perm; /* operation perms */
	int shm_segsz; /* size of segment (bytes) */
	__kernel_time_t shm_atime; /* last attach time */
	__kernel_time_t shm_dtime; /* last detach time */
	__kernel_time_t shm_ctime; /* last change time */
	__kernel_ipc_pid_t shm_cpid; /* pid of creator */
	__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
	unsigned short shm_nattch; /* no. of current attaches */
	unsigned short shm_unused; /* compatibility */
	void *shm_unused2; /* ditto - used by DIPC */
	void *shm_unused3; /* unused */
};

struct shmid_ds 是 System V 共享内存的状态信息结构体,在 Linux 系统中用来描述共享内存段的属性和状态。下面是 struct shmid_ds 结构体中各个成员的含义:

成员含义
struct ipc_perm shm_perm用于描述共享内存的操作权限。
int shm_segsz共享内存段的大小,以字节为单位。
__kernel_time_t shm_atime最后一次附加(attach)该共享内存的时间。
__kernel_time_t shm_dtime最后一次分离(detach)该共享内存的时间。
__kernel_time_t shm_ctime最后一次修改该共享内存的时间。
__kernel_ipc_pid_t shm_cpid创建者进程的进程号(PID)。
__kernel_ipc_pid_t shm_lpid最后一次操作该共享内存的进程号(PID)。
unsigned short shm_nattch当前附加(attach)该共享内存的进程数。
unsigned short shm_unused未使用的字段,用于兼容性。
void* shm_unused2未使用的字段,由 DIPC(Distributed Inter-Process Communication)使用。
void* shm_unused3未使用的字段。

🥰通过这些状态信息,我们可以获取共享内存段的大小、权限、最后访问时间、创建者信息以及当前附加进程的数量等相关信息。这些信息对于管理和监控共享内存非常有用,能够帮助我们更好地理解和控制共享内存的状态。

三、共享内存的使用

1. 共享内存的使用步骤

(1)包含头文件

首先,在程序中包含 <sys/ipc.h><sys/shm.h><sys/types.h> 头文件,以便能够使用共享内存相关的函数和数据结构。

(2)获取键值(ftok函数)

ftok 函数是一个用于生成 System V IPC(进程间通信)键值的函数,它通常用于创建消息队列、共享内存和信号量的标识符。其原型如下:

key_t ftok(const char *pathname, int proj_id);
  • pathname 参数是一个指向路径名的指针,它引用一个现有的目录项。
  • proj_id 是一个用户定义的整数,用来区分不同的 IPC 对象。

ftok 函数会将给定的路径名和项目 ID 转换成一个唯一的 key 值,以便在创建或获取 IPC 对象时使用。这个 key 值是一个标识 IPC 对象的关键参数,确保了不同的 IPC 对象具有不同的标识符。

需要注意的是,ftok 函数并不是一个完美的方法来生成唯一的 IPC 键值,因为它对路径名和项目 ID 的要求比较严格,而且在不同的系统上可能会有一些限制。另外,由于 ftok 使用的是低位 8 位作为唯一标识,所以在某些情况下可能存在冲突。(可以类比C++中的哈希函数)

(3)创建共享内存段(shmget函数)

shmget 函数用于创建或获取一个共享内存段。它的原型如下:

int shmget(key_t key, size_t size, int shmflg);
  • key 是通过 ftok 函数生成的键值,用于标识共享内存段。
  • size 是共享内存段的大小,以字节为单位。
  • shmflg 是用来指定权限和行为的标志位。

shmget 函数的功能如下:

  1. 如果以给定的键值 key 找到了一个共享内存段,则返回该共享内存段的标识符(非负整数)。
  2. 如果以给定的键值 key 没有找到对应的共享内存段,则根据 shmflg 参数的设置来创建一个新的共享内存段,并返回该共享内存段的标识符。
  3. 当创建一个新的共享内存段时,需要指定共享内存段的大小 size。如果创建成功,操作系统会分配足够的内存空间来容纳这个大小的共享内存段,并返回其标识符。
  4. shmflg 参数可以用来指定共享内存段的权限和行为,例如读写权限、创建新的共享内存段还是获取已有的共享内存段等。

需要注意的是,共享内存段在整个系统中是全局可见的,可以被多个进程同时访问。因此,在使用共享内存时,需要确保进程之间的同步和互斥,以避免数据竞争和不一致性的问题

(4)将共享内存连接到当前进程的地址空间(shmat函数)

shmat 函数用于将共享内存段连接到当前进程的地址空间,以便进程可以访问共享内存中的数据。它的原型如下:

void *shmat(int shmid, const void *shmaddr, int shmflg);
  • shmid 是共享内存段的标识符,通常是由 shmget 函数返回的值。
  • shmaddr 是用来指定将共享内存连接到进程地址空间的地址,通常设为 NULL,表示由系统自动选择合适的地址。
  • shmflg 是用来指定连接行为的标志位。

shmat 函数的功能如下:

  1. 将指定标识符的共享内存段连接到当前进程的地址空间,并返回一个指向共享内存段起始地址的指针。
  2. 如果 shmaddr 参数设为 NULL,则系统会自动选择合适的地址将共享内存连接到当前进程的地址空间。
  3. shmflg 参数可以用来指定连接的行为,例如是否只读、读写权限等。

✅在调用 shmat 函数后,程序员可以通过返回的指针来访问共享内存中的数据

(5)访问共享内存

连接成功后,就可以通过返回的指针来访问共享内存中存储的数据了。

(6)分离共享内存(shmdt函数)

shmdt 函数用于将共享内存段从当前进程的地址空间分离,以释放资源并防止内存泄漏。它的原型如下:

int shmdt(const void *shmaddr);
  • shmaddr 是指向共享内存段起始地址的指针,需要与之前调用 shmat 函数时返回的指针相同。

shmdt 函数的功能如下:

  1. 将共享内存段从当前进程的地址空间分离。
  2. 分离后,当前进程将无法再访问共享内存段中的数据。

下面是 shmdt 函数的示例用法:

#include <sys/types.h>
#include <sys/shm.h>
#include <stdio.h>

int main() 
{
    void *ptr = ...; // 已知指向共享内存的指针
    int status = shmdt(ptr); // 将共享内存从当前进程的地址空间分离

    if (status == -1) 
    {
        perror("shmdt");
        return 1;
    }
    printf("Shared memory detached\n");
    return 0;
}

需要注意的是,分离共享内存后,当前进程将无法再通过指针 ptr 访问共享内存中的数据。为避免内存泄漏,使用完共享内存后应该及时调用 shmdt 函数分离共享内存。

2. 共享内存的使用示例

进程1:创建共享内存并写入数据

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

int main() {
    key_t key = ftok("shmfile", 'R'); // 通过 ftok 函数生成键值
    int size = 1024; // 共享内存段的大小
    int shmflg = IPC_CREAT | 0666; // 创建共享内存段的权限
    
    int shmid = shmget(key, size, shmflg); // 获取共享内存的标识符
    
    if (shmid == -1) {
        perror("shmget");
        return 1;
    }
    
    printf("Shared memory segment ID: %d\n", shmid);
    
    char *shmaddr = shmat(shmid, NULL, 0); // 将共享内存连接到当前进程的地址空间

    if (shmaddr == (char *)-1) {
        perror("shmat");
        return 1;
    }

    strcpy(shmaddr, "Hello, shared memory!"); // 向共享内存写入数据

    printf("Data written to shared memory: %s\n", shmaddr);

    shmdt(shmaddr); // 将共享内存从当前进程的地址空间分离
    
    return 0;
}

进程2:连接共享内存并读取数据

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>

int main() {
    key_t key = ftok("shmfile", 'R'); // 通过 ftok 函数生成键值
    int size = 1024; // 共享内存段的大小
    int shmflg = 0666; // 访问共享内存的权限

    int shmid = shmget(key, size, shmflg); // 获取共享内存的标识符

    if (shmid == -1) {
        perror("shmget");
        return 1;
    }

    char *shmaddr = shmat(shmid, NULL, 0); // 将共享内存连接到当前进程的地址空间

    if (shmaddr == (char *)-1) {
        perror("shmat");
        return 1;
    }

    printf("Data read from shared memory: %s\n", shmaddr); // 从共享内存读取数据

    shmdt(shmaddr); // 将共享内存从当前进程的地址空间分离
    
    // 在实际应用中,可能需要在完成读取数据后删除共享内存段,使用 shmctl 函数执行删除操作
    // shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

四、共享内存的优缺点

优点:

  1. 快速高效: 由于共享内存直接映射到进程的地址空间,进程可以直接读写共享内存中的数据,因此在性能上非常高效。

  2. 方便: 共享内存提供了一个简单的机制,允许多个进程共享相同的数据,而无需进行复制或传输。这样可以方便地实现进程间的数据共享。

  3. 灵活性: 共享内存可以用于任意类型的数据,包括结构化数据、对象等,因此非常灵活。

缺点:

  1. 同步问题: 由于多个进程可以同时访问共享内存,因此需要额外的同步机制来确保数据的一致性和完整性,比如信号量、互斥锁等

  2. 安全性: 共享内存的使用需要特别小心,因为在没有适当的同步和保护机制的情况下,可能会导致竞争条件和数据损坏。

  3. 复杂性: 在设计和实现中,共享内存可能会引入更多的复杂性,需要开发人员自行管理内存分配、释放、同步等问题,容易出现错误。

  4. 可移植性: 共享内存的实现可能受限于操作系统,因此在不同的平台上可能存在一定的可移植性问题。

温馨提示

感谢您对博主文章的关注与支持!如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于Linux以及C++编程技术问题的深入解析、应用案例和趣味玩法等。如果感兴趣的话可以关注博主的更新,不要错过任何精彩内容!

再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索Linux、C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
在这里插入图片描述

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

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

相关文章

LeetCode - 142. 环形链表 II (C语言,快慢指针,配图)

如果你对快慢指针&#xff0c;环形链表有疑问&#xff0c;可以参考下面这篇文章&#xff0c;了解什么是环形链表后&#xff0c;再做这道题会非常简单&#xff0c;也更容易理解下面的图片公式等。 LeetCode - 141. 环形链表 &#xff08;C语言&#xff0c;快慢指针&#xff0c;…

写作脑科学——屠龙的高效写作指南

ISBN: 978-7-115-59231-6 作者&#xff1a;杨滢&#xff08;屠龙的胭脂井&#xff09; 页数&#xff1a;201页 阅读时间&#xff1a;2023-09-09 推荐指数&#xff1a;★★★★★ 十分推荐这本书&#xff0c;写的非常简单易懂&#xff0c;里面有很多方法论和实用技巧&#xff0c…

使用Maxent模型预测适生区

Maxent模型因其在潜在适生区预测中稳健的表现&#xff0c;时下已经成为使用最广泛的物种分布模型。biomod虽然可以通过集成模型的优势来弥补数据量较小的劣势&#xff0c;但是其在使用和运算时间上的优势远不如Maxent&#xff0c;虽然最新的biomod2已经修复了一些bug&#xff0…

Power Apps-使用power Automate流

创建&#xff1a;Power Automate-创建power Apps使用的流-CSDN博客 打开Power Apps&#xff0c;创建页面&#xff0c;添加三个输入框&#xff08;分别是换算前单位、换算后单位、货币数&#xff09;&#xff0c;和一个文本框&#xff08;输出结果&#xff09;以及一个按钮 在…

微信聚合聊天,自动回复

微信&#xff0c;这款融合通讯、社交、娱乐、小程序于一体的平台&#xff0c;已经深深融入我们的日常生活。作为我们日常生活中不可或缺的社交工具&#xff0c;尤其在工作中&#xff0c;我们需要通过微信来沟通客户&#xff0c;这个时候我们就会希望有快速回复客户的方式秒回客…

自动备份pgsql数据库

bat文件中的内容&#xff1a; PATH D:\Program Files\PostgreSQL\13\bin;D:\Program Files\7-Zip set PGPASSWORD**** pg_dump -h 8.134.151.187 -p 5466 -U sky -d mip_db --schema-only -f D:\DB\backup\%TODAY%-schema-mip_db_ali.sql pg_dump -h 8.134.151.187 -p 5466…

从房地产先后跨界通信、文旅演艺领域,万通发展未来路在何方?

近年来&#xff0c;房地产市场可谓负重前行&#xff0c;各大房企纷纷谋求新出路。 作为中国最早的房企之一&#xff0c;万通发展再次处在转型变革的十字路口。自去年以来&#xff0c;万通发展在转型升级之路上动作频频&#xff0c;可谓忙得不亦乐乎。 大幕落下之时&#xff0c;…

【word密码】word设置只读方式的四个方法

想要将word文档设置为只读模式&#xff0c;方法有很多&#xff0c;今天小奥超人介绍几个方法给大家。 方法一&#xff1a;文件属性 常见的、简单的设置方法&#xff0c;不用打开word文件&#xff0c;只需要右键选择文件&#xff0c;打开文件属性&#xff0c;勾选上【只读】选…

使用c++程序,实现图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转

数字图像处理–实验三A图像的基本变换 实验内容 A实验&#xff1a; &#xff08;1&#xff09;使用VC设计程序&#xff1a;实现图像平移变换&#xff0c;图像缩放、图像裁剪、图像对角线镜像。 &#xff08;2&#xff09;使用VC设计程序&#xff1a;对一幅高度与宽度均相等的…

模拟业务流程+构造各种测试数据,一文带你测试效率提升80%

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

【Unity】文件信息的存储和解析(C#代码)

目录 文件存储 两种文件信息解析方法 文件加密处理 文件解密处理 全部代码 文件存储 一些游戏案例开发过程中的一些数据转换成Json格式&#xff0c;然后存到指定的位置 //3.将对象转化为JsonList<Hokag> hokagList new List<Hokag>(){new Hokag(){Name"…

【UE5】显示或隐藏物体轮廓线

效果 步骤 1. 先下载所需的材质文件“M_Highlight.uasset” 材质下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rxmRhkUoXVq6-DkIKyBhAQ 提取码&#xff1a;55bv 2. 在视口中拖入后期处理体积 根据需求设置后期处理体积的大小或者直接设置无限范围&…

Spring6(四):JUnit、事务

文章目录 5. 单元测试&#xff1a;JUnit5.1 整合JUnit55.2 整合JUnit4 6. 事务6.1 JdbcTemplate6.1.1 准备工作6.1.2 实现CURD①装配 JdbcTemplate②测试增删改功能③查询数据返回对象④查询数据返回list集合⑤查询返回单个的值 6.2 事务6.2.1 编程式事务6.2.2 声明式事务 6.3 …

性能测试 —— 性能问题分析步骤!

前言 性能测试大致分以下几个步骤&#xff1a; 需求分析脚本准备测试执行结果整理问题分析 今天要说的是最后一个步骤——“问题分析”&#xff1b; 需求描述 有一个服务&#xff0c;启动时会加载一个1G的词表文件到内存&#xff0c;请求来了之后&#xff0c;会把请求词去词…

ajax异步传值以及后端接收参数的几种方式

异步传值 第一种呢&#xff0c;也是最简单的一种&#xff0c;通过get提交方式&#xff0c;将参数在链接中以问号的形式进行传递 // 前台传值方法 // 触发该方法调用ajaxfunction testAjax(yourData) {$.ajax({type: "get", // 以get方式发起请求url: "/yo…

童装CPC认证检测哪些内容?童装上架亚马逊美国站CPC认证办理

童装是指适合儿童穿着的服装。按年龄分&#xff0c;包括婴儿服装、儿童服装、童装、中年童装、大童服装。CPC认证即儿童产品证书&#xff08;CPC&#xff09;&#xff0c;主要针对12岁以下的儿童&#xff0c;如玩具、摇篮、童装等。跨境卖家作为“进口商”&#xff0c;想要将中…

AC修炼计划(AtCoder Regular Contest 162)

传送门&#xff1a;AtCoder Regular Contest 162 - AtCoder A题签到 B - Insertion Sort 2 我们可以从头开始一个一个排序&#xff0c;把1通过操作放到第一个&#xff0c;把2通过操作放到第二个。。。以此类推。但会出现一种情况&#xff0c;如果我们所要排的数字在最后一位&…

【解决方案】危化品厂区安防系统EasyCVR+AI智能监控

危化品属于危险、易燃易爆、易中毒行类&#xff0c;一旦在生产运输过程中发生泄漏后果不堪想象&#xff0c;所以危化品的生产储存更需要严密、精细的监控&#xff0c;来保障危化品的安全。EasyCVRTSINGSEE青犀AI智能分析网关搭建的危化品智能监控方案就能很好的为危化品监管保驾…

基于ssm流浪动物救助管理系统

基于ssm流浪动物救助管理系统 摘要 随着城市化的不断发展&#xff0c;流浪动物问题逐渐凸显&#xff0c;而对流浪动物的救助和管理成为社会关注的焦点。本文基于SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架&#xff0c;设计并实现了一套流浪动物救助管理系统。该系…

碾压Fast Request!IDEA插件推荐:Apipost-Helper

IDEA是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具&#xff0c;而今天给大家介绍一款IDEA插件&…