Linux下进程间的通信--共享内存

共享内存概述:

共享内存是进程间通信的一种方式,它允许两个或多个进程共享一个给定的存储区。共享内存是最快的一种IPC形式,因为它允许进程直接对内存进行读写操作,而不需要数据在进程之间复制。

共享内存是进程间通信(IPC)中效率非常高的一种方式,因为它允许多个进程直接访问同一块内存区域,从而避免了数据在进程间复制的开销。这种直接访问内存的方式减少了数据传输的时间,提高了通信效率。

 在 Linux 系统中通过 ipcs -m 查看所有的共享内存

1.创建共享内存:

shmget() 是一个在 Linux 系统上用于创建或获取共享内存段的系统调用

shmget()函数描述:

函数头文件:
#include <sys/ipc.h>
#include <sys/shm.h>

函数原型:
int shmget(key_t key, size_t size, int shmflg);

函数参数:
key_t key: 这是一个键值,用于标识共享内存段。如果key是IPC_PRIVATE,则创建一个新的共享内存段,并且不与其他任何共享内存段关联。
size_t size: 这是共享内存段的大小,以字节为单位。这个大小必须是一个系统页的整数倍。
int shmflg: 这是一组标志位,用于控制共享内存段的权限和控制选项。
常见的标志位包括:
IPC_CREAT: 如果指定了这个标志,并且key指定的共享内存段不存在,则创建一个新的共享内存段。
IPC_EXCL: 与IPC_CREAT一起使用,如果共享内存段已经存在,则shmget()调用失败。
0666 (八进制): 这是权限掩码,用于设置共享内存段的权限。默认情况下,所有用户都可以读写共享内存段。

函数返回值:
成功:返回一个有效的共享内存标识符
失败:返回-1,并设置errno来指示错误
错误原因:
EACCES: 没有权限访问共享内存段。
EEXIST: IPC_CREAT | IPC_EXCL 被设置,但共享内存段已经存在。
EINVAL: size不是系统页大小的整数倍,或者key是无效的。
ENOMEM: 系统内存不足,无法创建新的共享内存段

 扩充知识--系统页大小:

在Linux系统中,"系统页面大小"(也称为"页大小"或"分页大小")是指操作系统用于管理内存的分配单元的大小。这个大小是虚拟内存系统中页表条目的大小,也是内存管理单元(MMU)分页机制的基础。

系统页面大小通常是4KB(即4096字节),但这个值可能会根据不同的体系结构和操作系统的实现而有所不同。例如,在某些64位体系结构上,页面大小可能是8KB或更大。这个大小对于性能优化很重要,因为它决定了内存映射和页表条目的效率。

 示例代码:

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

int main() {
    size_t size = 1024; // 分配1024字节
    int shmflg = 0666 | IPC_CREAT; // 设置权限并创建共享内存

    int shmid = shmget(IPC_PRIVATE, size, shmflg);
    if (shmid == -1) {
        fprintf(stderr, "shmget failed: %s\n", strerror(errno));
        return 1;
    }

    printf("Shared memory ID: %d\n", shmid);
    return 0;
}

 2.附加共享内存:

 shmat() 是一个在 Linux 系统中用于将共享内存段附加到调用进程的地址空间的系统调用。这个函数是共享内存 IPC 机制的一部分,它允许进程访问由 shmget() 创建的共享内存段

shmat()函数描述:

函数头文件:
#include <sys/types.h>
#include <sys/shm.h>

函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);

函数参数:
int shmid: 这是由shmget()函数返回的共享内存段的标识符。
const void *shmaddr: 这是一个可选的指针,指定共享内存段应该被附加到进程地址空间的哪个位置。
如果设置为NULL,系统会自动选择一个合适的地址。

int shmflg: 这是一个标志位,用于控制共享内存的附加行为。
可能的标志包括:
SHM_RDONLY: 将共享内存附加为只读。
SHM_RND: 将共享内存附加到一个页面边界地址,这可以提高内存访问的效率。

函数返回值:
成功:返回附加的共享内存段的地址
失败:返回(void *) -1,并设置errno以指示错误的原因。
错误原因
EACCES  调用进程没有请求的附加类型所需的权限,
并且在管理IPC命名空间的用户命名空间中没有CAP_IPC_OWNER功能。

EIDRM   shmid指向一个已删除的标识符。

EINVAL  无效的shmid值,未对齐(即未对齐页面且未指定SHM_RND)或无效的shmaddr值,
或者不能在shmaddr上附加段,或者指定了SHM_REMAP而shmaddr被指定NULL。

ENOMEM   无法为描述符或页表分配内存。

 示例代码:

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

int main() {
    int shmid;             // 共享内存标识符
    char *shared_memory;   // 共享内存的指针

    // 创建一个共享内存段
    shmid = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(1);
    }

    将共享内存附加到其地址空间
    shared_memory = (char *)shmat(shmid, NULL, 0);
    if (shared_memory == (char *)(-1)) {
        perror("shmat");
        exit(1);
    }

    // 写入一些数据到共享内存
    strcpy(shared_memory, "Hello, World!");
   
    return 0;
}

 3.分离共享内存:

当进程不再需要访问共享内存时,可以使用 shmdt 系统调用将其从进程的地址空间中分离

 shmdt()函数描述: 

函数头文件:
#include <sys/types.h>
#include <sys/shm.h>

函数原型:
int shmdt(const void *shmaddr);

函数参数:
shmaddr: 这是之前通过shmat()函数附加的共享内存段的地址。

函数返回值
成功:返回0。
失败:返回-1,并设置errno以指示错误。
错误原因:
EINVAL: 在shmaddr上没有附加共享内存段;或者shmaddr没有在页边界上对齐

4.读写共享内存:

一旦共享内存段被附加到进程的地址空间,进程就可以通过指针直接访问和操作共享内存中的数据。这使得共享内存成为进程间通信(IPC)中非常快速和高效的一种方式。

一旦共享内存段被附加,进程就可以通过指针 shmaddr 读写共享内存。这部分内存就像普通的内存一样使用

示例代码:

void* addr = shmat(shmid,NULL,0);
if(addr == (void*)-1)
{
    perror("shmat");
    exit(EXIT_FAILURE);
}
char buf[1024]={0};
memcpy(buf,addr,10);
printf("share memory content:%s\n",buf);
shmdt(addr); //分离共享内存

5.控制共享内存:

在Linux中,共享内存的控制通常通过 shmctl 系统调用来实现。shmctl 函数可以对共享内存段进行多种操作,包括获取共享内存的状态、设置共享内存的状态以及删除共享内存段

shmctl()函数描述:

函数头文件:
#include <sys/ipc.h>
#include <sys/shm.h>

函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);:

函数参数:
shmid:共享内存段的标识符,这个标识符是通过shmget()函数创建共享内存段时返回的。
cmd:指定要执行的控制操作。
它可以是以下命令之一:
IPC_STAT:获取共享内存段的状态信息,buf指向的结构会被填充。
IPC_SET:设置共享内存段的属性,buf指向的结构包含了要设置的值。
IPC_RMID:删除共享内存段,只有拥有适当权限的用户(通常是创建者或超级用户)可以执行此操作。
SHM_LOCK:锁定共享内存段,防止其被交换出物理内存。
SHM_UNLOCK:解锁共享内存段,允许其被交换。
IPC_INFO:获取系统范围内共享内存的信息(Linux 特定)。
SHM_INFO:获取系统范围内共享内存的详细信息(Linux 特定)。
SHM_STAT_ANY:获取任何用户的共享内存段的状态信息(Linux 特定,自 Linux 4.17 起支持)。

buf:指向shmid_ds结构的指针,该结构用于存储共享内存段的信息或新属性
函数返回值:
成功:0
失败:-1,并设置errno以指示错误原因

 shmid_ds结构体:

示例代码:

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

int main() {
    int shmid;
    struct shmid_ds shminfo;

    shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);

    // 获取共享内存段的信息
    if (shmctl(shmid, IPC_STAT, &shminfo) == -1) {
        perror("shmctl IPC_STAT");
        return 1;
    }

    printf("Size: %ld\n", (long)shminfo.shm_segsz);
    printf("Last attached: %ld\n", (long)shminfo.shm_nattch);

    // 删除共享内存段
    if (shmctl(shmid, IPC_RMID, &shminfo) == -1) {
        perror("shmctl IPC_RMID");
        exit(EXIT_FAILURE);
    }

    return 0;
}

 结语:

无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力

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

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

相关文章

MySQL基础篇(黑马程序员2022-01-18)

1 MySQL数据库概述 1.1 MySQL数据库的下载,安装,启动停止 1.2 数据模型 (1)关系型数据库(RDBMS) 概念&#xff1a;建立在关系模型基础上&#xff0c;由多张相互连接的二维表组成的数据库。 特点&#xff1a; A. 使用表存储数据&#xff0c;格式统一&#xff0c;便于维护。…

【JavaScript】数据结构之树

什么是树形结构&#xff1f; 一种分层数据的抽象模型&#xff0c;用来分层级关系的。虚拟dom它所组织的那个数据原理就是树形结构 深度优先搜索&#xff08;遍历&#xff09;- 递归 从根出发&#xff0c;尽可能深的搜索树的节点技巧 访问根节点对根节点的children挨个进行深…

基于python+django+vue的社区爱心养老管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的社…

mysql的zip解压缩版安装

文章目录 一、MySQL下载二、mysql解压缩版安装1、解压缩2、设置环境变量3、mysql初始化4、安装mysql服务5、启动mysql服务6、连接mysql7、修改初始密码8、安装完成 一、MySQL下载 下载网址&#xff1a;MySQL下载 本文以mysql8.4.2版本为例下载解压缩版。 二、mysql解压缩版安…

ElementUI 快速入门:使用 Vue 脚手架搭建项目

文章目录 一 . ElementUI 的基本安装1.1 通过 Vue 脚手架创建项目1.2 在 vue 脚手架中安装 ElementUI1.3 编写页面 ElementUI 是 Vue.js 的强大 UI 框架&#xff0c;让前端界面开发变得简单高效。本教程将带你从安装到实战&#xff0c;快速掌握 ElementUI 的核心技巧。 核心内容…

