【Linux后端服务器开发】共享内存

news2024/9/24 7:22:45

目录

一、共享内存概述

二、共享内存(IPC资源)的查看——ipcm

三、共享内存的创建——shmget

四、共享内存的控制(删除)——shmctl

五、共享内存的关联——shmat

六、共享内存去关联——shmdt

七、进程间通信


一、共享内存概述

概念:让不同进程,看到同一个内存块的方式,就是共享内存

共享内存可以提高进程间通信的效率,减少数据拷贝带来的开销。在 Linux 系统中,可以使用 shmget、shmat、shmdt 等系统调用来操作共享内存。

优点:相比于管道而言,共享内存不仅能够用于非父子进程之间的通信,而且访问数据的速度也比管道要快。这得益于通信直接访问内存,而管道则需要先通过操作系统访问文件再获得内存数据。

缺点:用于进程间通信时,共享内存本身不支持阻塞等待操作。这是因为当读端读取数据后,数据并不会在内存中清空。因此读端和写端可以同时访问内存空间,即全双工。因为共享内存本质是进程直接访问内存,无法主动停止读取,如果读端不加以限制,那么将持续读取数据。同理,写端也会持续写入数据。换句话说,共享内存本身没有访问控制。 

二、共享内存(IPC资源)的查看——ipcm

  • 查看:ipcm -m
  • 删除:ipcrm -m [shmid]

用shell监视IPC资源:

while :; do ipcs -m; echo "---------"; sleep 1; done

共享内存不由进程控制,而是由os控制

三、共享内存的创建——shmget

创建共享内存时,通过ftok()函数获得的key值保证共享内存在系统中的唯一性

.PHONY:all
all: client serve

client: shm_client.cc
    g++ -o $@ $^ -std=c++11

serve: shm_serve.cc 
    g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
    rm -rf client serve

comm.hpp

#ifndef _COMM_HPP_
#define _COMM_HPP_

#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>

#define NAME_PATH "."
#define PROJ_ID 0x66
#define MAX_SIZE 4096

key_t GetKey() 
{
    key_t k = ftok(NAME_PATH, PROJ_ID);
    if (k < 0) 
    {
        std::cout << errno << ": " << strerror(errno) << std::endl;
        exit(1);
    }
    return k;
}

int GetShmHelper(key_t k, int flags) 
{
    int shmid = shmget(k, MAX_SIZE, flags);
    if (shmid < 0) 
    {
        std::cout << errno << ": " << strerror(errno) << std::endl;
        exit(1);
    }
    return shmid;
}

int GetShm(key_t k) 
{
    return GetShmHelper(k, IPC_CREAT);
}

int CreateShm(key_t k) 
{
    return GetShmHelper(k, IPC_CREAT | IPC_EXCL | 0600);
    // IPC_EXCL不能单独使用,若共享内存不存在则创建,若存在则报错
}

#endif

shm_serve.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = CreateShm(k);
    printf("%d\n", shmid);

    return 0;
}

shm_client.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = GetShm(k);
    printf("%d\n", shmid);

    return 0;
}

运行结果

四、共享内存的控制(删除)——shmctl

在头文件中加入删除函数

void DelShm(int shmid) 
{
    if (shmctl(shmid, IPC_RMID, NULL) == -1) 
    {
        std::cout << errno << ": " << strerror(errno) << std::endl;
        exit(1);
    }
}

shm_serve.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = CreateShm(k);
    printf("%d\n", shmid);

    sleep(5);
    DelShm(shmid);

    return 0;
}

运行结果

从对IPC资源的循环监视可见,共享内存在shm_serve运行后产生,5s后销毁

五、共享内存的关联——shmat

在头文件中加入关联函数

void* AttachShm(int shmid) 
{
    void* start = shmat(shmid, NULL, 0);
    if ((long long)start == -1) 
    {
        std::cout << errno << ": " << strerror(errno) << std::endl;
        exit(1);
    }
    return start;
}

shm_serve.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = CreateShm(k);
    printf("%d\n", shmid);

    sleep(2);
    char* start = (char*)AttachShm(shmid);
    printf("attach success, address start: %p\n", start);

    sleep(2);
    DelShm(shmid);

    return 0;
}

运行结果

serve运行之后,共享内存创建,2s之后关联数变为1,又两秒之后共享内存删除

六、共享内存去关联——shmdt

在头文件加入去关联函数

void DetAttachShm(void* start) 
{
    if (shmdt(start) == -1) 
    {
        std::cout << errno << ": " << strerror(errno) << std::endl;
        exit(1);
    }
}

shm_serve.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = CreateShm(k);
    printf("%d\n", shmid);

    sleep(2);
    char* start = (char*)AttachShm(shmid);
    printf("attach success, address start: %p\n", start);

    sleep(2);
    DetAttachShm(start);
    
    sleep(2);
    DelShm(shmid);

    return 0;
}

