Linux学习笔记之八(进程间的共享内存)

news2024/11/20 6:36:04

Linux

  • 1、引言
  • 2、实现共享内存
    • 2.1、创建一个共享内存
    • 2.2、将共享内存链接到进程空间
    • 2.3、断开与共享内存的链接
    • 2.4、对共享内存进行后续操作
  • 3、应用实例

1、引言

在之前一篇文章Linux学习笔记之六(进程之间的管道通信和信号处理)中我讲了进程间可以通过管道通信。管道通信也是在内存中某个地方开辟一块内存,让不同进程可以访问它,进而实现通信的目的。
而本文所讲的共享内存也大概是这么一个逻辑,不过相较与管道通信,内存共享实现起来更加复杂,也没有读写阻塞功能,但执行起来的效率也更加高,似乎是最快的进程通信方式。

2、实现共享内存

共享内存其任务在于从物理内存中申请一块内存区域,然后将这个区域映射到不同进程的空间中。进而进程访问该共享区域,进行读写操作。下图截取于B站,该图比较清晰明了说明了共享内存的运行逻辑。从这张图可以看出,任何进程都有自己的空间,而这些空间本质是取之于物理内存,但取的顺序则是杂乱的。共享内存无非是一块大家都可以取走的内存块而已。
在这里插入图片描述
接下来说明实现共享内存的基本步骤:
第一步:创建一个共享内存
第二步:将共享内存链接到进程空间
第三步:断开与共享内存的链接
第四步:对共享内存进行后续操作(如销毁)

2.1、创建一个共享内存

创建一个共享内存用到的函数是shmget(share memory get),其函数原型如下:

int shmget(key_t key, size_t size, int shmflag);

参数概览:

key:设置该共享内容的关键字标识。
size:指定共享内存的空间大小。
shmflag:设置共享内存的访问权限。
返回值:创建成功则返回共享内存标识符,失败则返回-1.

参数详解:
1. key参数:key 参数是一个用于标识共享内存段的关键字。它允许多个进程通过使用相同的 key 参数来访问同一个共享内存段。这就是说,如果多个进程想要访问同一个共享内存段,它们必须提供相同的 key 参数值。
通常情况下,key 参数可以是一个由 ftok() 函数生成的键值(通过给定文件路径名和一个项目标识符来生成唯一的键值),也可以是手动指定的一个键值,也可以通过一些宏指定一些key值。
关于ftok函数,其函数原型如下:

key_t ftok(const char *pathname, int proj_id);

第一个参数是真实存在的文件路径,第二个参数是项目的id,可以自己设定。
计算机会根据这两个参数的组合,生成一个独一无二的key值,保证不同进程可以访问同一个内存空间。
2. size参数:一般而言我们会设置成4096的整数倍,因为计算机的最小内存单元就是4kB,但如果不设置成4096的整数倍也无所谓,计算机会根据自动帮你调整到合适的值。比如你设置2009,计算机也会帮你调整到4096.
2. shmflag参数:该参数用于设置共享内存的访问权限,一般由一些宏和四位整数组成,比如0777 | IPC_CREAT。权限的设置相信大家都耳熟能详了,第一位0表示后面的三位数字是八进制数字,777分别表示,用户、用户组、其他人的权限。7会被拆解位111,分别表示rwx(读写执行)三个权限。
常见的宏有:
IPC_CREAT:若共享内存存在则打开,否则创建一个。
IPC_EXCL:若共享内存不存在则创建,否则报错。
IPC_NOWAIT:若该操作需要等待,直接报错。

最后是调用该函数需要头文件(后文提到的所有函数也需要包含这几个头文件):

#include "sys/types.h"
#include "sys/ipc.h"
#include "sys/shm.h"

2.2、将共享内存链接到进程空间

在这一步用到函数是shmat,其函数原型如下:

void *shmat(int shmid, const void *addr, int shmflg);

参数概览:

shmid:这里输入的是共享内存的标识符,其实就是shmget函数的返回值。
void *addr:指定链接到进程中的哪个地址块,一般不需要指定,由计算机自动分配即可。
int shmflg:标志位,一般设置为0即可。
返回值:成功则返回共享内存在进程空间中的链接地址,失败则返回-1。

注:void *指的是无类型指针,无类型换一种理解方式就是,可以赋予它任意类型。
通过这个步骤,我们拿到了链接地址,再用这个地址来索引相应的内存空间之后,便可以进行读写操作,以实现进程通信。

2.3、断开与共享内存的链接

进程通信结束之后自然是要将进程与共享内存之间的链接断开。这一步用到的函数时shmdt,其函数原型如下:

int shmdt(const void *address);

void *address:该地址指的进程空间中的链接地址。一般就是shmat中的返回值了。
返回值:成功则返回0,失败则返回-1。

2.4、对共享内存进行后续操作

进程通信结束,链接也断开,下一步自然是要考虑如何回收或销毁这个共享内存了。用到的函数时shmctl,其函数原型如下:

int shmctl(int shm_id, int command, struct shmid_ds *buf);

