XV6源码阅读——进程地址空间

2024-04-25 02:20

本文主要是介绍XV6源码阅读——进程地址空间,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 页表
  • 实际情况


前言

一个本硕双非的小菜鸡,备战24年秋招。打算尝试6.S081,将它的Lab逐一实现,并记录期间心酸历程。
代码下载

官方网站:6.S081官方网站

页表

每个进程都有一个单独的页表,当xv6在进程之间切换时,也会更改页表。如图2.3所示,一个进程的用户内存从虚拟地址零开始,可以增长到MAXVA (kernel/riscv.h:348),原则上允许一个进程内存寻址空间为256G。

在这里插入图片描述
当进程向xv6请求更多的用户内存时,xv6首先使用kalloc来分配物理页面。然后,它将PTE添加到进程的页表中,指向新的物理页面。Xv6在这些PTE中设置PTE_W、PTE_X、PTE_R、PTE_U和PTE_V标志。大多数进程不使用整个用户地址空间;xv6在未使用的PTE中留空PTE_V。

我们在这里看到了一些使用页表的很好的例子。首先,不同进程的页表将用户地址转换为物理内存的不同页面,这样每个进程都拥有私有内存。第二,每个进程看到的自己的内存空间都是以0地址起始的连续虚拟地址,而进程的物理内存可以是非连续的。第三,内核在用户地址空间的顶部映射一个带有蹦床(trampoline)代码的页面,这样在所有地址空间都可以看到一个单独的物理内存页面。

图3.4更详细地显示了xv6中执行态进程的用户内存布局。栈是单独一个页面,显示的是由exec创建后的初始内容。包含命令行参数的字符串以及指向它们的指针数组位于栈的最顶部。再往下是允许程序在main处开始启动的值(即main的地址、argc、argv),这些值产生的效果就像刚刚调用了main(argc, argv)一样。
在这里插入图片描述
为了检测用户栈是否溢出了所分配栈内存,xv6在栈正下方放置了一个无效的保护页(guard page)。如果用户栈溢出并且进程试图使用栈下方的地址,那么由于映射无效(PTE_V为0)硬件将生成一个页面故障异常。当用户栈溢出时,实际的操作系统可能会自动为其分配更多内存。

XV6使用进程的页表,不仅是告诉硬件如何映射用户虚拟地址,也是明晰哪一个物理页面已经被分配给该进程的唯一记录。这就是为什么释放用户内存(在uvmunmap中)需要检查用户页表的原因。

实际情况

像大多数操作系统一样,xv6使用分页硬件进行内存保护和映射。大多数操作系统通过结合分页和页面故障异常使用分页,比xv6复杂得多,我们将在第4章讨论这一点。

内核通过使用虚拟地址和物理地址之间的直接映射,以及假设在地址0x8000000处有物理RAM (内核期望加载的位置) ,Xv6得到了简化。这在QEMU中很有效,但在实际硬件上却是个坏主意;实际硬件将RAM和设备置于不可预测的物理地址,因此(例如)在xv6期望能够存储内核的0x8000000地址处可能没有RAM。更严肃的内核设计利用页表将任意硬件物理内存布局转换为可预测的内核虚拟地址布局。

RISC-V支持物理地址级别的保护,但xv6没有使用这个特性。

在有大量内存的机器上,使用RISC-V对“超级页面”的支持可能很有意义。而当物理内存较小时,小页面更有用,这样可以以精细的粒度向磁盘分配和输出页面。例如,如果一个程序只使用8KB内存,给它一个4MB的物理内存超级页面是浪费。在有大量内存的机器上,较大的页面是有意义的,并且可以减少页表操作的开销。

xv6内核缺少一个类似malloc可以为小对象提供内存的分配器,这使得内核无法使用需要动态分配的复杂数据结构。

内存分配是一个长期的热门话题,基本问题是有效使用有限的内存并为将来的未知请求做好准备。今天,人们更关心速度而不是空间效率。此外,一个更复杂的内核可能会分配许多不同大小的小块,而不是(如xv6中)只有4096字节的块;一个真正的内核分配器需要处理小分配和大分配。

这篇关于XV6源码阅读——进程地址空间的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933471

相关文章

Python中使用正则表达式精准匹配IP地址的案例

《Python中使用正则表达式精准匹配IP地址的案例》Python的正则表达式(re模块)是完成这个任务的利器,但你知道怎么写才能准确匹配各种合法的IP地址吗,今天我们就来详细探讨这个问题,感兴趣的朋... 目录为什么需要IP正则表达式?IP地址的基本结构基础正则表达式写法精确匹配0-255的数字验证IP地

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

Linux中的进程间通信之匿名管道解读

《Linux中的进程间通信之匿名管道解读》:本文主要介绍Linux中的进程间通信之匿名管道解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基本概念二、管道1、温故知新2、实现方式3、匿名管道(一)管道中的四种情况(二)管道的特性总结一、基本概念我们知道多

查看Oracle数据库中UNDO表空间的使用情况(最新推荐)

《查看Oracle数据库中UNDO表空间的使用情况(最新推荐)》Oracle数据库中查看UNDO表空间使用情况的4种方法:DBA_TABLESPACES和DBA_DATA_FILES提供基本信息,V$... 目录1. 通过 DBjavascriptA_TABLESPACES 和 DBA_DATA_FILES

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重

Linux进程终止的N种方式详解

《Linux进程终止的N种方式详解》进程终止是操作系统中,进程的一个重要阶段,他标志着进程生命周期的结束,下面小编为大家整理了一些常见的Linux进程终止方式,大家可以根据需求选择... 目录前言一、进程终止的概念二、进程终止的场景三、进程终止的实现3.1 程序退出码3.2 运行完毕结果正常3.3 运行完毕

Linux配置IP地址的三种实现方式

《Linux配置IP地址的三种实现方式》:本文主要介绍Linux配置IP地址的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录环境RedHat9第一种安装 直接配置网卡文件第二种方式 nmcli(Networkmanager command-line

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

Linux虚拟机不显示IP地址的解决方法(亲测有效)

《Linux虚拟机不显示IP地址的解决方法(亲测有效)》本文主要介绍了通过VMware新装的Linux系统没有IP地址的解决方法,主要步骤包括:关闭虚拟机、打开VM虚拟网络编辑器、还原VMnet8或修... 目录前言步骤0.问题情况1.关闭虚拟机2.China编程打开VM虚拟网络编辑器3.1 方法一:点击还原VM