Linux操作系统之线程:分页式存储管理

目录

前言:

一、分页式存储管理

二、二级页表的地址转化

三、缺页中断

总结


前言:

我们上篇文章简单介绍了线程的一些知识点,但是还有很多坑没有给大家填上,包括页表部分我们还没为大家说明。

本篇文章我将会继续为大家讲解线程的有关内容,希望对大家有所帮助。

一、分页式存储管理

我们今天先继续谈论关于分页式存储的话题。

首先就是帮助大家深入的了解页表。

我们之前在学习进程PCB的时候就已经接触到了页表,在上文我们也曾提到过:在分页式存储管理中,虚拟地址空间被划分为固定大小的页(Page)(通常为4KB),而物理内存则被划分为相同大小的页框(Page Frame)。操作系统通过页表(Page Table)建立虚拟页到物理页框的映射关系,使得进程可以透明地访问物理内存。

我们的每一个进程都有自己的页表结构,这是大家之前就知道的。但是这个页表结构具体是什么样的呢?

我们之前只说了页表负责存储虚拟地址空间到物理地址的映射关系,但是页表具体怎么存储的呢?

在32位系统中,虚拟空间的最大空间是4GB,这是每一个用户程序都拥有的虚拟内存空间。既然需要让4GB的虚拟内存全部可用,那么页表中就需要能够表示所4GB空间的表项数量,也就是4GB/4KB=1048576个表项,如下图所示:

但是在32位系统中,地址的长度是4个字节(4B),那么页表中的每一个表项就是占用4个字节,所以页表占据的总空间就是4MB的大小,也就是说映射表自己本身,就要占用4MB/4KB=1024个物理页,这样会存在哪些问题呢?
回想一下,我们当初为什么要使用页表,要使用虚拟内存空间。
因为我们的物理地址是碎片化的,我们需要将进程划分为一个个页,可以不用连续的存放在物理内存中。
但是此时你一个页表就需要1024个连续的页框,这是不是和当时的目标背道而驰了?
此外,其实很多进程在一段时间内只需要访问某几个页就可以正常运行了。因此我们没有毕业一次让所有的物理页都常驻内存。
解决需要大容量页表的最好方法是:把页表看成普通的文件,对他进行离散分配,即对页表在分页,由此形成多级页表的思想。
为了解决这个问题,我们可以把这个单一页表拆分为1024个体积更小的映射表。这样一来,1024(每个表中的表项个数)*1024(表的个数),仍然可以覆盖4GB的物理内存空间。
即:
  • 将原1M个条目的单级页表拆分为 1024个小页表(每个小页表存储1024个条目,占4KB)。

  • 新增一个页目录(Page Directory),包含1024个条目,每个条目指向一个小页表。

  • 总容量不变:1024小页表×1024条目/页表=1M1024小页表​×1024条目/页表​=1M条目,仍可覆盖4GB空间。

 

 

页目录表就是用来负责管理小页表的结构。所有小页表的物理地址被页目录表项指向,而页目录的物理地址被CR3寄存器指向,这个寄存器中,保存了当前正在执行任务的页目录地址。

所以操作系统在加载用户程序时,不仅仅需要为程序内容来分配物理地址,还需要为用来保存程序的页目录和页表分配物理地址哦!!


二、二级页表的地址转化

事实上,20位可寻址1M个页框 × 4KB = 4GB,与32位地址空间上限一致。并且物理页框的基址必须是4KB的整数倍(即低12位全为0),因此存储物理地址时无需记录低12位,硬件会自动在拼接时补零。如0x123 → 物理页框基址 = 0x123000。

所以我们如果把二级页表的32位全部用来存储地址,会造成浪费。于是,我们的二级页表的32位的前20位才是存储的物理地址,而后面12位,存储的是页偏移。

什么意思呢?就是对我们32位的虚拟地址来说,我们可以把这32个数字划分为三段。

第一段1-10位,表示的是这个虚拟地址代表的页目录,2^10次方刚好就是1024个页目录项。

第二段11-20位,这个是在找到了页目录项的基础上,找到这个页目录项上面的页表项。

第三段21-32位,表示的是偏移量,我们最后结合这个偏移量找到物理地址:

以0000000000 1111111110 111111111111为例:

 我们32位的物理地址也是差不多的理由,只不过是划分了两段。

第一段1-20位表示物理页框号,第二段21-32位表示标志位,包括读写权限这些。


