【Linux】再谈虚拟地址空间

news2024/11/24 3:19:30

前言

虚拟地址空间对于理解操作系统的许多概念是很有帮助的,这里我们对虚拟地址空间进行更加深入理解,如果以前没有看过对于虚拟地址空间的初级介绍的话,可以先看这里《虚拟地址空间》

再谈虚拟地址空间

  • 一、页表难道真的只是简单一 一存储映射吗?
  • 二、内存与磁盘IO时是逐个字节进行IO吗?
  • 三、页表的存储和转化原理
  • 四、补充

一、页表难道真的只是简单一 一存储映射吗?


我们知道虚拟地址空间的基本单位是字节,所以在32位平台下虚拟地址空间上会有多少个地址呢?

答案是: 2 32 2^{32} 232个!虚拟地址空间中的每一个地址依次为 [ 0 , 2 32 − 1 ] [ 0 , 2 ^{32} − 1 ] [0,2321] 即 0x00000000 - 0xFFFFFFFF,也就是我们常说的 4 GB 虚拟内存空间。

在这里插入图片描述

为了让虚拟地址与物理地址能够一 一映射,我们需要有页表来维护映射关系,为了后续方便维护页表我们先来计算一下页表的大小:虚拟地址4个字节,物理地址4字节,假设其他属性4字节,虚拟地址总数 2 32 2^{32} 232个。

2 32 ∗ ( 4 + 4 + 4 ) b y t e = 50 , 331 , 648 K B = 49 , 152 M B = 48 G B > 4 G B 2^{32} * (4 + 4 + 4) byte = 50,331,648KB = 49,152MB = 48GB > 4GB 232(4+4+4)byte=50,331,648KB=49,152MB=48GB>4GB

经过计算我们发现如果我们要维护页表,我们需要有48GB的内存,但是在32位平台下我们的CPU最多只能控制4GB的内存,这说明页表绝对不是简单的一 一存储映射!

为了搞清楚页表的存储和映射规则我们还要了解文件系统方面的知识,如果你没有这方面的知识的话可以先看这里的的一些介绍《【Linux】文件系统》


二、内存与磁盘IO时是逐个字节进行IO吗?


由于磁盘在存储时是按照数据块的方式进行存储的所以注定了文件在磁盘的时候,就是以块为单位进行存储的(一个块的大小一般是4KB即8个扇区的大小,其具体大小OS有关)

所以OS在和磁盘这样的设备进行IO交互的时候,就不能按照字节为单位的而是要按照为单位。

  1. 其实如果非要OS在和磁盘这样的设备进行IO交互的时候设定单位为字节也是可以的,但是这回导致过多的IO,过多的IO注定了过多的寻址,过多的寻址意味着过多的机械运动 ,由于磁盘本身就是一个机械设备效率低下,过多的IO会导致效率更加低下。

  2. 如果将IO的单位设定的过大,又会导致磁盘不能被有效的利用,而且数据加载不是IO单位的整倍数时会迁移更多的无关数据。

为了让内存与与磁盘更高效地进行IO,操作系统对内存也进行了按管理划分,OS将内存划分成一个个页框,其中每个页框可以存储的数据的大小为4KB,这4KB被称为一页 (Page)的数据。

为了管理内存的每个页框Linux系统中有一种数据结构struct page,由于struct page结构本身就占有一定内存,如果struct page结构设计过大,那么本身就会占用较多内存,而给系统或者用户可用的内存就较少,所以strcut page对结构大小非常敏感,即使增加一个字节对系统影响也会非常大,故Linux社区对struct page的结构做了严格设计,不会轻易增加字段。

page结构中有一个非常重要的字段叫flag通过这个字段可以判断当前内存块有没有被占用,最后Linux使用数组将所有的page管理起来struct page mm[1,048,576]

在这里插入图片描述

内存管理的本质:将磁盘中的特定的4KB的数据块(数据内容)放入到哪一个物理内存的页框中(数据保存的空间)


局部性原理的特性的一些理解
根据局部性原理,我们允许计算机提前加载正在访问的数据的相邻或者附近的数据,通过预先加载要访问数据的附近的数据可以减少未来的IO次数。

假设我们使用一个10KB的文件,那么我们需要加载3个数据块,意味着我们使用该文件时在内存中会多加载数据,这部分多加载出来的数据的本质就叫:做数据的预加载! 所以我们没有必要花费心思去处理多加载进内存的数据。


三、页表的存储和转化原理


以32位操作系统为例,虚拟地址其实并不是被整体使用的,而是按照 10 + 10 + 12 10 + 10 + 12 10+10+12的方式进行划分使用的。页表也不仅仅只有一个而是多个而且是分级别的。

