Linux下实现共享内存的两种机制(附源码)

 

START

 

Hello 大家好。

今天来讲一下Linux进程通信中重要的通信方式:共享内存作为Linux软件开发攻城狮,进程间通信是必须熟练掌握的重要技能,而共享内存是在程序开发中常用的也是重要的一种进程间通信方式。

下面我们就来聊一聊Linux下进程间如何实现共享内存通信,有哪些方式?

1、基本概念

UNIX Linux

UNIXLinux是两种不同的操作系统,它们的主要区别在以下几个方面:

历史:UNIX是最早的商业化操作系统之一,最初由贝尔实验室开发,而Linux则是由Linus Torvalds1991年开发的开源操作系统。

源代码:UNIX的源代码是私有的,需要购买授权才能使用和修改,而Linux是开源的,任何人都可以自由地访问、使用和修改其源代码。

可移植性:由于UNIX的代码是私有的,因此它们在不同的硬件平台之间的可移植性较差。而Linux的源代码是开放的,因此它可以在多种硬件平台上运行。

发行版:UNIX有多个商业和非商业版本,如SolarisAIXHP-UX等,每个版本都有自己的特点和功能。而Linux则有许多不同的发行版,如UbuntuDebianRed HatFedora等。

命令行工具:UNIXLinux有许多相同的命令行工具和命令,如lsgrepawk等,但也有一些不同之处。

总的来说,UNIXLinux都是基于UNIX哲学的操作系统,但它们在源代码、可移植性、发行版和命令行工具等方面有所不同。

System V POSIX

System VPOSIX是两种不同的操作系统标准,它们的区别在以下几个方面:

历史背景:System V最初是由AT&T开发的UNIX版本,而POSIXIEEE为了保证不同UNIX系统的兼容性而开发的标准。

体系结构:System V是一种具体的操作系统,而POSIX则是一种操作系统接口标准。因此,System V具有更多的操作系统特定功能,而POSIX的接口更为通用,适用于多种不同类型的UNIX系统。

文件系统:System VPOSIX的文件系统不同。System V使用名为“inode”的数据结构来描述文件和目录,而POSIX则使用名为文件描述符的整数来表示打开的文件。

ShellSystem VPOSIXShell也不同。System VShellBourne Shell,而POSIXShellBourne-Again Shellbash)。

网络支持:System VPOSIX的网络支持也不同。System V使用TCP/IP协议栈,而POSIX使用套接字(socket)接口。

2System V IPC POSIX IPC

System V IPCInterprocess Communication)和POSIX IPC都是用于在不同进程间进行通信的机制,但它们之间有几个区别:

编程接口:System V IPCPOSIX IPC的编程接口不同。System V IPC使用IPC对象(如信号量、共享内存和消息队列)来实现进程间通信,而POSIX IPC使用命名对象(如命名信号量、命名共享内存和命名管道)。

可移植性:POSIX IPC是由IEEE POSIX标准定义的,因此POSIX IPC是可移植的,可在不同的操作系统上使用。而System V IPC是由System V操作系统提供的,因此不同的操作系统可能实现不同,因此在跨平台时可能会有问题。

接口和实现:System V IPC的接口和实现是紧密耦合的,而POSIX IPC的接口和实现是松散耦合的。这意味着在POSIX IPC中,接口和实现是独立的,因此可以在实现中进行更改,而不影响接口,这使得在不同的系统上实现相同的接口变得更容易。

特性:System V IPC提供的特性比POSIX IPC多,例如,System V IPC提供了消息队列,而POSIX IPC则没有。另一方面,POSIX IPC提供了诸如命名管道之类的特性,而System V IPC则没有。

综上所述,System V IPCPOSIX IPC都有其优点和缺点。在选择使用哪种IPC机制时,需要根据具体应用场景和需求进行权衡。

3、共享内存实现方式

Linux下,共享内存可以使用System V IPC机制或POSIX IPC机制实现。

使用System V IPC机制:

使用shmget()函数创建共享内存区域并获取其标识符。使用shmat()函数将共享内存区域附加到进程地址空间中。使用shmdt()函数将共享内存区域从进程地址空间中分离。使用shmctl()函数控制共享内存区域的属性和状态。

使用POSIX IPC机制:

使用shm_open()函数创建共享内存区域并获取其文件描述符。使用ftruncate()函数调整共享内存区域的大小。使用mmap()函数将共享内存区域映射到进程地址空间中。使用munmap()函数解除共享内存区域与进程地址空间的映射关系。使用shm_unlink()函数删除共享内存区域的文件名并释放资源。

System V IPC机制实现共享内存

以下是一个使用System V IPC机制实现共享内存的简单例程,它展示了如何创建、附加和分离共享内存区域。

#include <stdio.h>

#include <stdlib.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <string.h>



#define SHM_SIZE 1024 // 共享内存大小



int main() {

    int shmid;

    char *shmaddr;

    char s8ReadBuf[1024] = {0};

    key_t key = ftok(".", 's'); // 获取共享内存标识符



    if (key == -1) {

        perror("ftok");

        exit(1);

    }



    // 创建共享内存区域

    shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);

    if (shmid == -1) {

        perror("shmget");

        exit(1);

    }



    // 将共享内存区域附加到进程地址空间中

    shmaddr = shmat(shmid, NULL, 0);

    if (shmaddr == (char *) -1) {

        perror("shmat");

        exit(1);

    }



#if 1

    // 在共享内存中写入数据

    strncpy(shmaddr, "Hello, world!", SHM_SIZE);

#else

    // 读数据

    // memcpy(s8ReadBuf, shmaddr, 1024);

    // printf("s8ReadBuf:%s\n", s8ReadBuf);

#endif



    // 分离共享内存区域

    if (shmdt(shmaddr) == -1) {

        perror("shmdt");

        exit(1);

    }



    return 0;

}

在上面的例程中,我们首先使用ftok()函数生成一个key值作为共享内存的标识符。然后使用shmget()函数创建共享内存区域,shmaddr指向共享内存区域的起始地址。最后使用shmdt()函数分离共享内存区域。

POSIX IPC机制实现共享内存

以下是一个使用POSIX IPC机制实现共享内存的简单例程,它展示了如何创建、映射和解除映射共享内存区域。

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <unistd.h>

#include <string.h>



#define SHM_SIZE 1024 // 共享内存大小

#define SHM_NAME "/myshm" // 共享内存名称



int main() {

    int fd;

    char *shmaddr;

    char s8ReadBuf[1024] = {0};

    const char *msg = "Hello, world!";



    // 创建共享内存区域

    fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);

    if (fd == -1) {

        perror("shm_open");

        exit(1);

    }



    // 调整共享内存区域的大小

    if (ftruncate(fd, SHM_SIZE) == -1) {

        perror("ftruncate");

        exit(1);

    }



    // 映射共享内存区域到进程地址空间中

    shmaddr = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (shmaddr == MAP_FAILED) {

        perror("mmap");

        exit(1);

    }



#if 1

    // 在共享内存中写入数据

    strncpy(shmaddr, msg, SHM_SIZE);

#else

    // 读数据

    // memcpy(s8ReadBuf, shmaddr, 1024);

    // printf("s8ReadBuf:%s\n", s8ReadBuf);

#endif

    // 解除共享内存区域与进程地址空间的映射关系

    if (munmap(shmaddr, SHM_SIZE) == -1) {

        perror("munmap");

        exit(1);

    }



    // 删除共享内存区域的文件名并释放资源

    if (shm_unlink(SHM_NAME) == -1) {

        perror("shm_unlink");

        exit(1);

    }



    return 0;

}

在上面的例程中,我们使用shm_open()函数创建一个共享内存区域,然后使用ftruncate()函数调整共享内存区域的大小。接着,我们使用mmap()函数将共享内存区域映射到进程地址空间中,并使用strncpy()函数在共享内存中写入数据。最后,我们使用munmap()函数解除共享内存区域与进程地址空间的映射关系,并使用shm_unlink()函数删除共享内存区域的文件名并释放资源。

