当前位置: 首页 > news >正文

用户虚拟地址空间布局架构

目录

一、Linux内核整体架构及子系统

二、内存管理模块架构

三、用户地址空间的内存布局

(1)mm_struct

(2)vm_area_struct


一、Linux内核整体架构及子系统

        Linux内核是操作系统中最为关键的一个部分,对下管理所有硬件资源,对上提供系统调用接口给程序员使用。

        下图是对操作系统整体架构的简图:

但是我们可以将其更具体化一点,专门看看内核以下部分:

二、内存管理模块架构

整体架构如下:

        对于我们上层无论是malloc还是new,本质都调用到了比如ptmalloc、tcmalloc等。即malloc是对外呈现的状态,但是可以根据需求选择底层的逻辑。

        ptmalloc和tcmalloc本质是一个内存池,因为操作系统本身的系统调用并未提供合适的内存管理机制,仅仅是通过brk、sbrk等来移动堆的指针(是在操作虚拟地址,实际物理地址分配则是第一次使用的时候再和硬件交互)。但是这样就必须要求程序员自己管理每一个内存块,而ptmalloc等则直接利用brk向内存硬件申请一大片连续的内存,然后自己对这个内存进行切分,挂载形成内存池,我们之前曾模拟过tcmalloc,原理也是如此。

        比如tcmalloc就很适合多线程高并发的状态,而ptmalloc则更加全能一点,各方面都比较均衡。

        MMU是CPU内部的一个模块,他的作用就将虚拟地址转换成物理地址,即每一个线程误以为自己独享整个内存空间,而其中有一个页表缓存,用于缓解CPU和内存速度不匹配的问题。

        每一次进程切换的时候,都会把pgd的值给到MMU模块,MMU根据pgd的地址找到真实物理内存的页表,从而完成进程后续的操作。

三、用户地址空间的内存布局

(1)mm_struct

/* 包含必要的头文件 */
#include <linux/list.h>
#include <linux/rbtree.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>struct vm_area_struct;/* 定义mm_struct结构体 */
struct mm_struct {struct vm_area_struct *mmap;          /* 指向虚拟内存区域链表的指针 */struct rb_root mm_rb;                 /* 管理虚拟内存区域的红黑树根节点 */spinlock_t mmap_lock;                 /* 用于保护对mmap链表和mm_rb红黑树的并发访问 */unsigned long task_size;              /* 任务的虚拟地址空间大小 */pgd_t * pgd;                         /* 指向页全局目录(Page Global Directory)的指针 */atomic_t mm_users;                    /* 使用该地址空间的用户数(包括内核线程) */atomic_t mm_count;                    /* 地址空间的引用计数 *//* 以下字段用于标识代码段和数据段的地址范围 */unsigned long start_code, end_code, start_data, end_data;/* 堆相关地址 */unsigned long start_brk, brk;         /* 堆的起始地址和当前顶部地址 */unsigned long start_stack;           /* 栈的起始地址 *//* 用于跟踪内存分配和释放的统计信息 */struct mm_rss_stat rss_stat;/* 内存管理的其他相关字段 */struct list_head mmlist;             /* 用于将mm_struct链接到全局内存描述符链表 */struct file *core_file;              /* 指向核心转储文件的指针(如果有的话) */struct user_struct *user;            /* 指向用户结构体的指针,包含用户相关的资源限制等信息 */struct mm_struct *user_ns_exposed;   /* 指向用于用户命名空间暴露的mm_struct */struct anon_vma *root_anon_vma;      /* 用于管理匿名虚拟内存区域的根节点 */
};

        mm_struct是pcb中管理该进程的宏观结构体。他定义了堆、栈、代码段以及数据段的地址范围等,同时还维护了一个vm_area_struct链表来记录上述区域的细节。

具体如下图所示:

        注意这里vm_area_struct是一个链表指针,并非一个mm_struct中只有一个,而是每一个区域都会有,比如代码段、堆、栈、数据段都有自己的vm_area_struct

(2)vm_area_struct

