linux 共享内存 shmget

  74ac905cfa3740079f2f66a445a3d7c2.gif#pic_center

  • 专栏内容:linux下并发编程
  • 个人主页:我的主页
  • 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

目录

前言

概述

原理机制

系统命令

接口说明

代码演示

结尾


前言

本专栏主要分享linux下并发编程相关知识,包括多进程,多线程,进程/线程间通信,并发同步控制,以及高并发下性能提升,请大家多多留言。


概述

共享内存是进程间通信的一种常用手段,相较于其它通信方法,它可以在进程间传递大量的不同格式的数据,同时这些数据不需要持久保存在磁盘上。

原理机制

共享内存相当于操作系统在进程的地址空间外,再开辟了一段物理内存,再把这段物理内存映射到进程的虚拟地址空间内,这样进程就可以访问了。

那么不同进程如何知道这段物理内存呢?

所以,第一步是确定一个唯一的key值,把这个key在不同进程间传递,不同进程拿到后就可以用这个key值向操作系统查到共享内存空间。

第二步,就是映射到进程的内存空间。我们都知道,进程的内存空间是一个虚拟地址空间,通过段页机制将物理内存地址转成虚拟内存地址,所以此处的共享内存,也需要把它挂到进程的虚拟地址空间中,进程才可以访问,不然还是找不到。

第三步,此时就可以直接读写了。

第四步,使用完成后,资源需要释放,否则会造成内存泄漏,这可是编程的大忌。因为涉及到多个进程共同使用,当然我们释放有两种形式,一是当前进程不再引用使用,此时共享内存还存在;一种是其它进程不再使用时,删除共享内存,此时共享内存就彻底不存在了。

系统命令

查询共享内存系统资源,使用系统命令

 ipcs -m

查询结果如下:

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status

0x0101de21 229412     test     600        8192       1

手动使用系统命令删除共享内存,使用共享内存的id

ipcrm -m shmid

接口说明

接口对应的头文件为

 #include <sys/types.h>

 #include <sys/ipc.h>

 #include <sys/shm.h>

(1)创建和获取已有的共享内存,每个共享内存都有唯一的key来标识,key值可以用IPC_PRIVATE,也可以用ftok函数生成。

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

size ,共享内存的大小,分配时会与PAGE_SIZE向上取整;

shmflg,可以取值

IPC_CREAT

创建共享内存,如果不带时,只是查找key值标识的共享内存

IPC_EXCL

与IPC_CREATE一起使用,如果已经有key标识的共享内存时,就会失败

SHM_HUGETLB

创建大页内存,一般页面大小为2KB/4KB,这里可以使更大的页面,在密集型读时可以得到性能提升;

SHM_HUGE_2MB

同上,创建2MB的大页内存

SHM_NORESERVE

不为此共享内存使用swap空间

(2)映射到进程私有虚拟地址空间

void * shmat(int shmid, char __user * shmaddr, int shmflg);

将shmid标识的共享内存,映射到shmaddr对应的进程内存地址上,映射后的地址是与SHMLBA向下对齐的地址。如果地址为空,则由系统选择一块进程空闲空间进行映射。

关于SHMLBA,这是关于CPU  cache调度相关,有些话长,在另外一篇博文中专门解释。

shmflg,标识共享内存的使用权限,可以取值

SHM_EXEC

共享内存可以有执行权限

SHM_RDONLY

以只读权限使用共享内存

SHM_REMAP

如果当前映射地址已经有映射有其它共享内存,可以进行替换

(3)解除与当前进程的映射

int shmdt(const void *shmaddr);

当然这里只是与当前进程解除了映射,内核资源也仅仅对引用计数减一,并没有删除;

(4)删除共享内存资源

int shmctl(int shmid, int cmd, struct shmid_ds * buf);

此系统函数,可以对共享内存进行一些控制操作,其中包括删除共享资源,由cmd来指定对应的操作;

cmd,可以取下面的值

IPC_STAT

调用者需要有读权限,会将kernal中共享内存信息拷到buf中返回

IPC_SET

可以设置shmid_ds结构成员的信息

IPC_RMID

销毁共享内存,当然必须是引用计数为0,调用者一定是创建者或最后一个使用进程

IPC_INFO

获取共享内存的系统限制相关参数值

SHM_INFO

获取共享内存资源使用情况

SHM_STAT

同IPC_STAT

SHM_LOCK