运行结果

serve运行之后,共享内存创建,无关联

2s之后关联数为1, 又2s之后关联数为0,又2s后共享内存销毁

七、进程间通信

shm_client.cc用同样的方式与共享内存关联和去关联

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = GetShm(k);
    printf("%d\n", shmid);

    sleep(2);
    char* start = (char*)AttachShm(shmid);
    printf("attach success, address start: %p\n", start);

    sleep(2);
    DetAttachShm(start);

    return 0;
}

先运行serve,再运行client,运行结果

在共享内存关联数为2的时刻,两个进程间可进行通信

shm_serve.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = CreateShm(k);
    printf("%d\n", shmid);

    sleep(2);
    char* start = (char*)AttachShm(shmid);
    printf("attach success, address start: %p\n", start);

    //使用
    while (true) 
    {
        printf("client say# %s\n", start);
        struct shmid_ds ds;
        shmctl(shmid, IPC_STAT, &ds);
        printf("获取属性:size(%d) pid(%d) myself(%d) key(0x%x)\n",
            ds.shm_segsz, ds.shm_cpid, getpid(), ds.shm_perm.__key);
        sleep(1);
    }

    sleep(2);
    DetAttachShm(start);

    sleep(2);
    DelShm(shmid);

    return 0;
}

shm_client.cc

#include "comm.hpp"

int main() 
{
    key_t k = GetKey();
    printf("0x%x\n", k);
    int shmid = GetShm(k);
    printf("%d\n", shmid);

    sleep(2);
    char* start = (char*)AttachShm(shmid);
    printf("attach success, address start: %p\n", start);

    //使用
    int count = 1;
    const char* message = "hello serve, 我是client,给你发消息 ";
    while (true) 
    {
        // pid count message
        snprintf(start, MAX_SIZE, "%s[pid(%d)[消息编号:%d]\n", message, getpid(), count++);
        sleep(1);
    }

    sleep(2);
    DetAttachShm(start);

    return 0;
}

运行结果

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

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

相关文章

力扣 -- 309. 最佳买卖股票时机含冷冻期

题目链接&#xff1a;309. 最佳买卖股票时机含冷冻期 - 力扣&#xff08;LeetCode&#xff09; 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 参考代码&#xff1a; class Solution { public:int maxProfit(vec…

基于matlab使用深度神经网络对肿瘤图像进行分类(附源码)

一、前言 此示例演示如何使用 Inception-v3 深度神经网络对可能不适合内存的多分辨率全玻片图像 &#xff08;WSI&#xff09; 进行分类。 用于肿瘤分类的深度学习方法依赖于数字病理学&#xff0c;其中整个组织切片被成像和数字化。生成的 WSI 具有高分辨率&#xff0c;大约…

Openlayers实战:平移、弹性平移、飞行动画

Openlayers地图上经常会遇到这样的一种 场景,获取到某数据后,会重新定位中心点到某个位置,这里可以用setCenter([lon,lat]), 更可以用动画的形式展现。 在本实战中,展示出平移、弹性平移、飞行的动画。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还是大剑…

【图像处理OpenCV(C++版)】——5.5 图像平滑之双边滤波

前言&#xff1a; &#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; &#x1f31f;&#x1f31f;&#x1f31f; 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义&#xff0c;适用于平时学习、工作快…

第三十六天 Java基础学习(三十)

一、Spring MVC 组件是将处理某类问题的代码进行封装的整体模块。一个大的问题可以拆分为不同的小问题&#xff0c;解决每个小问题的代码封装可以称之为组件&#xff0c;但是组件又是无法独立运行的&#xff0c;必须结合其他组件一起才能最终解决问题。就好比汽车&#xff0c;…

同步任务和异步任务的执行过程

同步任务和异步任务的执行过程 1、执行过程描述2、EventLoop的概念 1、执行过程描述 同步任务 是由JS主线程按次序执行异步任务委托给宿主环境执行已完成的异步任务对应的回调函数&#xff0c;会被加入到任务队列中等待执行JS的主线程的执行栈被清空后&#xff0c;会读取任务队…

Java026——System 类和Scanner 类

一、System 类 1.1、System 类提供的常用方法 方法 功能描述 ----------------------------------------------------------------------------------------------------------------------- currentTimeMillis() 返回当前计算机时间 和 格林威治时间&#xff…

mysql查询练习

1.创建表 CREATE TABLE worker( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL,工资 float(8,2) NOT NULL,政治面貌 varchar(10) NOT NULL DEFAULT 群众 , 姓名 varchar(20) NOT NULL,出生日期 date NOT NULL,PRIMARY KEY (职工号))ENGINE…

4.3Java EE——一对多查询

