linux C -- 内存管理

news2024/12/23 0:18:44

链接: linux C学习目录

linux C 共享内存机制

  • 共享内存
  • 物理位置shared memory
  • 常用函数
  • 编程模型
  • 范例
    • write.c
    • read.c
  • 修改参数
  • 实验

共享内存

  1. 二个或者多个进程,共享同一块由系统内核负责维护的内部内存区域其地址空间通常被映射到堆和栈之间
  2. 无需复制信息,最快的一种IPC机制
  3. 需要考虑同步访问的问题
  4. 内核为每个共享内存,维护一个shmid_ds结构体形式的共享内存对象

物理位置shared memory

共享内存的物理位置位于堆和栈之间
在这里插入图片描述

常用函数

#include <sys/shm.h>

/**
创建一块共享内存
*  key:该函数以key参数为键值创建共享内存,获取已有的共享内存
*  size:共享内存的字节数,建议取内存页(4096)的整数倍,
        若只为获取已有的共享内存,参数写0
*  shmflag:0-获取,不存在即失败;
           IPC_CREAT:没有就创建,有就获取
           IPC_EXCL:排斥,已存在即失败
*  return:返回共享内存的标识(和地址是一个键值对),失败-1
**/
int shmget(key_t key ,size_t size,int shmflag);


/**
映射地址到共享内存
*  shmid:唯一标识符
*  shmaddr:指定映射地址,设置为NULL系统自动选择
*  shmflg:
    0-以读写方式使用内存共享
    SHM_RDONLY-只读 
    SHM_RND-只在参数shmaddr非NULL时起作用,表示对
    改参数向下取内存页的整数倍,作为映射地址
*  return:成功返回映射地址;失败-1

注意:内存将改共享内存的加载计数+1,这类共享内存的方式
必须要所有的映射都关闭之后才能释放这块内存区域,所有必须
记录映射的次数;
**/
void* shmat(int shmid,const void* shmaddr,int shmflg);

/**
卸载共享内存
*  shmaddr:从调用进程的地址空间中,
    取消由shmaddr参数所指向的,共享内存映射区域
*
*  return:成功返回0,失败返回-1

注意:卸载后共享内存计数器减1
**/
int shmdt(const void* shmaddr);



/**
销毁/控制共享内存
*  shmid:唯一识别号
*  cmd:
    IPC_STAT - 获取共享内存的属性,通过buf参数输出
    IPC_SET  - 设置共享内存的属性,通过buf参数输入,
                仅以下三个属性可设置:
                    shmid_ds::shm_perm.uid
                    shmid_ds::shm_perm.gid
                    shmid_ds::shm_perm.mode
    IPC_RMID  - 标记删除共享内存.
                并非真正删除共享内存,只是做一个删除标记
                禁止其被继续加载,但已有加载的依然保留.
                只有当该共享内存的记载计数为0时,才真正被删除
*  struct shmid_ds*:见下

*  return:成功返回0,失败返回-1
**/
int shmctl(int shmid,int cmd,struct shmid_ds* buf)


/**
*	共享内存结构体
**/
typedef struct {
    struct ipc_perm shm_perm;//所有者及权限:见下表结构体
    size_t          shm_segsz;//大小(字节)
    time_t          shm_atime;//最后加载时间
    time_t          shm_dtime;//最后卸载时间
    time_t          shm_ctime;//最后改变时间
    pid_t           shm_cpid;//创建进程PID
    pid_t           shm_lpid;//最后加载/卸载进程PID
    shmatt_t        shm_nattch;//当前加载计数
    ...
};

struct ipc_perm {
    key_t     key;//键值
    uid_t     uid;//有效属主ID
}


编程模型

步骤进程A函数进程B步骤
1创建shmget获取1
2加载shmat加载2
3使用使用3
4卸载shmdt卸载4
5销毁shmctl

范例

write.c

#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>