锁定共享内存,此时内存页面不会被替换

SHM_UNLOCK

解除锁定

(5)ftok系统函数对应的头文件与声明如下:

#include <sys/types.h>

#include <sys/ipc.h>

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

代码演示

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

#define SHM_SIZE 8192
int main(int argc ,char *argv[])
{
        key_t   shm_key = ftok(".", 1);
        int shm_id = -1;
        char *pshm = NULL;
        char str[] = "Hello, World!";
        int pid = 0;
        int underSubprocess = 0;

        shm_id = shmget(shm_key, SHM_SIZE, 0600|IPC_CREAT);
        if(shm_id < 0)
        {
                printf("get shm error [%s]\n",strerror(errno));
                return -1;
        }

        pshm = (char *)shmat(shm_id, NULL, 0);
        if(pshm == (char *)-1)
        {
                printf("attach sharememory error [%s]\n", strerror(errno));
                return -1;
        }

        pid = fork();
        if(pid == 0)
        {
                // under subprocess
                printf("I'm in the subprocess\n");
                sleep(2);
                printf("recv: %s\n",pshm);
                underSubprocess = 1;
        }
        else if(pid > 0)
        {
                strncpy(pshm, str, sizeof(str));

                sleep(5);
                printf("I'm father ,will exit.\n");
        }
        else
        {
                printf("fork error\n");
        }

        if(-1 == shmdt(pshm))
        {
                printf("detach sharememory error [%s]\n",strerror(errno));
                return -1;
        }

        if(underSubprocess == 0)
                shmctl(shm_id, IPC_RMID, NULL);

        return 0;
}

在运行过程中查看系统共享内存

------ Shared Memory Segments --------

key        shmid      owner      perms      bytes      nattch     status

0x0101de21 229412     test     600        8192       1

确实已经创建了。


结尾

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。另外有什么想要了解的内容,也可以给我发邮件,互相谈讨,定知无不言。

注:未经同意,不得转载!

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

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

相关文章

【深度解刨C语言】内存管理(详)

文章目录前言一.动态内存1.动态内存的用处2.内存的布局简单证明内存布局栈向下生长的证明堆向上增长的证明3.malloc与free进一步理解总结前言 前提: 内存有基本的认识 内存函数基本的了解 如果你对内存与内存函数太不清楚可以看:动态内存管理 目标: 为什么要用动态内存&…

我体验了首个接入GPT-4的代码编辑器,太炸裂了

最近一款名为Cursor的代码编辑器已经传遍了圈内&#xff0c;受到众多编程爱好者的追捧。 它主打的亮点就是&#xff0c;通过 GPT-4 来辅助你编程&#xff0c;完成 AI 智能生成代码、修改 Bug、生成测试等操作。 确实很吸引人&#xff0c;而且貌似也能大大节省人为的重复工作&…

vue尚品汇商城项目-day04【29.加入购物车操作(难点)】

文章目录29.加入购物车操作&#xff08;难点&#xff09;29.1加入购物车按钮29.2addCartSuce29.3购物车29.3.1 向服务器发送ajax请求&#xff0c;获取购物车数据29.3.2UUID临时游客身份29.3.3动态展示购物车29.4修改购物车产品的数量&#xff08;需要发请求&#xff1a;参数理解…

203. 移除链表元素

1、题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&…

File 类的用法和 InputStream, OutputStream,System 类的用法

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

Typescript学习笔记(一)

什么是TypeScript? TypeScript 是添加了类型系统的 JavaScript&#xff0c;适用于任何规模的项目。 TypeScript 是一门静态类型、弱类型的语言。 安装TypeScript npm install -g typescript编译 tsc hello.tsTypeScript 只会在编译时对类型进行静态检查&#xff0c;如果发…

iOS 内存管理机制与原理

内存分区 内存一般分为五大区&#xff1a;栈区、堆区、常量区、全局区、代码区。如图 1.栈区 是由编译器自动分配并释放的&#xff0c;主要用来存储局部变量、函数的参数等&#xff0c;是一块连续的内存区域&#xff0c;遵循先进后出&#xff08;FILO&#xff09;原则。一般在…

WebAssembly 助力云原生:APISIX 如何借助 Wasm 插件实现扩展功能?