用户与订单关联关系图​​​​​​​ 与一对一的关联关系相比&#xff0c;接触更多的关联关系是一对多&#xff08;或多对一&#xff09;。例如一个用户可以有多个订单&#xff0c;多个订单也可以归一个用户所有。用户和订单的关联关系如图。 一、<collection>元素 在MyB…

前端技术学习第九讲:VUE基础语法---VUE常用指令

VUE常用指令 在VUE学习中&#xff0c;通常使用相关指令使VUE对象中的内容与网页进行挂载绑定&#xff0c;是我们的数据与视图之间产生关联&#xff0c;完成渐进式动态效果。VUE指令都会以“v-”开头。 指令名描述v-text将文本内容挂载到页面元素中v-html将html代码展示到页面…

更开放、更高性能、更具规模,闪马智能布局AGI时代

7月6日&#xff0c;2023世界人工智能大会&#xff08;WAIC 2023&#xff09;在上海盛大开幕。本届大会以“智联世界 生成未来”为主题&#xff0c;聚焦通用人工智能发展&#xff0c;共话产业新未来。 8日上午&#xff0c;由上海闪马智能科技有限公司&#xff08;下称“闪马智能…

ZGC垃圾收集器(-XX:+UseZGC)

ZGC在jdk11只支持Linux版本&#xff0c;4TB的内存&#xff0c;STW时间控制在10ms内&#xff1b;jdk16已经支持16TB的内存&#xff0c;STW时间不超过1ms&#xff0c;下面主要针对jdk11版本的详解 一、堆内存结构 ZGC堆内存分为三种类型的页面即小页面&#xff08;空间大小2M&a…

CYCLO (L-ALA-L-ALA),5845-61-4,环(丙氨酰-丙氨酰),氨基酸中间体

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 【产品描述】 cyclo(Ala-Ala)氨基酸中间体&#xff0c;主要由丙氨酰组成 【中文名称】环(丙氨酰-丙氨酰) 【英文名称】 cyclo(Ala-Ala)&#xff0c;CYCLO (L-ALA-L-ALA) 【结 构 式】 【CAS】5845-61-4 【分子式】C6H10N2O…

C#制作打包安装程序,安装程序类使用

这里写目录标题 安装Microsoft Visual Studio Installer Projects创建安装项目设置安装程序文件设置程序桌面图标给程序设置安装程序名称安装程序类怎么使用Installer1.cs自定义安装步骤自定义设置安装程序路径&#xff0c;让用户安装时不能选择安装路径生成安装包 安装Microso…

实例011 在状态栏中显示检查框

实例说明 在设计程序界面时&#xff0c;为了规范界面&#xff0c;可以将一些控件放置在状态栏中&#xff0c;这样既能起到控制程序的作用&#xff0c;又能使界面和谐、美观。运行程序&#xff0c;在窗体的状态栏中加入了显示时间检查框。效果如图1.11所示。 技术要点 在状态…

对Linux系统对Spark开发环境配置

单机版本 上传对应文件&#xff0c;解压文件&#xff0c;并查看 unzip scala-2.12.12.zip tar -xzf spark-3.2.0-bin-hadoop2.7.tgz 移动scala及spark安装包到指定目录下 在opt目录下移动该文件到/usr目录下 mv scala-2.12.12 /usr/scala/ mv spark-3.2.0-bin-hadoop2.7 /…

Django_使用redis缓存数据

目录 一、配置redis 二、缓存Django的默认session 三、使用django的缓存机制缓存数据 四、自定义缓存数据 源码等资料获取方法 一、配置redis 在settings中添加配置参数 # Django的缓存配置 CACHES {"default": {"BACKEND": "django_redis.ca…

【企业微信多选的星期数据生成如“周一、周三至周六“】

目标效果如下图 实现这个过程首先是要找到逻辑&#xff0c;这个看似简单的操作却属实让我想了很久。 首先要了解需求 根据拿到的数据得到生成符合要求的字符串。中间有连续的星期大于三天的&#xff0c;开始和结束星期中间要有"至"。 分析逻辑 一、判断开始日期和…

RabbitMQ系列(19)--实现在RabbitMQ宕机的情况下对消息进行处理

前言&#xff1a;在生产环境中由于一些不明原因&#xff0c;导致RabbitMQ重启的情况下&#xff0c;在RabbitMQ重启期间生产者投递消息失败&#xff0c;生产者发送的消息会丢失&#xff0c;那这时候就需要去想在极端的情况下&#xff0c;RabbitMQ集群不可用的时候&#xff0c;如…

创造一款安卓自定义控件_裁剪原理介绍

1、新增功能&#xff0c;旋转&#xff1a; 效果如图&#xff0c;点击旋转&#xff0c;可以将控件画面本身进行90度倍数的旋转&#xff0c;并进行宽高比例适配&#xff0c;旋转之后裁剪依然正常。 功能实现原理&#xff1a; 1、通过调用view的setRotation功能进行以View为中心…