虚拟地址的前10位被存放进入页目录里面,再向后10位被存放进页表项里面,经过页目录可以找到页表项,经过页表项可以找到物理内存中的页框的起始地址,页框的起始地址 + 虚拟地址最低12位的比特位既可以找到真正的物理地址

最低12位比特位可以表示的数据范围是: [ 0 , 4095 ] [0, 4095] [0,4095],而页框内的可用地址总数为: 4096 4096 4096(4KB) ,于是通过页框起始地址 + 页内偏移就可以访问到一个页框内的所有地址,所有页框按照同样的操作便能找到所有的地址,这种寻址方式被称为:基地址+偏移量的方式。

在这里插入图片描述

这时我们再计算一下页目录的大小:页目录总数为1,目录里面的行数: 2 10 2^{10} 210 ,假设虚拟地址前10个比特位存储需要4个字节,指向页表项的指针也是4字节。

1 ∗ 2 10 ∗ ( 4 + 4 ) b y t e = 8 K B 1*2^{10}* (4 + 4) byte= 8KB 1210(4+4)byte=8KB

这时我们再进行计算页表项的大小:页表项总数为 2 10 2^{10} 210,目录里面的行数: 2 10 2^{10} 210 ,假设虚拟地址再向后10个比特位存储需要4个字节,指向页框的指针也是4字节。

2 10 ∗ 2 10 ∗ ( 4 + 4 ) b y t e = 8 M B 2^{10} * 2^{10}* (4 + 4) byte= 8MB 210210(4+4)byte=8MB

所以我们使用8MB的空间就能完成映射功能!

最后页表并不是直接全部创建的,而是根据需要进行创建多少页表,如果页表不够再进行新增。


我们实际在申请malloc内存的时候,OS只要给你在虚拟地址空间上申请就行了,当你在真正访问时,0S发现虚拟地址并没没有真正建立映射,于是触发缺页中断,执行中断处理方法才会自动给你申请具体的物理内存并且填充页表。

四、补充


此外页表的属性是有很多的,例如是否命中,读写权限,内核级/用户级权限等,这些权限也是相当有用的信息。
在这里插入图片描述

例如:修改常量字符串为什么会触发段错误?

答案是:指针变量里面保存的是指向的字符的虚拟起始地址,指针变量寻址的时候,必定会伴随虚拟到物理的转化,通过MMU + 查页表的方式 ,对你的操作进行权限审查,发现你虽然能找到,但是你进行的操作是非法的,MMU发生异常,OS识别异常,异常转换成信号,发送给目标进程,进程在从内核转换成为用户态的时候,进行信号处理,然后终止进程。

我们讲解原理采用的是32位操作系统进行讲解的,对于64位操作系统也是同理,64位平台下用的是多级页表来进行更多地址的映射

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

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

相关文章

Arduino 入门学习笔记11 读写内置EEPROM