小结

通过上面的示例希望对小伙伴们在共享内存通信编程中有所帮助,学会如何使用共享内存通信,并灵活运用于日常的编程中。共享内存方式的通信必须熟练掌握与应用。

END

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytest自动化框架之allure测试报告的用例描述设置

allure测试报告的用例描述相关方法&#xff1b;如下图 allure标记用例级别severity 在做自动化测试的过程中&#xff0c;测试用例越来越多的时候&#xff0c;如果执行一轮测试发现了几个测试不通过&#xff0c;我们也希望能快速统计出缺陷的等级。 pytest结合allure框架可以对…

每日学术速递4.26

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.AutoNeRF: Training Implicit Scene Representations with Autonomous Agents 标题&#xff1a;AutoNeRF&#xff1a;使用自主代理训练隐式场景表示 作者&#xff1a;Pierre Marz…

SaaS云HIS系统源码功能介绍

SaaS云HIS首页功能&#xff1a;包括工作计划、预警、主功能菜单、医院机构公告。 一、工作计划 1.值班概况&#xff1a;值班日期、值班时间、值班科室&#xff08;内科、外科等&#xff09; 2.待处理患者&#xff1a;内科人数、外科人数等 病历统计&#xff1a;入院病历、出…

华为面试题:1+4=5,2+5=12,3+6=21,问8+11=?网友:幼儿园级别

面试&#xff0c;一直都是职场人士绕不过去的坎&#xff0c;对于有的人来说&#xff0c;或许更擅长日常的工作&#xff0c;在面试环节可谓是自己的薄弱环节&#xff0c;但对于有的人来说&#xff0c;相比于工作&#xff0c;更擅长应付面试&#xff01; 最近&#xff0c;有一位…

《面向基于人工智能的学习健康系统,使用心电图进行人群水平的死亡率预测》阅读笔记

目录 一、摘要 二、十个问题 Q1论文试图解决什么问题&#xff1f; Q2这是否是一个新的问题&#xff1f; Q3这篇文章要验证一个什么科学假设&#xff1f; Q4有哪些相关研究&#xff1f;如何归类&#xff1f;谁是这一课题在领域内值得关注的研究员&#xff1f; Q5论文中提到…

过来人转本考试后的感悟和经验,真的很受用

过来人转本考试后的感悟和经验&#xff0c;真的很受用&#xff01;转本不仅是分数的较量&#xff0c;也是信息收集、时间管理、学习能力、毅力等等的较量。同学们在转本中难免会遇见一些困难&#xff0c;为了避免走弯路&#xff0c;一起来看看过来人的感悟和经验吧&#xff01;…

项目范围控制:如何控制项目范围的变化?

一个成功的项目需要在进度、成本和质量之间取得平衡。控制项目交付范围是实现这个平衡的关键。然而&#xff0c;项目范围是会变化的&#xff0c;因此控制项目范围变化是必要的。 如何控制项目范围的变化&#xff1f; 1、了解项目的交付范围 项目经理、团队成员、利益相关者和…

verilog手撕代码3——序列检测和序列发生器

文章目录 前言一、序列检测器1.1 重复序列检测1.1.1 序列缓存对比/移位寄存器法1.1.2 状态机法 1.2 非重复序列检测 二、序列发生器2.1 移位寄存器法2.2 反馈法2.3 计数器法 前言 2023.4.25 2023.4.26 学习打卡&#xff0c;天气转晴 一、序列检测器 1.1 重复序列检测 1.1.1 …

等级保护、风险评估和安全测评分别是什么?

2022-06-17 15:17 迈入“等保2.0时代”以后&#xff0c;我国对于等级保护的要求更为严格和具体。等级保护、风险评估和安全测评这三个词&#xff0c;也因此总是出现在人们的视野之中&#xff0c;还总是被混淆。那这三者究竟分别是什么呢&#xff1f;如何区分它们&#xff1f;它…