int main(void){
    printf("创建共享内存...\n");
    
    key_t key = ftok(".",100);
    if(key == -1){
        perror("ftok");
        return -1;    
    }
    
    int shmid = shmget(key,4096,0644|IPC_CREAT | IPC_EXCL);
    if(shmid == -1){
        perror("shmget");
        return -1;    
    }
    
    printf("加载共享内存...\n");
    void* shmaddr = shmat(shmid,NULL,0);
    if(shmaddr == (void*)-1){
        perror("shmat");
        return -1;    
    }
    
    printf("写入共享内存...\n");
    sprintf(shmaddr,"我是%u进程写入的数据.",getid());
    
    printf("按<回车>卸载共享内存(0x%08x/%d)...",key,shmid);
    getchar();
    
    if(shmdt(shmaddr) == -1){
        perror("shmdt");
        return -1;    
    }
    
    printf("按<回车>销毁共享内存(0x%08x/%d)...",key,shmid);
    getchar();
    if(shmctl(shmid,IPC_RMID,NULL) == -1){
        perror("shmctl");
        return -1;    
    }
    
    printf("大功告成!\n");
    return 0;
}

read.c

#include <stdio.h>
#include <time.h>
#include <sys/shm.h>

int shmstat(int shmid){
    struct shmid_ds shm;
    if(shmctl(shmid,IPC_STAT,&shm) == -1){
        perror("shmctl");
        return -1;    
    }
    printf("键值:0x%08x\n",shm.shm_perm.__key);
    printf("有效属主ID:%u\n",shm.shm_perm.uid);
    printf("有效属组ID:%u\n",shm.shm_perm.gid);
    printf("有效创建者ID:%u\n",shm.shm_perm.cuid);
    printf("有效创建组ID:%u\n",shm.shm_perm.cgid);
    printf("权限字:%#o\n",shm.shm_perm.mode);
    printf("大小(字节):%u\n",shm.shm_segsz);
    printf("最后加载时间:%s\n",ctime(&shm.shm_atime));
    printf("最后卸载时间:%s\n",ctime(&shm.shm_dtime));
    printf("最后改变时间:%s\n",ctime(&shm.shm_ctime));
    printf("创建进程ID:%u\n",shm.shm_cpid);
    printf("最后加载/卸载进程ID:%u\n",shm.shm_lpid);
    printf("当前加载计数:%ld\n",shm.shm_nattch);
    
    return 0;
}


int main(void){
    printf("获取共享内存...\n");
    
    key_t key = ftok(".",100);
    if(key == -1){
        perror("ftok");
        return -1;    
    }
    
    int shmid = shmget(key,0,0);
    if(shmid == -1){
        perror("shmget");
        return -1; 
    }
    
    printf("加载共享内存...\n");
    void* shmaddr = shmat(shmid,NULL,0);
    if(shmaddr == (void*)-1){
        perror("shmat");
        return -1;    
    }
    shmstat(shmid);
    printf("读取共享内存...\n");
    printf("共享内存(0x%08x/%d):%s\n",key,shmid,shmaddr);
    
    printf("卸载共享内存...\n");
    if(shmdt(shmaddr) == -1){
        perror("shmdt");
        return -1;    
    }
    
    shmstat(shmid);
    printf("大功告成!\n");
    return 0;
}

修改参数

函数shmctl是可以修改一些特定参数的我们可以试一下

备注: 修改参数一定不要直接修改,这样会把原先的其他参数修改掉

  1. 先读取原始的共享内存结构体参数
  2. 然后修改参数
  3. 最后设置回去
//修改共享内存的一些属性
int shmset(int shmid){
    struct shmid_ds shm = {0};
    
    if(shmget(shmid,IPC_STAT,&shm) == -1){
        perror("shmctl");
        return -1;
    }
    
    shm.shm_perm.uid = 0600;
    shm.shm_segsz = 2*4096;//共享内存的大小是不能修改的
    
    if(shmctl(shmid,IPC_SET,&shm) == -1){
        perror("shmctl");
        return -1;    
    }  
}

实验

ipcs -m //查询共享内存

在这里插入图片描述
可以看到shmid = 65559的就是我们创建的共享内存,字节大小也是4096,连接数是1,就是只有一个线程在使用共享内存。