Arduino 入门学习笔记11 使用I2C读写EEPROM 一、Arduino 内置EEPROM介绍二、EEPROM 操作1. 包含EEPROM库:2. 写入数据到EEPROM:3. 从EEPROM读取数据4. 完整示例: 一、Arduino 内置EEPROM介绍 Arduino的内置EEPROM(Electrically E…

iptables四表五链

iptables四表五链 iptables传输数据包的过程 当一个数据包进入网卡时,它首先进入PREROUTING链,内核根据数据包目的IP判断是否是发往本机的。如果数据包就是进入本机的,它就会沿着图向下移动到INPUT链。数据包到了INPUT链后,任何进…

Identity Server 4 传参数到登录界面

Identity Server 4 传参数到登录界面 登录界面取得参数

【C# 基础精讲】文件流和文本处理

文件流是C#中用于进行文件读写操作的重要概念,它提供了一种逐字节或逐块访问文件内容的机制。文本处理则是指在读取和写入文件时,对文本数据进行解析、操作和转换的过程。在本文中,我们将深入探讨文件流的概念、种类以及使用方法,…

0基础学Python之从第一个Python程序开始聊起

一、python的安装 由于python语言有着大量优秀的函数包,所以为了下载的便利性,我是在外网的笔记本上部署了python的学习环境。 Python Release Python 3.11.4 | Python.org 复制链接,迅雷下载,速度喜人。 下载后一路click&…

人类反馈强化学习RLHF;微软应用商店推出AI摘要功能

🦉 AI新闻 🚀 微软应用商店推出AI摘要功能,快速总结用户对App的评价 摘要:微软应用商店正式推出了AI摘要功能,该功能能够将数千条在线评论总结成一段精练的文字,为用户选择和下载新应用和游戏提供参考。该…

FPGA_学习_16_IP核_ROM

在寻找APD最合适的偏压的过程中,一般会用到厂商提供一条曲线,横坐标是温度的变化,纵坐标表示击穿偏压的变化,但每个产品真正的击穿偏压是有差异的。 为了能够快速的找到当前温度下真实的击穿偏压,我们可以这样做&#…

C++之std::unordered_map<int, int, string>应用实例(一百八十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

小程序化,一种创新的HybirdApp开发模式

跨端框架的出现,弥补了传统移动应用开发中跨平台难题。开发者可以使用一套代码构建适用于多个平台的应用,既能在不同设备上保持一致的用户体验,又能更高效地进行开发和维护。这种开发模式不仅提升了开发效率,还为用户提供了更加一…

【K8S系列】Weave Net 故障排除的常见问题和解决方案

写在前面 当使用 Weave Net 进行容器网络配置时,可能会遇到一些常见的故障情况。以下是一些常见问题及其解决方案: 问题列表 1 节点无法加入 Weave Net 网络 解决方案 检查节点之间的网络连通性,确保可以通过 IP 地址相互访问。 检查节点的…

nodejs安装与卸载(高版本降为低版本)

初到公司发现电脑上面已经安装nodejs,但是版本是最新版本。但是问题来了,好像是不太支持vue3,所以查了一些资料,具体的也不是很清楚,反正就是nodejs的版本不能太高最好保持在16以下。好吧,那就重新卸载再来…

苹果手机怎么连接电脑?4招轻松连接!

“新买了一部苹果手机,想连接电脑传一些文件,但是不知道该如何操作。有没有朋友可以帮帮我呀?” 苹果手机作为一款智能手机,在市场上的应用越来越常见。苹果手机与电脑进行连接可以更好的进行文件的传输、备份以及进行其他操作。 …

FreeModbus——源码获取(一)

网站 About - Embedded Experts (embedded-experts.at) 下载v1.6版本,刚开始我还没找到,后面对照别人的截图才找到(哈哈,感觉自己好二),把鼠标移过去,这个地方是才从黑变成这个绿色

基于X86六轮差速移动机器人运动控制器设计与实现(二)规划控制算法

带输入约束的 MPC 路径跟踪控制 MPC 算法是一种基于控制对象模型的控制方法,其优势在于在控制中考虑了 系统的多种物理约束,同时基于模型与当前机器人的反馈信息预估出未来机器人 位姿信息的处理方法可以解决控制迟滞的问题。 4.1 MPC 路径跟踪控…

压多少抗多少,滴滴全链路压测仿真度量体系建设

滴滴在重大节假日、活动前为保障线上系统稳定,需要通过全链路压测做多轮风险排查以及容量验收,我们经常听到这样的声音"你们全链路压测和线上业务场景有多大差异"、"是不是压测达到目标线上真的能抗这么大量"、"我的某某个模块…

iPhone15即将发布,苹果赔偿5亿美元,但再次不包括中国用户

苹果的iPhone15即将发布,就在此时苹果的“电池门”再次被翻出,这次美国的法院判决苹果给每名用户赔偿65美元,合计大约5亿美元,只是独独不包括中国用户,这就有点歧视中国用户了吧? 事件的起因在于2017年很多…

c++11 标准模板(STL)(std::basic_stringbuf)(六)

定义于头文件 <sstream> template< class CharT, class Traits std::char_traits<CharT>, class Allocator std::allocator<CharT> > class basic_stringbuf : public std::basic_streambuf<CharT, Traits> std::basic_stringbu…

C++新经典02--编译预处理

编译预处理 编译阶段会做如下几件事&#xff1a; (1)预处理。 (2)编译。包括词法分析、语法分析、目标代码生成、优化等。 (3)汇编。产生.o(.obj)目标文件。 C语言一般提供三种预处理功能&#xff1a;宏定义、 文件包含、条件编译。这三种预处理功能也是通过在源程序文件写入…

5G智能网关助力打造数字乡村物联网

乡村振兴&#xff0c;网络先行&#xff0c;信息通信技术赋能农业农村现代化发展的作用日益彰显&#xff0c;也成为实施乡村振兴战略的重要力量。 截止今年三月&#xff0c;我国5G网络已经覆盖全国所有地级市、县城城区及数万行政村&#xff0c;农村光纤平均下载速率超过100Mb/s…

C#之枚举中的按位与()按位或(|)。

一些基础定义&#xff1a; 按位或运算符&#xff08;|&#xff09;是一种位运算符&#xff0c;用来对两个二进制数进行操作。对于每个位上的1&#xff0c;如果至少有一个二进制数中的对应位为1&#xff0c;则结果为1&#xff1b;否则&#xff0c;结果为0。按位与运算符&#x…