struct vm_area_struct {struct mm_struct *vm_mm;             /* 指向所属的mm_struct结构体 */unsigned long vm_start;             /* 虚拟内存区域的起始地址 */unsigned long vm_end;               /* 虚拟内存区域的结束地址 */unsigned long vm_flags;             /* 内存区域的标志,如读写权限、可执行等 */struct rb_node vm_rb;               /* 用于将该vma插入到mm_rb红黑树中的节点 */union {struct list_head vm_next_share; /* 用于链接到共享该vma的链表 */struct raw_prio_tree_node prio_tree_node;};struct list_head vm_list;           /* 用于链接到mmap链表 */struct file * vm_file;              /* 如果该vma映射了文件,指向对应的文件结构体 */void * vm_private_data;             /* 私有数据指针,用于特定的内存映射场景 */struct vm_area_struct *vm_next;     /* 指向下一个vma(在链表中) */
};

        既然已经有了brk、start_stack等为什么还需要vm_area_struct这样一个结构体呢?我们看到在mm_struct中,存放的是一个vm_area_struct的链表,而非单个的vm_area_struct。

        这说明每一个区域(如堆、栈,代码段、数据段),都会有一个vm_area_struct。他就是用来精细化管理进程虚拟地址空间的结构体。我们知道不同的区域往往有着不同的属性,如可读、可写权限,以及是否和文件相关。

        同时我们可以看到其中有一个成员是rb_node类型的,他是一个将该vm_area_struct结构体插入红黑树的字段,其键值为虚拟内存区域的起始地址,利用红黑树高效的查询效率,内核可以快速定位某个虚拟地址属于哪个vm_area_struct。例如内存访问缺页中断的时候,就利用到了它。

        再比如我们平时的非法访问错误。就是在这里产生的,当程序想对一个只读区域尽心修改,内核首先会找到该区域的vm_area_struct,然后获取vm_flags标志位,得到读写权限,如果权限不对则发生错误。

http://www.xdnf.cn/news/1160605.html

相关文章:

  • C语言:20250721笔记
  • 日历类生辰八字九九三伏入梅出梅算法
  • 【用unity实现100个游戏之34】使用环状(车轮)碰撞器(Wheel Collider)从零实现一个汽车车辆物理控制系统,实现一个赛车游戏
  • PHP反序列化漏洞详解
  • 悬镜安全将受邀参加2025开放原子开源生态大会
  • 进程资源分配的安全性判断与安全序列
  • A316-Mini-V1:超小尺寸USB高清音频解码器模组技术探析
  • 基于Vue与CloudBase AI Toolkit的色觉识别Web应用开发报告:VibeCoding新范式实践
  • C#/.NET/.NET Core技术前沿周刊 | 第 47 期(2025年7.14-7.20)
  • 【前端状态更新与异步协调完全指南:React、Vue架构原理与复杂业务场景实战】
  • Django关于ListView通用视图的理解(Cursor解释)
  • RBAC(Role-Based Access Control,基于角色的访问控制)介绍(一种通过角色来管理用户权限的访问控制模型)
  • Spring Boot 集成 RabbitMQ:普通队列、延迟队列与死信队列全解析
  • 微信小程序服务端快速对接指南(java版)
  • Taro 路由相关 API 详解与实战
  • OpenCV学习(二)-二维、三维识别
  • opencv无法读取视频
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘pytest’问题
  • 金仓数据库:融合进化,智领未来——2025年数据库技术革命的深度解析
  • Spring MVC 核心工作流程
  • C/C++ 详谈结构体大小计算(内存对齐)
  • 在 Angular 应用程序中使用 Genkit 的完整指南
  • 在 Windows上用WSL和VSCode进行Linux开发环境配置
  • 【洛谷】The Blocks Problem、合并两个有序数组,补充pair(vector相关算法题p2)
  • Spring AI 集成阿里云百炼与 RAG 知识库,实现专属智能助手(框架思路)
  • 2025年终端安全管理系统的全方位解析,桌面管理软件的分析
  • Lua:小巧而强大的脚本语言,游戏与嵌入式的秘密武器
  • 智能体性能优化:延迟、吞吐量与成本控制
  • “融合进化,智领未来”电科金仓引领数字化转型新纪元
  • 前端JavaScript进阶