本文将介绍 Wasm&#xff0c;以及 Apache APISIX 如何实现 Wasm 功能。 作者朱欣欣&#xff0c;API7.ai 技术工程师 原文链接 什么是 Wasm Wasm 是 WebAssembly 的缩写。WebAssembly/Wasm 是一个基于堆栈的虚拟机设计的指令格式。 在 Wasm 未出现之前&#xff0c;浏览器中只能…

Hadoop(伪分布式)+Spark(local模式)搭建Hadoop和Spark组合环境

一、安装Hadoop环境使用Ubuntu 14.04 64位 作为系统环境&#xff08;Ubuntu 12.04&#xff0c;Ubuntu16.04 也行&#xff0c;32位、64位均可&#xff09;&#xff0c;请自行安装系统。Hadoop版本: Hadoop 2.7.4创建hadoop用户如果你安装 Ubuntu 的时候不是用的 "hadoop&qu…

研究的艺术 (The craft of research) 读书笔记

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 对于研究者而言&#xff0c;写作是一件很重要的事&#xff0c;好的写作不仅能让更多人愿意读&#xff0c;获得更大影响力&…

Windows系统配置SSH服务

1.安装OpenSSH 打开【设置】-【应用】 选择【管理可选功能】 点击【添加可选功能】 选择【OpenSSH 服务端】&#xff0c;切记不是【OpenSSH 客户端】&#xff08;如果安装一个不行&#xff0c;就都安装&#xff0c;我都安装了可以用&#xff09;&#xff0c;然后点击下载即可 …

ERP系统如何让项目管理更轻松?

项目管理是许多企业的首要任务&#xff0c;通常有一个ERP系统来协助他们。然而&#xff0c;一些企业仍然没有意识到&#xff0c;ERP解决方案可以使他们的项目管理更容易。项目管理需要有一个目标&#xff0c;并在你朝着完成项目前进的过程中控制变量&#xff0c;而ERP系统指导你…

成都北大青鸟怎么样?

对于任何一个培训机构的了解大概的流程是&#xff1a;听说名字——网上搜索&#xff0c;可以看到机构官网&#xff0c;也会看到机构广告&#xff0c;当然也会看到各种有好有坏的评论&#xff0c;到这里会对机构形成初印象&#xff1b;然后如果身边有培训出身的小伙伴会去询问对…

【C语言进阶:自定义类型详解】联合(共用体)

本节重点内容&#xff1a; 联合类型的定义联合的特点联合大小的计算⚡联合类型的定义 联合也是一种特殊的自定义类型这种类型定义的变量也包含一系列的成员&#xff0c;特征是这些成员公用同一块空间&#xff08;所以联合也叫共用体&#xff09;。 为了方便大家理解举个例子…

Java 网络编程之NIO(ByteBuffer)

在 Java NIO 中&#xff0c;ByteBuffer 是用于存储和传输数据的一种数据结构。它提供了高效的数据存储和读取能力&#xff0c;使得 Java NIO 能够高效地处理大量的数据输入输出。 ByteBuffer 的作用包括以下几个方面: 存储数据:ByteBuffer 可以存储任意长度的数据&#xff0c;…

Elasticsearch 8.X 如何基于用户指定 ID 顺序召回数据?

1、实战问题如何根据输入的id 的顺序输出结果&#xff0c;id 个数有500个&#xff0c;还有分页&#xff1f;问题来源&#xff1a;https://t.zsxq.com/0cdyq7tzr2、方案探讨2.1 Elasticsearch 默认排序机制在 Elasticsearch 中&#xff0c;如果未指定排序规则&#xff0c;检索结…

Linux下实现的 HTTP 服务器

项目功能&#xff1a;&#xff08;1&#xff09;能接收客户端的GET请求&#xff1b;&#xff08;2&#xff09;能够解析客户端的请求报文&#xff0c;根据客户端要求找到相应的资源&#xff1b;&#xff08;2&#xff09;能够回复http应答报文&#xff1b;&#xff08;3&#x…

数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路、题解过程、完整题解

目录 题目描述 题目示例 核心思路 链表实现 数组实现 重点 题解过程 结构体类型定义 创建一个循环队列并初始化 判断循环队列为空或为满 入队列函数 出队列函数 取队头数据 取队尾数据 销毁循环队列 完整题解 题目来源&#xff1a;力扣 题目描述 设计你的…

Sentinel滑动时间窗限流算法原理及源码解析(下)

文章目录对统计数据如何使用获取之前统计好的数据对统计数据如何使用 流控快速失败 获取之前统计好的数据

SpringBoot 项目的创建与启动

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