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

news2024/12/25 0:12:25

🍎作者:阿润菜菜
📖专栏: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
$

暂未完成

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

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

相关文章

AD21 PCB----过滤、捕获、板子边框绘制、精准移动

目录 过滤器和捕获 板子边框绘制 精准移动 过滤器和捕获 板子边框绘制 两种方式均在Mechanical 1 方式一&#xff1a; 第一步&#xff1a;利用PCB的基础图形进行绘制边框 第二步&#xff1a;选中绘制的图形 第三步&#xff1a; 方式二&#xff1a;外部导入 第一步&#x…

SpringCloud 微服务系列——【服务间的通信方式、OpenFeign、Hystrix组件使用】

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

【UE 粒子系统】电火花粒子效果

效果 步骤 1. 新建一个粒子系统&#xff0c;命名为“SparkParticles” 再新建一个材质&#xff0c;命名为“SparkParticleMaterial” 2. 打开“SparkParticleMaterial”&#xff0c;将混合模式改为半透明&#xff0c;着色模型为无光照 然后添加如下节点 3. 打开“SparkParticl…

输入输出练习

文章目录 1. AB(1)2. AB(2)3. AB(3)4. AB(4)计算一系列数的和5. AB(5) 计算一系列数的和6. AB(6)7. AB(7)8. 字符串排序(1)9. 字符串排序(2)10 字符串排序(2)11. 注意数据范围 1. AB(1) import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public …

差分运算放大电路原理解析

差分运算放大电路&#xff0c;对共模信号得到有效抑制&#xff0c;而只对差分信号进行放大&#xff0c;因而得到广泛的用。 注&#xff1a; &#xff08;1&#xff09;共模信号   共模信号&#xff08;common mode signal&#xff09;是指同时作用于多个电路或电子设备上的信…

1.10和1.11和1.12、Makefile

1.10和1.11和1.12、Makefile 1.10、Makefile(1)1.10.1、什么是Makefile1.10.2、Makefile的文件命名和规则实际操作 1.11、Makefile(2)1. 工作原理&#xff08;1.10.3&#xff09;实际操作 1.12、Makefile(3)1. 变量2. 模式匹配3. 函数实际操作①实现变量和模式匹配②实现函数操…

Vue(简介、前期配置、Vue展示、模板语法)

一、简介 1. 什么是Vue&#xff1f; 2. Vue特点 采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护 组件化&#xff1a;每一部分直接就是大盒子组件&#xff08;创建一个单独的Vue文件&#xff09;&#xff0c;直接可以修改单独封装的组件部分代码 Vue使用声明式…

为什么需要内网穿透技术?

随着互联网技术的快速发展&#xff0c;企业和个人越来越依赖于网络资源&#xff0c;而内网穿透技术正是解决远程访问内网资源的关键。本文将详细介绍内网穿透的概念及其重要性&#xff0c;以帮助您了解为什么我们需要使用内网穿透技术。 目录 一、内网穿透技术简介 二、为什…

Java中List排序的3种方法

在某些特殊的场景下&#xff0c;我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表&#xff0c;但列表默认是以用户编号从小到大进行排序的&#xff0c;而我们的系统需要按照用户的年龄从大到小进行排序&#xff0c;这个时候&#xff0c;…

2 变量运算符-基本数据类型讲解【Go语言教程】

2 变量运算符-基本数据类型讲解【Go语言教程】 2.1 变量 2.1.1 声明变量方式 指定变量类型&#xff0c;声明后若不赋值&#xff0c;使用默认值 类型推导 通过: 多变量声明 全局变量定义 在函数外部定义的就是全局变量 变量变量名值数据类型 注意&#xff1a;如果go程序报错&…

UE4/5多人游戏详解(七、自定义委托,实现寻找会话和加入会话的函数,通过Steam进行两台电脑的联机)

目录 可能出现问题&#xff08;在六部分的测试可能无法连接的问题【在末尾加上了&#xff0c;怕有人没看见在这里写一下】&#xff09; 自定义委托 调整位置 创建更多的委托和回调函数给菜单&#xff1a; 多播和动态多播 代码&#xff1a; 委托变量 代码&#xff1a; 回…

( “树” 之 BST) 109. 有序链表转换二叉搜索树 ——【Leetcode每日一题】

二叉查找树&#xff08;BST&#xff09;&#xff1a;根节点大于等于左子树所有节点&#xff0c;小于等于右子树所有节点。 二叉查找树中序遍历有序。 109. 有序链表转换二叉搜索树 给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为高度…

Linux: 进程间通信机制

文章目录 1. 前言2. 进程间通信机制2.1 管道2.1.1 匿名管道2.1.2 popen() 和 pclose()2.1.3 命名管道 FIFO 2.2 消息队列2.3 共享内存2.4 信号量2.5 网络套接字2.6 UNIX套接字2.7 信号 3. 参考资料 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给…

基于格密码的LWE问题

LWE LWE问题&#xff0c; Learning With Errors&#xff0c;带有安全性证明的第一个版本是由Oded Regev 在2005年提出&#xff0c;Kawachi等给出了效率的改进&#xff0c;接着一些效率方面非常重要的改进由Peikert等提出。 格理论知识 格密码学&#xff08;Lattice-based Cr…

PTA L1-093 猜帽子游戏 (15 分)

宝宝们在一起玩一个猜帽子游戏。每人头上被扣了一顶帽子&#xff0c;有的是黑色的&#xff0c;有的是黄色的。每个人可以看到别人头上的帽子&#xff0c;但是看不到自己的。游戏开始后&#xff0c;每个人可以猜自己头上的帽子是什么颜色&#xff0c;或者可以弃权不猜。如果没有…

机器学习算法 决策树

文章目录 一、决策树的原理二、决策树的构建2.1 ID3算法构建决策树2.2 C4.5 算法树的构建2.3 CART 树的创建 三、决策树的优缺点 一、决策树的原理 决策树&#xff08;Decision Tree&#xff09;是一种非参数的有监督学习方法&#xff0c;它能够从一系列有特征和标签的数据中总…

NDK OpenCV人脸定位

NDK系列之OpenCV人脸定位技术实战&#xff0c;本节主要是通过OpenCV C库&#xff0c;实现识别人脸定位&#xff0c;并对识别到的人脸画面增加红框显示。 实现效果&#xff1a; 实现逻辑&#xff1a; 1.初始化CameraX&#xff0c;绑定图片分析器ImageAnalysis&#xff0c;监听…

7.队列算法

算法&#xff1a;队列算法 队列是一种抽象的数据结构&#xff0c;有点类似于Stacks。与堆栈不同&#xff0c;队列的两端都是开放的。一端始终用于插入数据(入队)&#xff0c;另一端用于删除数据(出队)。队列遵循先进先出方法&#xff0c;即首先访问先存储的数据项。 一个真实的…

【C++初阶】类与对象(上)

一.什么是类&#xff0c;什么是对象 我们可以形象的把类比作是一个房子的设计图纸&#xff0c;而对象就是根据设计图纸设计出来的房子。 由设计图纸到房子的过程&#xff0c;我们称之为类的实例化。 C兼容C的&#xff0c;所以C中的结构体在C中也能用&#xff0c;但是C把结构体升…

rust教程 第一章 —— 初识rust

文章目录 前言一、Rust简介二、安装Rust编译器三、第一个Rust程序四、 IDE环境五、初识包管理六、总结 前言 本系列教程目录可查看这里&#xff1a;Rust教程目录 近些年来不断有新的语言崛起&#xff0c;比如当下非常火的go语言&#xff0c;不过相比于C&#xff0c;go语言确实…