【Bus】编写一个Demo虚拟的总线-设备-驱动模型

文章目录 1. 前言2. 总线驱动模型三要素2.1 总线2.2 设备2.3 驱动 3. Demo Code3.1 virt_bus_core.c3.2 virt_device.c3.3 virt_driver.c 4. 工程代码下载地址5. 参考资料 1. 前言 Linux平台为了驱动的可重用性&#xff0c;虚拟了很多的虚拟总线。很经典的就是platform总线&am…

如何编写高质量代码、提高编程效率?

一、 前言 高质量代码是指在满足功能需求的基础上&#xff0c;具备高性能、安全、可扩展、易维护、可测试等特点的代码。它不仅可以提高开发效率和代码质量&#xff0c;更能有效减少代码维护成本&#xff0c;促进团队协作和项目成功。因此&#xff0c;编写高质量代码对程序员来…

【Java】什么是SOA架构?与微服务有什么关系?

文章目录 服务化架构微服务架构 我的一个微服务项目&#xff0c;有兴趣可以一起做 服务化架构 我们知道&#xff0c;早期的项目&#xff0c;我们都是把前后端的代码放在同一个项目中&#xff0c;然后直接打包运行这个项目&#xff0c;这种项目我们称之为单体项目&#xff0c;比…

【Vue】Vue-cli,创建项目设置自定义默认配置

Vue2.0&#xff0c;Vue-cli项目配置 步骤一&#xff0c;打开文件夹&#xff0c;导航栏输入cmd&#xff0c;打开命令行窗口步骤二&#xff0c;输入命令步骤三&#xff0c;选择第三个自定义新建项目步骤四&#xff0c;选择需要的项目模块&#xff0c;空格选择完&#xff0c;回车步…

密码学|AES加密算法|学习记录

AES简介 AES加密是分组加密的一种 明文长度为固定的128位 密钥可长度为128&#xff0c;192&#xff0c;256位 128bit16字节&#xff0c;在AES中我们将数据用4x4字节的矩阵表示。&#xff08;注排列顺序为先从上到下再从左到右&#xff09; AES的一般步骤 对于上图最终轮区…

CASAIM高精度自动化三维扫描系统检测塑料件,自动检测形位公差

随着塑料工业的迅速发展&#xff0c;以及塑料制品在航空、航天、电子、机械、船舶和汽车等工业部门的推广应用&#xff0c;对塑料件的质量要求也越来越高。 为了检测塑料件的尺寸偏差以及测量关键部位的3D尺寸和形位公差&#xff0c;对影响总成零件精度的产品、工装、工艺进行精…

第十章_Redis集群(cluster)

是什么 定义 由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序集。 官…

yield用法理解,配有代码块和解析

包含 yield 关键字的函数&#xff0c;是一个生成器 yield和return的区别 1、return是返回return关键字的值&#xff0c;被调用一次就返回一次&#xff0c;return只能放在一个函数代码块的最后面&#xff0c;运行到return的时候&#xff0c;就结束循环&#xff0c;结束这个函数…

用户画像系列——HBase 在画像标签过期策略中的应用

一、背景 前面系列文章介绍了用户画像的概念、用户画像的标签加工、用户画像的应用。本篇文章主要介绍一些画像的技术细节&#xff0c;让大家更加详细的了解画像数据存储和处理的逻辑 举个现实中的例子&#xff1a; 例子1&#xff1a;因为疫情原因&#xff0c;上线一个平台(…

没有U盘电脑如何使用本地硬盘安装Ubuntu20.04(双系统)

环境: DELL7080台式机 Ubuntu20.04 两块硬盘 问题描述: 没有U盘电脑如何使用本地硬盘安装Ubuntu20.04(双系统) 解决方案: 一、下载镜像文件 1.上线自行下载安装镜像文件 二、分区 1.win10下磁盘管理压缩2个分区一个10G左右制作安装盘,一个几百G安装系统使用 10…