看一下使用结果
在这里插入图片描述

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

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

相关文章

web应用 —— HTML

web应用 一、HTML 1.插件 1.Live Server 模拟网站服务器 2.Auto Rename Tag 自动修改标签对 3.设置settings-format-勾选Format On Save &#xff08;创建文件&#xff1a;File-Open Folder-新建文件夹-命名文件&#xff09; 2.html文档结构 html所有标签为树形结构&…

基于YOLOv5+C3CBAM+CBAM注意力的海底生物[海参、海胆、扇贝、海星]检测识别分析系统

在我前面的一些文章中也有用到过很多次注意力的集成来提升原生检测模型的性能&#xff0c;这里同样是加入了注意力机制&#xff0c;区别在于&#xff0c;这里同时在两处加入了注意力机制&#xff0c;第一处是讲CBAM集成进入原生的C3模块中&#xff0c;在特征提取部分就可以发挥…

Microsoft系统漏洞修复

近期收到服务器系统漏洞扫描&#xff0c;发现很多关于Microsoft本身的系统漏洞。 有很多新手不知道怎么去修复系统漏洞&#xff0c;害怕一旦修复出问题&#xff0c;自己要担责。 我这里讲解下怎么准备的去寻找漏洞&#xff0c;并把它修复的过程。 我已下列的漏洞为例&#x…

RK3588平台开发系列讲解(日志篇)syslog介绍

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、syslog介绍二、syslog的架构三、syslog日志组成四、syslog接口说明1、openlog2、syslog3、closelog五、syslog.conf接口说明1、selector2、level3、action4、示例沉淀、分享、成长,让自己和他人都能有所收获!&am…

计算机网络第三章

目录 1.数据链路层 1.数据链路层的基本概述 2.数据链路层的功能概述 3.封装成帧 4.差错控制 1.检错编码 2.纠错编码 5.流量控制 1.停止-等待协议 2.选择重传协议(SR) 3.后退N帧协议(GBN) 6.介质访问控制 1.静态划分信道(信道划分介质访问控制) 2.动态分配信道 7.局域网 8.链路…

【经验分享】美赛报名以及注册方法-以2023年美赛为例

首先点击COMAP的官网链接&#xff1a; https://www.comap.com/ 然后选择Contests目录下的MCM/ICM 选择 Learn More and Register 然后选择 Click here to register for the 2023 MCM/ICM contest 注册分为两个步骤&#xff1a;顾问&#xff08;指导教师&#xff09;注册和填…

uni-app中自定义TabBar

1.由于原生的tabBar不能做到事件的拦截处理所以才自定义 注意点&#xff1a;自定义tabBar后则原生的uni.switchTab(OBJECT)不能再使用了 第一步&#xff1a;需要把原生的tabBar注释掉 第二步&#xff1a;在components下新建TabBar.vue文件&#xff08;那个页面用那个页面引入…

RHCE-Web服务器在linux上的部署,了解hash算法以及常见的加密方式

目录 1.WEB服务器&#xff08;Web Server&#xff09; 浏览器 工作原理 常见状态码&#xff1a; www服务器的基本配置 2.web服务配置样例 3.了解hash算法以及常见的加密方式 hash算法&#xff1a; 常用HASH函数 处理冲突方法 常用hash算法的介绍&#xff1a; ssh协议…

Composition步骤

纲要&#xff1a; SWC属于AUTOSAR的Component文件夹下&#xff0c;而Composition属于Composition文件夹下。 AUTOSAR Project Structure Sample目录 1. Create Software Composition 2. Add SWC into Composition 3. Create AssemblyConnector between SWCs 1. Create Sof…

优化SpringBoot程序启动速度

Spring Boot 程序优化 一、延迟初始化Bean 一般在 SpringBoot 中都拥有很多的耗时任务&#xff0c;比如数据库建立连接、初始线程池的创建等等&#xff0c;我们可以延迟这些操作的初始化&#xff0c;来达到优化启动速度的目的。Spring Boot 2.2 版本后引入 spring.main.lazy-i…