shm_id:共享内存对象的id,即内存的标识符。一般时shmget的返回值。
command:指定对该内存的操作命令,主要有删除命令(IPC_RMID)。
shmid_ds *buf:该参数用于获取内核结构的结构值,一般也不用。故直接设置为0即可。

最后注意一点,如果使用调用shmctl(shmid, IPC_RMID, 0)这句话,最后删除的只是共享内存的标识符,使系统不再维护该内存标识符,而不是真正把共享内存释放掉。如果想要共享内存被释放掉,则需要等到该内存没有被任何进程调用时,系统才会自动被释放掉。

3、应用实例

本例子的目的:创建两个进程A和B,A进程往共享内存写入数据,B进程将数据读出来。
故,首先创建一个进程A,去往一块共享内存写入数据。

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


int main()
{
    key_t key  = ftok("$HOME/shared_memory/program_A.c", 9);        //generate a unique key
    int shmid = shmget(key, 4096, 0751|IPC_CREAT);                  //create a shared memory
    char *addr = shmat(shmid, 0, 0);        //link the shared memory with this program               
    char buffer[100];           //create a buffer for writing data
    while(1)
    {
        printf("\nPlease input a character: ");
        fgets(buffer, sizeof(buffer), stdin);
        if(strcmp(buffer, "q\n") == 0)              //judge whether what I input is 'q' or not
            break;                                  
        strncpy(addr, buffer, sizeof(buffer));          //writing data into the shared memory
    }
    
    if(shmdt(addr) == 0){
        printf("disconnect shared memory successfully!\n");
    }
    else{
        printf("fail to disconnect!\n");
    }

    if(shmctl(shmid, IPC_RMID, 0) == 0)
    {
        printf("delete the identifer successfully!\n");
    }
    else{
        printf("the identifer already be deleted!\n");
    }

    return 0;
}

其次,创建一个进程B,从共享内存中读取数据。

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


int main()
{
    key_t key  = ftok("$HOME/shared_memory/program_A.c", 9);      
    int shmid = shmget(key, 4096, 0751|IPC_CREAT);                  
    char *addr = shmat(shmid, 0, 0);                     
    while(1)
    {
        char input;
        printf("please input a character: ");
        scanf("%c", &input);
        if(input == 'q')
            break;
        int c;
        while ((c = getchar()) != '\n' && c != EOF) {}
        printf("what i receive is: %s\n", addr);
    }
    
    if(shmdt(addr) == 0){
        printf("disconnect successfully!\n");
    }
    else{
        printf("fail to disconnect!\n");
    }

      if(shmctl(shmid, IPC_RMID, 0) == 0)
    {
        printf("delete successfully!\n");
    }
    else{
        printf("the identifer already be deleted!\n");
    }

    return 0;
}

最后,我打开两个终端,同时运行进程A和B,运行结果如下:
在这里插入图片描述

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

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

相关文章

如何快速构建知识服务平台,打造个人或企业私域流量

随着互联网的快速发展&#xff0c;传统的知识付费平台已经不能满足用户的需求。而SaaS知识付费小程序平台则是一种新型的知识付费方式&#xff0c;具有灵活、便捷、高效等特点&#xff0c;为用户提供了更加优质的付费知识服务。本文将介绍如何搭建自己的SaaS知识付费小程序平台…

T天池SQL训练营(五)-窗口函数等

–天池龙珠计划SQL训练营 5.1窗口函数 5.1.1窗口函数概念及基本的使用方法 窗口函数也称为OLAP函数。OLAP 是OnLine AnalyticalProcessing 的简称&#xff0c;意思是对数据库数据进行实时分析处理。 为了便于理解&#xff0c;称之为窗口函数。常规的SELECT语句都是对整张表进…

elasticsearch-head 启动教程

D:\elasticsearch-head-master>grunt server ‘grunt’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 npm install -g grunt-clinpm install

资源三号5米全国数字高程模型DEM

简介 近些年来&#xff0c;国产高分辨率遥感卫星的发展突飞猛进&#xff0c;天绘系列卫星、资源三号卫星、高分一号、二号卫星以不断提高的影像空间分辨率、逐步增强的影像获取能力、较好的影像现势性等特点逐步打破了国外商业卫星的主导地位&#xff0c;开始广泛服务于各…

Andorid sudio 换行方法

1.遇到的问题&#xff0c;二维码内容要换行 String text "成绩&#xff1a;1000 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff1a;张三 \n姓名&#xff…

Java数字化健康卫生智慧云HIS系统源码

基于云计算技术的B/S架构云HIS集挂号、处方、收费、取药、病历于一体,完全适配各类中小型医院、诊所。 一、云 HIS定义 1、云 HIS 系统是运用云计算、大数据、物联网等新兴信息技术&#xff0c;按照现代医疗卫生管理要求&#xff0c;在一定区域范围内以数字化形式提供医疗卫生…

细讲结构体

