【Linux】System V 共享内存、消息队列、信号量

🍎作者:阿润菜菜
📖专栏:Linux系统编程


system V共享内存介绍

  1. System V 共享内存是一种进程间通信的机制,它允许多个进程共享一块物理内存区域(称为“段”)。System V 共享内存的优点是效率高,因为进程之间不需要复制数据;缺点是需要进程之间进行同步,以避免数据的不一致性
  2. 共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到
    内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

示意图:
在这里插入图片描述

深入理解

1.实现进程间通信的第一个前提就是如何让不同的进程看到同一份资源,匿名管道我们是通过子进程继承父进程打开的资源,命名管道是通过两个进程都打开具有唯一性标识的命名管道文件,而共享内存其实是通过OS创建一块shm,然后通过MMU将shm的地址分别映射到两个进程的各自地址空间当中,那么两个进程就可以通过这份虚拟起始地址来进行进程间通信。
在应用层也就是用户层,我们只能操作虚拟地址,但内核中会有MMU进行虚拟地址的映射,所以进程在IPC时,只需要操纵虚拟地址即可,从虚拟地址中读取或向虚拟地址中进行写入,这样就完成了共享内存式的IPC。
2. 进程凭什么独立?每个进程拥有自己独立的进程地址空间mm_struct,自己独立的映射的物理内存空间

实例

System V 共享内存的API包括以下几个系统调用:

  • shmget(2):创建一个新的段或获取一个已存在的段的标识符(ID)。这个ID是用来在其他API中引用段的。
  • shmat(2):将一个已存在的段映射到调用进程的虚拟地址空间中。这样,进程就可以通过指针来访问共享内存中的数据。
  • shmdt(2):将一个段从调用进程的虚拟地址空间中解除映射。这样,进程就不能再访问共享内存中的数据。
  • shmctl(2):对一个段进行控制操作,例如修改它的权限、获取它的状态信息、删除它等。

下面是一个使用System V 共享内存的示例程序,它由两个部分组成:writer.c和reader.c。writer.c负责创建一个共享内存段,并向其中写入一些字符串;reader.c负责读取共享内存段中的字符串,并打印出来。

writer.c:

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

#define SHM_SIZE 1024 // size of shared memory

int main() {
    int shmid; // shared memory ID
    key_t key; // key to locate shared memory
    char *shm; // pointer to shared memory

    // create a key using a file name and a char
    if ((key = ftok("writer.c", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    // create a shared memory segment
    if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666)) == -1) {
        perror("shmget");
        exit(1);
    }

    // attach the shared memory segment to the process
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    // write some strings to the shared memory
    strcpy(shm, "Hello, world!");
    shm += strlen("Hello, world!");
    strcpy(shm, "This is an example of System V shared memory.");
    shm += strlen("This is an example of System V shared memory.");
    strcpy(shm, "Goodbye!");

    // wait until reader finishes reading
    while (*shm != '*')
        sleep(1);

    // detach the shared memory segment from the process
    if (shmdt(shm) == -1) {
        perror("shmdt");
        exit(1);
    }

    return 0;
}

reader.c:

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

#define SHM_SIZE 1024 // size of shared memory

int main() {
    int shmid; // shared memory ID
    key_t key; // key to locate shared memory
    char *shm; // pointer to shared memory
    char *s;   // pointer to traverse shared memory

    // create a key using a file name and a char
    if ((key = ftok("writer.c", 'A')) == -1) {
        perror("ftok");
        exit(1);
    }

    // get the shared memory segment
    if ((shmid = shmget(key, SHM_SIZE, 0)) == -1) {
        perror("shmget");
        exit(1);
    }

    // attach the shared memory segment to the process
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }

    // read the strings from the shared memory
    s = shm;
    while (*s != '\0') {
        printf("%s\n", s);
        s += strlen(s) + 1;
    }

    // write a '*' to the shared memory to indicate reading is done
    *shm = '*';

    // detach the shared memory segment from the process
    if (shmdt(shm) == -1) {
        perror("shmdt");
        exit(1);
    }

    return 0;
}

为了运行这个示例程序,我们需要先编译writer.c和reader.c,然后先运行writer,再运行reader。运行结果如下:

$ gcc writer.c -o writer
$ gcc reader.c -o reader
$ ./writer &
[1] 1234
$ ./reader
Hello, world!
This is an example of System V shared memory.
Goodbye!
[1]+  Done                    ./writer
$

暂未完成

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

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

相关文章

OTG是什么意思?

OTG是什么意思&#xff1f; OTG是怎么样实现的&#xff1f; TYPE-C接口的手机如何实现同时充电OTG功能&#xff1f; OTG是什么意思&#xff1f; OTG是On-The-Go的缩写&#xff0c;是一项新兴技术&#xff0c;主要应用于不同的设备或移动设备间的联接&#xff0c;进行数据交…

基于遥感的自然生态环境检测——实验三:生态因子提取

实验三&#xff1a;生态因子提取 一、实验目标 生态因子生成&#xff1b;生态因子归一化&#xff1b;生态环境评价 二、实验内容 根据经过大气校正后的影像生产土地覆盖指数、土壤指数以及坡度等&#xff0c;对土地覆盖指数、土壤指数以及坡度进行密度分割归一化&#xff1…

“SCSA-T学习导图+”系列:下一代防火墙

本期引言&#xff1a; 近年来&#xff0c;随着数字化业务带给我们高效和便捷的同时&#xff0c;信息暴露面的增加、网络边界的模糊化以及黑客攻击的产业化&#xff0c;使得网络安全事件相较以往成指数级增加。传统防火墙基于五元组的方式对进出网络的数据流量进行访问控制&…

JavaScript(JS)-1.JS基础知识

1.JavaScript概念 (1)JavaScript是一门跨平台&#xff0c;面向对象的脚本语言&#xff0c;来控制网页行为的&#xff0c;它能使网页可交互 (2)W3C标准&#xff1a;网页主要由三部分组成 ①结构&#xff1a;HTML负责网页的基本结构&#xff08;页面元素和内容&#xff09;。 …

【Linux网络服务】Linux网络设置

一、查看网络配置 1.1ifconfig 1.2ip a 1.3什么是mtu 最大传输单元MTU&#xff0c;是指网络能够传输的最大数据包大小&#xff0c;以字节为单位。MTU的大小决定了发送端一次能够发送报文的最大字节数。如果MTU超过了接收端所能够承受的最大值&#xff0c;或者是超过了发送路径…

EIGRP 配置,详解拓扑表,路由汇聚

1.3 EIGRP 拓扑&#xff0c;路由以及汇聚 1.3.1 实验目的 通过对 EIGRP 拓扑&#xff0c;路由以及汇聚相关实验的练习&#xff0c;掌握 EIGRP 建立拓扑信息的方式&#xff0c; 度量计算方法&#xff0c;如何调整度量&#xff0c;非等价负载均衡&#xff0c;以及 EIGRP 末节路…

做完自动化测试,但别让不会汇报毁了你...

pytest 是一个成熟的全功能Python测试工具&#xff0c;可以帮助您编写更好的程序。它与 python 自带的 unittest 测试框架类似&#xff0c;但 pytest 使用起来更简洁和高效&#xff0c;并且兼容 unittest 框架。pytest 能够支持简单的单元测试和复杂的功能测试&#xff0c;pyte…

