Linux 那么/proc/$pid/maps文件中未提供的许多地址呢?

Linux 那么/proc/$pid/maps文件中未提供的许多地址呢?,linux,paging,virtual-memory,Linux,Paging,Virtual Memory,简要版本: 地图文件中未显示的地址的状态是什么?它们是属于未分配的虚拟页还是从匿名文件或其他文件分配的 详细版本 我正在学习虚拟机。在我的书(CS:APP)中,我了解到所有虚拟页面都可以分为三组:未分配、已分配但未缓存、已分配和缓存。我对“什么是已分配页面和未分配页面?何时分配页面?”有一些问题,还有,堆栈和堆是属于已分配页面还是未分配,还是仅在使用时分配? 为了解决这些问题,我阅读了/proc/$pid/maps文件,同时我认为我可以从中得到我想要的任何东西。在我看来,该文件包含所有内存映射关

简要版本: 地图文件中未显示的地址的状态是什么?它们是属于未分配的虚拟页还是从匿名文件或其他文件分配的

详细版本 我正在学习虚拟机。在我的书(CS:APP)中,我了解到所有虚拟页面都可以分为三组:未分配、已分配但未缓存、已分配和缓存。我对“什么是已分配页面和未分配页面?何时分配页面?”有一些问题,还有,堆栈和堆是属于已分配页面还是未分配,还是仅在使用时分配?
为了解决这些问题,我阅读了/proc/$pid/maps文件,同时我认为我可以从中得到我想要的任何东西。在我看来,该文件包含所有内存映射关系。但是没有关于它是否缓存的信息(我知道可能从用户模式看不到它…),以及未提交的页面是否未分配?

老实说,我不太了解地图文件。我所知道的是,每页上的信息始终存储在
page
结构中。我将以x86-64为例

对于Linux上的x86-64,您有页面全局目录(PGD)、页面上层目录(PUD)、页面中间目录(PMD)和页面目录(PD)。PGD表底部的地址存储在CR3寄存器中。PGD包含PUD的地址,PUD包含PMD的地址,PMD包含PDs的地址,PDs包含物理页的地址

一个仅使用48位的虚拟地址被分成5部分。12个最低有效位是物理页中的偏移量。下一块9位是PD中的偏移量。下一个区块是PMD中的偏移量等。例如,假设您有虚拟地址
0x0000000000000123
。CPU中的MMU将通过查看PGD的条目(偏移量)0、PUD的条目0、PMD的条目0、PD的条目0以及RAM中实际物理页面中的最终偏移量0x123来转换此虚拟地址。每个虚拟地址是64位,其中只有48个最低有效位将被使用

在引导时,内核进行检查以确定有多少内存可用。然后,它相应地构建其内核结构

当内核启动时,它会在自己的结构中将所有页面标记为未分配(内核需要除外)。
页面
结构对于这一点很重要。对于系统中的每个页面,内核都有一个
page
C结构(和)。此结构通知内核是否分配了页面

系统中的每个物理页都有一个与 它可以跟踪我们在网站上使用该页面的目的 片刻。请注意,我们无法跟踪正在使用的任务 一个页面,如果它是一个页面缓存页面,rmap结构可以告诉我们 谁在绘制地图

起初,页面大多未分配。当您以系统用户的身份启动可执行文件来启动新流程时,将为您的流程分配页面。在Linux上,可执行文件是ELF文件。ELF是一种传统格式,它将代码分成可加载段。每个段都会获得一个虚拟地址,它将在该虚拟地址空间中加载

假设您有一个elf文件,其中有一个段应该加载到虚拟地址0x400000。当您启动ELF可执行文件时,Linux内核将调用某些函数,这些函数将查看代码的大小并相应地分配页面。内核将查看其结构,并使用算法确定进程在RAM中的分配位置。然后,它将根据该进程的虚拟地址在实际物理内存中的位置设置页表

需要了解的是,系统中的每个CPU核心一次只运行一个进程。每个核心都有自己的页面表集。当一个内核发生进程切换时,页表将完全交换,以指向RAM中的其他位置。根据页表的设置方式,相同的虚拟地址可以指向RAM中的任何位置

内核为系统中运行的每个进程保存一个task_结构。task_结构包含一个名为pgd的字段,该字段是指向进程pgd的指针。每个过程都有自己的PGD。如果取消引用指向PGD的指针,则会得到PGD第一个条目的实际值。第一个条目是PUD的地址。有了这个唯一的指针,内核就可以访问属于进程的每个表并随意修改它们

当进程运行时,它可能会请求更多内存。这称为动态内存分配。内核无法知道进程将提前请求多少内存,因为它是动态的(在代码执行时完成)。当进程请求更多内存时,内核根据算法决定给进程分配哪个页面。然后,它将此页面标记为已分配给该进程。task_struct包含类型为mm_struct()的mm字段。它是该进程的内存描述符,因此内核可以知道该进程正在使用什么内存。进程本身不需要这些信息,因为进程应该只依靠自身向操作系统正确地请求内存,而不是跳转到RAM中不属于它的某个地方

你问的是堆和堆栈。进程的堆栈是在进程开始时分配的,我认为它的大小是固定的。如果堆栈溢出,将引发CPU异常,提示内核终止进程。每个CPU核心都有一个称为RSP的特殊寄存器。这是堆栈指针。它指向堆栈的顶部(堆栈朝着内存不足的方向向下增长)。当内核为您启动的进程分配堆栈时,它会将这个寄存器设置为指向它的顶部。堆栈指针包含一个vi