结构体是一些值的集合&#xff0c;这些值就是成员变量&#xff0c;这些变量可以是不同类型的。 当我们存放一个学生的信息是&#xff0c;包括性别&#xff0c;姓名&#xff0c;学号&#xff0c;年龄等内容&#xff0c;这些值是不同类型的&#xff0c;这是我们就可以使用结构体来…

实战rce绕过getshell曲折经历

tp rce漏洞 该网站debug显示该站点的tp版本为5.0.5&#xff0c;宝塔搭建 直接上rce payload 执行成功 问题点&#xff1a; 1.此站点disable_functions函数基本都禁用了&#xff0c;另外加载了禁用eval的扩展 2.web目录不允许出现.php后缀文件&#xff0c;写入后会立即删除 绕…

名创优品出海更难了,Q3净利增速放缓

近日&#xff0c;有媒体报道称&#xff0c;名创优品受市场流传针对公司的做空报告&#xff0c;叠加高管团队两次减持&#xff0c;共计180万股&#xff0c;若对应25美元的价格&#xff0c;则达4500万美元(约3.2亿元)。 12月5日&#xff0c;其港股收盘股价下跌14.04%&#xff1b…

本地团购分销:解密最新赚钱模式,带你开启财富之门!APP小程序H5三端源码交付,支持二开!

近年来&#xff0c;随着互联网的迅猛发展和电子商务的普及&#xff0c;本地团购分销逐渐成为了一种热门的赚钱模式。它不仅为消费者提供了更多的购物优惠&#xff0c;同时也给商家和分销商带来了可观的利润。在这篇文章中&#xff0c;我们将详细介绍本地团购分销的运作原理和盈…

15Linux、GIT及相关相似面试题、PostMan

Linux和git相似是命令相关的层次结构相似 Linux Linux Linux常用操作_linux操作-CSDN博客 程序员常用的10个Linux命令_简介linux系统中的10个常用命令及功能-CSDN博客 help help 命令 &#xff1a;获得 shell 内置命令的帮助信息&#xff0c;常用形式 help cd ls --help …

【C/PTA —— 15.结构体2(课内实践)】

C/PTA —— 15.结构体2&#xff08;课内实践&#xff09; 7-1 计算职工工资7-2 计算平均成绩7-3 找出总分最高的学生7-4 通讯录的录入与显示 7-1 计算职工工资 #include<stdio.h> #include<stdlib.h> typedef struct GZ {char name[6];double j;double f;double z;…

【Python系列】Python函数

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

2023 金砖国家职业技能大赛网络安全省赛理论题样题(金砖国家未来技能挑战赛)

2023 金砖国家职业技能大赛网络安全省赛理论题样题&#xff08;金砖国家未来技能挑战赛&#xff09; 一、参加比赛的形式 团队参与&#xff0c;每队2名选手&#xff08;设队长1名&#xff09;。 二、项目项目阶段简介 项目由四个阶段组成&#xff0c;将按顺序完成。向参与者…

21、命令执行

文章目录 一、命令执行概述1.1 基本定义1.2 原理1.3 两个条件1.4 命令执行漏洞产生的原因1.5 管道符号和通用命令符 二、远程命令执行2.1 远程命令执行相关函数2.2 远程命令执行漏洞的利用 三、系统命令执行3.1 相关函数3.2 系统命令执行漏洞利用 四、命令执行漏洞防御 一、命令…

[python库] mistune库的基本使用

前言 mistune库是一个解析Markdown的利器&#xff0c;使用起来非常简单。当我们想要解析Markdown格式的文档时&#xff0c;只需两步就能将其转换成html格式。如下&#xff1a; import mistune mistune.html(YOUR_MARKDOWN_TEXT)安装方式也非常简单&#xff0c;dddd&#xff1…

qt creator配置opencv库 (MSVC版本)

目录 1. MSVC版本 1.1 使用cmake编译opencv 1.2 再使用visual studio 2019生成opencv的lib,dll 1.3 配置opencv的系统环境变量 1.4 新建qt项目 1. MSVC版本 1.1 使用cmake编译opencv 1.2 再使用visual studio 2019生成opencv的lib,dll 1.3 配置opencv的系统环境变量 D:…

图形视图【例】对数计算尺

文章目录 对数计算尺 &#x1f4cf;示例代码 对数计算尺 &#x1f4cf; 对数可以有效地把乘法转换成加法运算,比如: l n A ∗ B l n A l n B ln^{A*B} ln^{A} ln^{B} lnA∗BlnAlnB 对数计算尺就是利用对数性质把乘法换成加法的一种辅助工具. 图片来自《程序员的数学1》 …

C //习题10.4 有两个磁盘文件“A“和“B“,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件“C“中去。

C程序设计 &#xff08;第四版&#xff09; 谭浩强 习题10.4 习题10.4 有两个磁盘文件"A"和"B"&#xff0c;各存放一行字母&#xff0c;今要求把这两个文件中的信息合并&#xff08;按字母顺序排列&#xff09;&#xff0c;输出到一个新文件"C"…

智能优化算法应用:基于爬行动物算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于爬行动物算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于爬行动物算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.爬行动物算法4.实验参数设定5.算法结果6.参考…