Verilog带参数的`define用法

宏除了可以进行简单的文本替换,还可以像函数和任务一样传递指定多个参数分别对文本进行对应的替换. 示例1&#xff1a; define Disp(pa,pb,pc) \initial \begin \#1200; \$display("%d \n",(papbpc)); \$display(" data_ pa data_ pb data_ pc %d",(…

C#中用程序代码修改了datagridview中的数据,保存时只对光标当前行有保存解决办法

C#中DataGridView绑定了DataTable后&#xff0c;通过代码修改DataGridView中的数据&#xff0c;总有一行&#xff08;被修改过并被用户选中的行集合中索引为0的行&#xff09;不能被UpDate回数据库的问题和解决办法 长江黄鹤 2017-06-26 | 300阅读 | 1转藏 转藏全屏朗读分…

真题详解(UML部署图)-软件设计(五十二)

真题详解&#xff08;地址索引&#xff09;-软件设计&#xff08;五十一)https://blog.csdn.net/ke1ying/article/details/130211684 瀑布模式&#xff1a;适应 开发大型项目&#xff0c;且需求明确。 演化模式&#xff1a;适应 对软件需求缺乏准确认知。 螺旋模式&#xff…

【linux】yum “应用商店” 的基本用法

好多工具 yum软件包查看软件包安装软件卸载软件 yum 通俗的讲&#xff0c;这就似我们手机上的应用商店&#xff0c;只不过是在linux下的。 我们可以用yum来下载东西。 软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序。 但是这样…

19 calloc 和 realloc 虚拟内存分配的调试

前言 前面提到了 malloc 虚拟内存分配相关的内容 malloc 虚拟内存分配的调试(1) malloc 虚拟内存分配的调试(2) 这里提 calloc 和 realloc, 这两个函数 虽然没有 malloc 使用频率那么高 但是 还是有很大的知名度的, 本文这里 我们来看一下 calloc 此函数传入两个参数, 第…

Obsidian中如何创作思维导图Mind-map

使用插件 obsidian-mind-map 1.直接在社区下载安装 设置快捷键或者在左侧竖形打开命令面板搜索关键字“mind”&#xff0c; 或者为了便于使用&#xff0c;设置快捷键&#xff0c;在设置-第三方插件中-选择快捷键 然后按下你想设置的快捷键就可以 我这里设置成了CtrlAltM ,M是…

虚拟数字人的3种驱动方式

虚拟数字人是由计算机程序所构建的具有人类特征的虚拟实体&#xff0c;目前的虚拟数字人经过了三代的更迭&#xff0c;划分每一代更迭的标准则是虚拟数字人的驱动方式。 一、虚拟数字人1.0&#xff1a;动画&CG驱动 虚拟数字人1.0就是目前我们所熟知的&#xff0c;比如&am…

LiveCharts2 初步认识

文章目录 1 LiveCharts2 是什么&#xff1f;2 LiveCharts2 可以做什么&#xff1f;3 简单使用LiveCharts2 &#xff0c;实现动态曲线图 1 LiveCharts2 是什么&#xff1f; GitHub&#xff1a;https://github.com/beto-rodriguez/LiveCharts2 官网&#xff1a; https://lvchar…

C++ STL学习之【反向迭代器】

✨个人主页&#xff1a; 夜 默 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 A year from now you may wish you had started today. 明年今日&#xff0c;你会希望此时此刻的自己已经开始行动了。 文章目录 &#x1f307;前言&a…

分布式锁-Redisson

分布式锁 1、分布式锁1.1 本地锁的局限性1.1.1 测试代码1.1.2 使用ab工具测试(单节点)1.1.3 本地锁问题演示(集群情况) 1.2 分布式锁实现的解决方案1.3 使用Redis实现分布式锁(了解即可)1.3.1 编写代码1.3.2 压测 1.4 使用Redisson解决分布式锁1.4.1 实现代码1.4.1 压测1.4.2 可…

2 常见模块库(2)

2.5 复用器与分路器模块 Mux是一种用于将多个信号组合成一个信号的模块。Mux模块的名称来源于多路复用器&#xff08;Multiplexer&#xff09;。 使用Mux可以将多个输入信号组合成一个向量或矩阵&#xff0c;以便在模型中传递和处理。Mux模块可以接受任意数量的输入信号&#x…

什么是伪原创?SEO伪原创该怎么做

伪原创是指在原有的文章或内容基础上进行修改或调整&#xff0c;以产生看起来是全新内容的文章&#xff0c;但实际上并没有创造新的价值。多数情况下&#xff0c;伪原创的目的是为了在文章相对原创的情况下&#xff0c;提高搜索引擎的排名。 一、高质量伪原创 做好伪原创&#…

C语言从入门到精通第8天(分支结构if、else、switch的使用)

分支结构if、else、switch的使用 if语句if...else语句if...else嵌套if...else if...else语句switch语句 if语句 语法&#xff1a; if(表达式){ 语句&#xff1b; } 如果表达式为真&#xff0c;则执行{}里面的语句。如果为假&#xff0c;则不执行。示例代码&#xff1a; int m…