【大数据hadoop】基于centos7搭建haoop与hive

一、前言 hadoop是大数据生态中的基础服务&#xff0c;也是其他大数据框架的基础运行环境&#xff0c;尤其是hdfs&#xff0c;是其他大数据框架的基础存储载体&#xff0c;因此系统学习和掌握hadoop对学习大数据很有必要&#xff1b; 而Hive则是Hadop生态系统中必不可少的一个数…

分布式任务介绍

分布式任务解决方案 Elastic-Job介绍 官网&#xff1a;http://elasticjob.io/index_zh.html 由当当网基于Quartz Zookeeper的二次开放产品 基于Zookeeper分布式锁&#xff0c;保证只有一个服务去执行定时任务。 基于Zookeeper实现了注册中心&#xff0c;自动帮助我们去调度指…

pgCluu 的安装、使用与实践

文章目录前言一、什么是 pgCluu二、pgCluu的安装流程静态模式动态模式三、pgCluu的用法pgCluu 用法pgCluu_collectd 用法&#xff1a;四、pgCluu的实操分享实操示例一&#xff1a;实操示例二&#xff1a;前言 PostgreSQL 的监控方法很多&#xff0c;数量越来越多的 PG 的监控再…

MFC输出普朗克常数

在量子力学中可以计算德布罗意波长&#xff0c;其公式如下&#xff1b; 德布罗意波长 h / (质量 * 速度&#xff09;&#xff1b; 其中h是普朗克常数&#xff1b; 先看一下普朗克常数&#xff1b;6.62 乘以10的负34次方&#xff1b; 输出一下此常数看一下&#xff1b; #de…

SpringCloud之Spring Cloud Config 分布式配置

Spring Cloud Config 分布式配置1. 分布式系统面临的配置文件问题2. Spring Cloud Config 分布式配置中心的概念3. Spring Cloud Config 分布式配置中心的作用4. Spring Cloud Config 分布式配置中心和 GitHub 整合5. 小案例Dalston.RELEASE Spring Cloud Config 为分布式系统…

Web3中文|Web3注定会成为元宇宙的一部分

“Web3”和“元宇宙”或许是2022年最热门的流行语了。在营销行话中、在广告中、在新闻报道中&#xff0c;Web3和元宇宙这两个概念总是被捆绑在一起。 但不得不说&#xff0c;二者经常被混为一谈是有原因的。因为它们都是定义模糊的新技术&#xff0c;都被认为是互联网的未来&a…

20230112在Ubuntu下看笔记本电脑电池的电量

20230112在Ubuntu下看笔记本电脑电池的电量 2023/1/12 17:24 ubuntu20.04 Xshell 7 (Build 0108) Copyright (c) 2020 NetSarang Computer, Inc. All rights reserved. Type help to learn how to use Xshell prompt. [C:\~]$ Connecting to 192.168.186.228:22... Connecti…

知物由学 | 多级建模方法提升汉语语音识别效果,获ISCSLP大赛认可

导读&#xff1a;语音是人类信息沟通的重要途径&#xff0c;同时也是人机交互的重要桥梁&#xff0c;自动语音识别可以表述为通过计算机将人类语音信号转录为书面形式的文字输出的过程。本文分享了网易易盾提出的多级建模单元的端到端汉语语音识别方法及具体的落地实践。 1.语…

什么是虹科weeve边缘计算软件平台?

一、前言 随着越来越多的企业希望进入物联网领域&#xff0c;他们在构建和部署物联网项目时面临着前所未有的挑战。根据思科的一项调查表明&#xff0c;超过60&#xff05;的受访者承认他们严重低估了管理自己的物联网计划的复杂性。更令人震惊的是&#xff0c;同一调查还发现…

MongoDB副本集搭建和读写分离配置

MongoDB副本集&#xff08;Replication Set&#xff09;由一组mongod实例(进程)组成&#xff0c;包含一个Primary节点和多个Secondary节点.客户端数据写入Primary节点。Secondary节点从Primary节点同步数据。以保持副本集内所有成员存储相同的数据集。Primary节点故障时会自动选…