在CPU内部,有一个叫做MMU的硬件电路。以上其实就是MMU的工作流程,他的速度很快,主要工作还是进行内存管理,地址转化只是他承接的任务之一。

然而还有一个问题,MMU要先进行两次页表查询确定物理地址,在确定了权限等问题之后,MMU再将这个物理地址发送给总线,内存收到之后开始读取对应的地址的数据并返回。那么当页表变为N级的时候,就变成了N次检索加1次读写。可见,页表的级数越多,他所花费的步骤越多,那么对于CPU来说,等待的时间也就越长。

(总线是计算机系统中用于在各部件之间传输数据、地址和控制信号的 公共通信通道。它相当于计算机的“神经系统”,负责连接CPU、内存、I/O设备等组件,确保它们能高效协同工作)

所以多级页表是一个双刃剑,在减少连续存储要求且减少存储空间的同时降低了查询效率(以时间换取空间) 

有没有提升效率的办法呢?
计算机科学中的所有问题都能通过加一个中间层解决,MMU就引入了一个新武器:TLB,江湖人称快表。
这个TLB,实际上就是一个缓存,类似于Redis,都是通过缓存高频访问的数据来加速性能。
当CPU发出虚拟地址时,MMU首先查询TLB——若命中(TLB Hit),直接返回物理地址,省去访问页表的开销 ;若未命中,查询页表(触发多级页表遍历),并且还会把这个未命中的映射关系传给TLB让它记录下来方便下一次。

三、缺页中断

操作系统采用了按需分配的惰性策略,进程的虚拟地址空间虽然理论上覆盖整个范围(如32位系统的4GB),但实际仅对当前使用的区域初始化页表映射。(因为我们之前说过进程运行只需要几张物理页就行),如果我们把映射关系全部初始化,会浪费大量内存存储未使用的页表项。所以,当我们CPU给MMU的虚拟地址,在TLB与页表都没找到对应的物理页,该怎么办呢?

这个时候,就想到我们之前说过的延时分配机制,这个我们在讲进程的写实拷贝与动态内存管理申请空间时也提到过一点。比如在动态内存分配(malloc)时,操作系统并不会立即分配实际的物理页,而是等到程序首次访问这块内存时才通过缺页中断来真正分配;又如在 fork() 创建子进程时,父子进程共享相同的物理页,只有当某个进程尝试写入时,才会触发缺页中断并执行真正的页面复制。

写实拷贝真实是怎么做到的呢?原因是什么呢?

就是因为映射关系在页表上并未全部给你加载到内存上(虽然所有的映射关系早就初始化了),当程序首次访问未分配的堆内存、文件映射区域或换出到磁盘的页面时, MMU 在页表项中发现"存在位"(Present Bit)为0时,表明该虚拟页要么尚未关联物理页,要么对应的数据还未加载到内存中(可能被换出到交换空间)。这时,作为 CPU 一部分的 MMU 就会触发一个特殊的软中断,将控制权交给操作系统的缺页处理程序。内核会根据不同的缺页原因采取相应措施:对于未分配的页面会分配新的物理页;对于被换出的页面会从磁盘换回;对于权限不足的访问则会抛出段错误。处理完成后,操作系统会更新页表映射,并让 CPU 重新执行引发缺页的指令。

这个中断,就叫做缺页中断(缺页异常)。

正是通过缺页中断这个桥梁,现代操作系统才能如此优雅地实现虚拟内存管理,让每个进程都"错觉"自己独占了整个地址空间,而实际上物理内存资源在被所有进程高效共享。


总结

计算机系统的内存管理是一个环环相扣的精妙体系。当进程运行时,它看到的是一个连续的虚拟地址空间(32位系统为4GB),这个设计抽象了物理内存的碎片化问题。但虚拟地址必须转换为真实的物理地址才能访问内存,这个转换过程通过页表(Page Table)实现,而页表本身也存储在物理内存中。

而我们为了高效管理这个转换过程,采用多级页表结构(如x86的两级页表)。第一级是页目录,存储1024个页目录项(PDE),每个PDE指向一个页表;第二级页表存储1024个页表项,每个PTE最终指向4KB的物理页框。这种层级结构通过虚拟地址的10-10-12分拆实现:高10位定位页目录项,中间10位定位页表项,低12位作为页内偏移。