MS SQL Server 实战 排查多列之间的值是否重复

目录 需求 范例运行环境 数据样本设计 功能实现 上传EXCEL文件到数据库 SQL语句 小结 需求 在日常的应用中&#xff0c;排查列重复记录是经常遇到的一个问题&#xff0c;但某些需求下&#xff0c;需要我们排查一组列之间是否有重复值的情况。比如我们有一组题库数据&…

【初阶数据结构】排序

目录 一、排序的概念及其运用 1.1排序的概念 1.2常见的排序算法 二、常见排序算法的实现 2 .1插入排序 2 .1.1基本思想&#xff1a; 2.1.2直接插入排序&#xff1a; 算法复杂度&#xff1a; 最坏情况&#xff1a; 最好的情况&#xff1a; 直接插入排序的特性总结&…

React js Router 路由 2, (把写过的几个 app 组合起来)

完整的项目&#xff0c;我已经上传了&#xff0c;资源链接. 起因&#xff0c; 目的: 每次都是新建一个 react 项目&#xff0c;有点繁琐。 刚刚学了路由&#xff0c;不如写一个 大一点的 app &#xff0c;把前面写过的几个 app, 都包含进去。 这部分感觉就像是&#xff0c; …

BSV区块链上的覆盖网络服务现已开放公测

​​发表时间&#xff1a;2024年8月30日 BSV区块链的覆盖网络服务现已正式开放公测。对于BSV区块链生态系统内的特定交易类型和数据管理及访问&#xff0c;覆盖网络服务都可以为它们提供强大、可扩展、并且合规的解决方案。覆盖网络以及其它即将推出的BSV服务将赋予开发者、企业…

SQL Server开启网络访问

目前工作中很少用到SQL Server了&#xff0c;最近需要测试几个表&#xff0c;需要搭建一个SQL Server数据库服务&#xff0c;这里做个总结吧。 安装这里就不做详细介绍了&#xff0c;本文只介绍如何开启SQL Server网络访问。 1、云服务器安全组设置 如果是搭建在云服务器上&a…

CTF——简单的《MICS》

文章目录 一、MICS1、MISC-LSB2、MISC-循环解压3、MISC-一个不同的压缩包4、MISC-异性相吸5、MISC-仔细找找6、MISC-再来一题隐写7、MISC-找找吧8、MISC-这是一张单纯的图片9、MISC-真假flag10、MISC-真正的黑客才可以看到本质11、MISC-追象者12、MICS-鸡蛋别放在一起 一、MICS…

【双方演化博弈】研究理论学习

1. 演化基础 1.1.演化博弈常用软件 载学习软件: Matlab、Vensim PLE、 Visio 其中,Matlab和Vensim PLE主要是用做演化博弈仿真,Matlab是演化博弈最常用的仿真软件&#xff0c;VensimPLE是系统动力学(SD)仿真软件也是常用仿真软件之一。 Python、Netlogo等软件也可以用来做演…

THREE.js:网页上的3D世界构建者

THREE.js&#xff1a;网页上的3D世界构建者 前言 THREE.js 是一个强大的基于 JavaScript 的库&#xff0c;它使得在网页上创建和展示三维图形变得异常简单。 通过封装复杂的 WebGL 技术&#xff0c;THREE.js 提供了一套丰富的 API&#xff0c;让开发者能够轻松地构建出令人印…

基于web的 BBS论坛管理系统设计与实现

博主介绍&#xff1a;专注于Java .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的可以…

MYSQL基础-多表操作-事务-索引

1. 多表设计 概述 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a; …

网络编程基础概述

文章目录 协议网络协议栈(osi)局域网IPIP和Mac地址端口号TCP和UDP网络字节序 协议 (网络协议的)意义:为了让计算机传输之间将信息正确传输给目标机器 不同系统之间能接入网络是因为定制了一套通用的协议以便支持不同系统间的网络通信 1.网络通信的问题: 将数据可靠的从A传给B a…

Cesium 计算3d凸包(ConvexHull)

Cesium 计算3d凸包(ConvexHull) Cesium 计算3d凸包(ConvexHull)

【Android 13源码分析】WindowContainer窗口层级-2-构建流程

在安卓源码的设计中&#xff0c;将将屏幕分为了37层&#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析&#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…

InputDispatcher的调试日志isLoggable动态开放logcat实战使用

背景&#xff1a; 在学习input专题课程后&#xff0c;那么就可以正常对所有和input相关的问题进行分析&#xff0c;经常分析的类就是InputDispatcher&#xff0c;平时如果看正常的logcat输出&#xff0c;发现InputDispatcher相关的日志非常少&#xff0c;基本上没办法进行有价…

用Python打造互动式中秋节庆祝小程序

中秋节&#xff0c;这个充满传统韵味的节日&#xff0c;不仅是家人团聚的时刻&#xff0c;也是程序员展示创意的好机会。本文将引导您使用Python创建一个互动式中秋节庆祝小程序&#xff0c;它不仅能够展示节日祝福&#xff0c;还能通过一些简单的特效增加节日气氛。 文章目录 …