欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

通过Rust编写操作系统之内存的分页与管理介绍(上)

来源:本站整理 作者:佚名 时间:2019-07-31 TAG: 我要投稿

Rust是一门系统编程语言,专注于安全,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言。Rust在语法上和C++类似,但是设计者想要在保证性能的同时提供更好的内存安全。 Rust最初是由Mozilla研究院的Graydon Hoare设计创造,然后在Dave Herman, Brendan Eich以及很多其他人的贡献下逐步完善的。 Rust的设计者们通过在研发Servo网站浏览器布局引擎过程中积累的经验优化了Rust语言和Rust编译器。
Rust编译器是在MIT License 和 Apache License 2.0双重协议声明下的免费开源软件。 Rust已经连续三年(2016,2017,2018)在Stack Overflow开发者调查的“最受喜爱编程语言”评选项目中折取桂冠。
本文介绍了内存分页技术,这是一种非常常见的内存管理方案,我们也将该技术用于通过 Rust 编写操作系统中。内存分页技术解释了为什么需要内存隔离、分段如何工作、虚拟内存是什么以及分页如何解决内存碎片(memory fragmentation)问题。另外,本文还探讨了x86_64体系结构上的多级页表布局情况,本文的完整源代码可以在GitHub 的post-08主题中找到。
内存保护
操作系统的一个主要任务是将程序彼此隔离。例如,web浏览器不应该干扰文本编辑器。为了实现这个目标,操作系统利用硬件功能来确保一个进程的内存区域不被其他进程访问。根据硬件和操作系统实现的不同,有不同的方法。
例如,一些ARM Cortex-M处理器(用于嵌入式系统)有一个内存保护单元(MPU),它允许你定义少量具有不同访问权限(例如无访问权限、只读限、写入权限)的内存区域。在每次内存访问时,MPU都会确保该地址位于具有正确访问权限的区域,否则发出异常警报。通过更改每个进程切换(process switch)上的区域和访问权限,操作系统可以确保每个进程只访问自己的内存,从而将进程彼此隔离。
在x86上,硬件支持两种不同的内存保护方法:分段和分页。
分段
分段技术早在1978年就已经被开发出来了,最初是为了增加可寻址内存的数量。当时的情况是cpu只使用16位地址,这将可寻址内存的数量限制为64KiB。为了使更多的64KiB可访问,就需要引入额外的段寄存器,每个段寄存器包含一个偏移地址。CPU会在每次内存访问时自动添加这个偏移量,以便可访问高达1MiB的内存。
段寄存器由CPU根据内存访问的类型自动选择,比如获取指令使用代码段CS,而堆栈操作(push/pop)则使用堆栈段SS。其他指令使用数据段DS或额外段ES。后来,又增加了两个可以自由使用的段寄存器FS和GS。
在第一版的分段技术中,段寄存器直接包含偏移量,不执行访问控制。后来,随着保护模式的引入,这种情况发生了改变。当CPU以此模式运行时,段描述符包含本地或全局描述符表的索引,该表除了包含偏移地址外,还包含段大小和访问权限。通过为每个进程加载单独的全局或本地描述符表,将内存访问限制在进程自己的内存区域,操作系统可以将进程彼此隔离。
通过在实际访问之前修改内存地址,分段技术已经使用了一种几乎无处不在的技术——虚拟内存。
虚拟内存
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。
Windows 8/8.1 操作系统如出现开机时卡在Windows徽标页面,无法进入系统,必须强制关机再重启才能打开时,可适当调整虚拟内存设置解决。
归根结底,虚拟内存背后的思想是从底层物理存储设备抽象出内存地址。首先执行转换步骤,而不是直接访问存储设备。对于分段来说,转换步骤是添加活动段的偏移地址。假设一个程序在偏移量0x1111000的段中访问内存地址0x1234000,则经过转换,实际访问的地址是0x2345000。
为了区分这两种地址类型,转换前的地址称为虚拟地址,转换后的地址称为物理地址。这两种地址的一个重要区别是,物理地址是惟一的,并且总是指向相同的、不同的内存位置。另一方面,虚拟地址依赖于转换功能。所以很有可能,两个不同的虚拟地址完全有可能指向同一个物理地址。同样,相同的虚拟地址在使用不同的转换功能时可以引用不同的物理地址。
如下所示,使用这个属性的一个示例是,并行运行相同的程序两次:

在这个示例中,相同的程序运行两次,但却使用了不同的转换功能。第一个示例的段偏移量为100,因此它的虚拟地址0-150被转换为物理地址100 – 250。第二个示例的段偏移量为300,因此它的虚拟地址0-150被转换为物理地址300 – 450。这允许两个程序运行相同的代码并使用相同的虚拟地址,但不会相互干扰。
另一个优点是,程序现在可以放在任意物理内存位置,即使它们使用完全不同的虚拟地址。因此,操作系统

[1] [2] [3]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载