地址转换时,MMU首先查询TLB快表(缓存结构),若未命中则需遍历页表。为提升效率,操作系统采用按需分配策略:不会为整个4GB空间初始化页表,而是仅维护当前活跃区域的映射。当访问未映射的区域时,MMU发现页表项中"存在位"(Present Bit)为0,触发缺页异常

缺页处理程序会根据不同情况采取行动:

  1. 若是首次访问的堆内存(如malloc分配),则分配物理页并建立映射

  2. 若是被换出的页面,则从交换空间换入

  3. 若是写时复制(COW)场景,则复制物理页并更新映射

这种机制与物理内存管理紧密耦合:操作系统通过伙伴系统管理物理页框分配,通过页缓存加速磁盘数据读取。

希望对大家有所帮助。

明天我们将重新讲回线程的知识点,这个知识点时讲到线程了顺带引出的,但也很重要!!! 

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

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

相关文章

xss1-8

Level-1<script>alert()</script>基础反射型 无任何过滤Level-2"> <script>alert()</script> <"闭合属性&#xff1a;">用来闭合当前标签的value属性注入新标签&#xff1a;闭合属性后&#xff0c;插入独立的<script>…

51c嵌入式~单片机~合集1

自己的原文哦~ https://blog.51cto.com/whaosoft/11897656 一、STM32的启动模式配置与应用 三种BOOT模式 所谓启动&#xff0c;一般来说就是指我们下好程序后&#xff0c;重启芯片时&#xff0c;SYSCLK的第4个上升沿&#xff0c;BOOT引脚的值将被锁存。用户可以通过设…

Typecho分类导航栏开发指南:从基础到高级实现

文章目录 Typecho分类导航栏深度解析:父分类与子分类的完美呈现 引言 一、Typecho分类系统基础 1.1 Typecho分类结构 1.2 获取分类数据的基本方法 二、基础分类导航输出 2.1 简单的平铺式导航 2.2 带计数器的分类导航 三、层级分类导航实现 3.1 递归输出父子分类 3.2 使用Type…

C++异步编程工具 async promise-future packaged_task等

深入探讨 C11 中引入的四个核心异步编程工具&#xff1a;std::async, std::future, std::promise, 和 std::packaged_task。它们共同构成了 C 现代并发编程的基础。 为了更好地理解&#xff0c;我们可以使用一个餐厅点餐的类比&#xff1a; std::future (取餐凭证)&#xff1…

Linux-网络管理

网络管理1. 网络基础1.1 TCP/IP 协议栈&#xff08;四层模型&#xff09;1.2 网络设备配置与基础概念1.3 网络接口命名规则1.4 网络配置文件位置2. 常用网络配置命令2.1 查看网络接口信息2.2 配置 IP 地址2.3 启用/禁用网卡2.4 修改网卡 MAC 地址2.5 配置网卡的 MTU&#xff08…

Linux锁的概念及线程同步

目录 1.常见锁概念 死锁 死锁四个必要条件 避免死锁 避免死锁算法 2. Linux线程同步 条件变量 同步概念与竞态条件 条件变量函数 初始化 销毁 等待条件满足 唤醒等待 简单案例&#xff1a; 条件变量使用规范 1.常见锁概念 死锁 死锁是指在一组进程中的各个进程均占有不会释放的…

docker更换国内加速器-更换华为加速器2025-717亲测可用docker 拉取镜像出错

[rootlocalhost ~]# docker pull nginx Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)报错原因就是…

Unity VR多人手术模拟恢复2:客户端移动同步问题分析与解决方案

Unity VR多人手术模拟恢复2&#xff1a;客户端移动同步问题分析与解决方案 &#x1f3af; 问题背景 在开发基于Unity Mirror网络架构的VR多人手术模拟系统时&#xff0c;我们遇到了一个复杂的客户端移动同步问题&#xff1a; 主要操作者&#xff08;第一个客户端&#xff09;&a…

uni-app开发的页面跳转全局加载中

uni-app开发的页面跳转全局加载中首先需要下载插件创建加载中页面组件app.vue页面中监听跳转首先需要下载插件 https://ext.dcloud.net.cn/plugin?id20613 创建加载中页面组件 <!-- 全局自定义加载中 --> <template><view v-if"visible" class&qu…

XXE漏洞4-XXE无回显文件读取-PentesterLab靶场搭建

