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

news2024/11/22 17:18:26

共享内存概述:

共享内存是进程间通信的一种方式,它允许两个或多个进程共享一个给定的存储区。共享内存是最快的一种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.coloradmin.cn/o/2140169.html

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

相关文章

【C++】【网络】【Linux系统编程】单例模式,加锁封装TCP/IP协议套接字

目录 引言 获取套接字 绑定套接字 表明允许监听 单例模式设计 完整代码示例 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 引言 有关套接字编程的细节和更多的系统调用课参考《UNIX环境高级编程》一书&#xff0c;可以在如下网站搜索电子版&#xff0c;该书在第16章详…

【C++】缺省(默认)参数

&#x1f984;个人主页:小米里的大麦-CSDN博客 &#x1f38f;所属专栏:C_小米里的大麦的博客-CSDN博客 &#x1f381;代码托管:C: 探索C编程精髓&#xff0c;打造高效代码仓库 (gitee.com) ⚙️操作环境:Visual Studio 2022 目录 一、概念 二、 全缺省&#xff08;Fully Defa…

多态的相关知识

一.多态的概念 1.多态&#xff1a;多态是⼀个继承关系的下的类对象&#xff0c;去调⽤同⼀函数&#xff0c;产⽣了不同的⾏为。 2.多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 1>编译时多态(静态多态)主要就是函数重载和函数模板&#xff0c;他们传不同类型的…

Powerpaint介绍及实现局部重绘效果测试[comfyui]

&#x1f358;背景 powerpaint&#xff0c;是一个高质量多功能的图像修补模型&#xff0c;可以同时支持插入物体、移除物体、图像扩展、形状可控的物体生成。 这个模型也是国产的&#xff0c;原作者是清华大学深圳国际研究生院&#xff0c;清华大学 &#xff0c;上海人工智能…

JAVA:非对称加密技术的详细指南

请关注微信公众号&#xff1a;拾荒的小海螺 博客地址&#xff1a;http://lsk-ww.cn/ 1、简述 非对称加密是一种加密技术&#xff0c;使用一对密钥进行数据加密和解密。这两个密钥分别是公开密钥&#xff08;public key&#xff09;和私有密钥&#xff08;private key&#xf…

【算法】栈与模拟

【ps】本篇有 5 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;删除字符串中的所有相邻重复项 .1- 题目解析 .2- 代码编写 2&#xff09;比较含退格的字符串 .1- 题目解析 .2- 代码编写 3&#xff09;基本计算器 II .1- 题目解析 .2- 代码编写 4&…

进程状态、进程创建和进程分类

文章目录 进程进程常见的状态进程调度进程状态变化关系 进程标识示例--进程标识的使用以及简介 进程创建fork函数vfork函数示例--使用fork函数创建子进程&#xff0c;并了解进程之间的关系 创建进程时发生的变化虚拟内存空间的变化示例--验证fork函数创建进程时的操作 对文件IO…

【例题】lanqiao3226 宝藏排序Ⅱ

样例输入 5 1 5 9 3 7样例输出 1 3 5 7 9解题思路 这里的n≤10^5&#xff0c;说明O(n ^2)的算法行不通。 基于比较的高效算法和基于数值划分的高效算法全部参考这篇文章 代码 最简单的自带排序 nint(input()) alist(map(int,input().split()))a.sort() print( .join(map…

量化交易backtrader实践(二)_基础加强篇(1)_数据列表准备与主要实践内容

上一篇回顾 上一篇是数据获取篇&#xff0c;在上一篇里&#xff0c;我们初步接触了backtrader的回测逻辑&#xff0c;重点放在了回测的数据获取的问题上&#xff0c;确保了我们在用合适且有效的正规数据在做回测&#xff0c;我们的目的是要通过backtrader深入讨论量化交易的内…

【Linux进程控制】进程等待

目录 进程等待 进程等待是什么&#xff1f; 为什么&#xff1f; 怎么办&#xff1f; wait方法 获取子进程status 多进程的等待问题 waitpid方法 什么是阻塞等待&#xff1f;什么是非阻塞等待&#xff1f; wait/waitpid获取子进程信息原理 进程等待 进程等待是什么&am…

【AI学习】陶哲轩在 2024 年第 65 届国际数学奥林匹克(IMO)的演讲:AI 与数学

陶哲轩在 2024 年第 65 届国际数学奥林匹克关于AI 和数学的演讲&#xff0c;很有意思。陶哲轩的讲话语速太快了&#xff0c;足见其聪明&#xff01; AI用于数学的一些方面&#xff1a; 陶哲轩介绍到刚刚被数学家接受并开始普及的方法&#xff1a;形式化证明辅助工具。 形式化…

API:连接数字世界的隐形纽带

在这个智能手机和应用程序无处不在的时代&#xff0c;你可能听说过API这个术语&#xff0c;但你知道它究竟是什么吗&#xff1f;API&#xff0c;全称为应用程序编程接口&#xff08;Application Programming Interface&#xff09;&#xff0c;是一种让不同的软件和服务之间能够…

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

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

C++11第五弹:线程库 | 互斥锁 | 原子操作

&#x1f308;个人主页&#xff1a; 南桥几晴秋 &#x1f308;C专栏&#xff1a; 南桥谈C &#x1f308;C语言专栏&#xff1a; C语言学习系列 &#x1f308;Linux学习专栏&#xff1a; 南桥谈Linux &#x1f308;数据结构学习专栏&#xff1a; 数据结构杂谈 &#x1f308;数据…

蓝牙耳机是入耳式的好还是开放式的好?2024开放式耳机推荐

个人推荐入开放式耳机&#xff0c;戴起来更舒服&#xff0c;主要有以下几方面原因&#xff1a; 减少对耳部的压迫&#xff1a; 不入耳设计&#xff1a;开放式耳机通常不需要插入耳道&#xff0c;避免了对耳道的直接压迫。入耳式耳机的耳塞长时间塞在耳道内&#xff0c;会对耳…

Linux基础---07文件传输

Linux文件传输地图如下&#xff0c;先选取你所需的场景&#xff0c;若你是需要Linux和Linux之间传输文件就查看SCP工具即可。 一.下载网站文件 前提是有网&#xff1a; 检查网络是否畅通命令&#xff1a;ping www.baidu.com&#xff0c;若有持续的返回值就说明网络畅通。Ctr…

前端基础知识(HTML+CSS+JavaScript)

文章目录 一、HTML1.1 HTML 基础&#xff1a;1.1.1 HTML 的概念&#xff1a;1.1.2 认识 HTML 标签&#xff1a;1.1.3 HTML 文件基本结构&#xff1a;1.1.4 标签层次结构&#xff1a; 1.2 HTML 快速入门&#xff1a;1.3 HTML常见标签&#xff1a;1.3.1 标题标签&#xff1a;h1-h…

数据结构-2.顺序表

1.线性表 线性是n个具有相同特性的数据元素的有限序列. 线性表是一种在实际中广泛使用的数据结构,常见的线性表有: 顺序表 , 链表 , 栈 , 队列... 线性表在逻辑上是线性结构, 也就是连续的一条直线 . 但是在物理结构上并不是连续的, 线性表在物理上存储时, 通常以数组和链式结…

5-----RYZ维修工具 操作界面预览与功能操作解析 刷机 解锁 修复参数等等

以上是工具选项功能的界面预览 。通过预览可以看到很多功能选项。此类工具涵盖了很多操作区域。需要根据自己机型的实际需求来操作。根据开发者的描述。此工具有一下功能。包含mtk刷机 分区修复。9008刷机 备份基带efs等等。 高通操作区域 高通修复串码 高通修改写入基带qc…