一.PentesterLab靶场搭建(实验环境搭建)介绍&#xff1a;PentesterLab 是一个全面的漏洞演示平台&#xff0c;但是它是收费的&#xff0c;我们这里只使用它的 xxe 演示案例。安装 PentesterLab 虚拟机:下载好镜像&#xff1a; 1.打开VMware新建虚拟机&#xff0c;选择典型就行。…

【机器学习】图片分类中增强常用方式详解以及效果展示

图片增强常用方式详解 引言 图片数据的质量和多样性对模型的训练效果起着至关重要的作用。然而&#xff0c;实际获取的图片数据往往存在数量不足、分布不均衡等问题。图片增强技术应运而生&#xff0c;它通过对原始图片进行一系列变换&#xff0c;生成更多具有多样性的图片&…

【URL 转换为PDF】HTML转换为PDF

1、方法1 pdfkit 安装依赖 # 安装 wkhtmltopdf&#xff08;系统级&#xff09; # Ubuntu/Debian sudo apt install wkhtmltopdf# macOS brew install wkhtmltopdf# Windows 下载安装&#xff1a;https://wkhtmltopdf.org/downloads.html# 安装 Python 库 pip install pdfkitimp…

单链表的定义、插入和删除

一、定义一个单链表 struct LNode{ //定义单链表节点类型ElemType data; //存放节点数据元素struct LNode *next; //指针指向下一个结点 }; //增加一个新节点&#xff1a;在内存中申请一个结点所需空间&#xff0c;并用指针p指向这个结点 struct LNode * p (struc…

Nextjs官方文档异疑惑

第一个区别&#xff1a;不同的页面对应的路由器设定&#xff01; 继续用 app 路由器&#xff08;推荐&#xff0c;Next.js 未来主流&#xff09; 路由规则&#xff1a;app 目录下&#xff0c;文件夹 page.tsx 对应路由。例如&#xff1a; app/page.tsx → 对应 / 路由&#xf…

突破AI模型访问的“光标牢笼”:长上下文处理与智能环境隔离实战

> 当AI模型面对浩瀚文档却只能处理零星片段,当关键信息散落各处而模型“视而不见”,我们该如何打破这堵无形的墙? 在自然语言处理领域,**输入长度限制**(常被称为“光标区域限制”)如同一个无形的牢笼,严重制约了大型语言模型(LLM)在真实场景中的应用潜力。无论是分…

AI 智能质检系统在汽车制造企业的应用​

某知名汽车制造企业在其庞大且复杂的生产流程中&#xff0c;正面临着棘手的汽车零部件质检难题。传统的人工质检方式&#xff0c;完全依赖人工的肉眼观察与简单工具测量。质检员们长时间处于高强度的工作状态&#xff0c;精神高度集中&#xff0c;即便如此&#xff0c;由于人工…

设计模式》》门面模式 适配器模式 区别

// 复杂子系统 class CPU {start() { console.log("CPU启动"); } } class Memory {load() { console.log("内存加载"); } } class HardDrive {read() { console.log("硬盘读取"); } }// 门面 class ComputerFacade {constructor() {this.cpu ne…

windows内核研究(驱动开发 第一个驱动程序和调试环境搭建)

驱动开发 第一个驱动程序 驱动的开发流程 1.编写代码 -> 生成.sys文件 -> 部署 -> 启动 -> 停止 ->卸载 // 编写我们的第一个驱动程序 #include<ntddk.h>// 卸载函数 VOID DrvUnload(PDRIVER_OBJECT DriverObject) {DbgPrint("我被卸载了\n"…

ABP VNext + 多级缓存架构:本地 + Redis + CDN

ABP VNext 多级缓存架构&#xff1a;本地 Redis CDN &#x1f4da; 目录ABP VNext 多级缓存架构&#xff1a;本地 Redis CDN一、引言 &#x1f680;二、环境与依赖 &#x1f6e0;️三、架构概览 &#x1f310;请求全链路示意 &#x1f6e3;️四、本地内存缓存层 &#x1…

RGBA图片格式转换为RGB格式(解决convert转换的失真问题)

使用convert转换的问题 OpenCV 的 cv2.cvtColor(…, cv2.COLOR_BGRA2GRAY) 会直接忽略 Alpha 通道的含义&#xff0c;将它当作第四个颜色通道来处理。 转换公式如下&#xff1a; gray 0.114*255 0.587*0 0.299*0 ≈ 29也就是说&#xff0c;即使 Alpha 为 0&#xff08;完全透…