为了更加有效的管理内存并减少出错,现代系统提供了一种对主存的抽象概念,叫做虚拟内存。为每个进程提供了一个私有的地址空间。作用可总结为以下三点:
虚拟内存概念分为两部分,一部分是物理内存,还有一部分是位于交换区的磁盘空间,这部分磁盘空间在内存不足时可以作为内存,将活动不频繁的数据放入磁盘中。
页表将虚拟页映射到物理页,每次地址翻译硬件将虚拟地址装换为物理地址时都会读取页表。操作系统负责维护页表的内容,以及在磁盘和DRAM之间来回传送页。实际上: 操作系统为每个进程提供了一个独立的页表,因而也就是一个独立的虚拟地址空间。
DRAM缓存不命中称之为缺页 :当发生缓存不命中时,会触发一个缺页异常,缺页异常调用内核中的缺页异常处理程序,该程序会选择一个牺牲页。
页表是带许可位的,例如SUP,VP0,VP1,VP2等,其中SUP只能在超级用户模式下访问,用户模式有读VP0和读写VP1的权限,如果一条指令违反了许可条件,那么cpu会触发一个一般保护故障,将控制传递给一个内核中的异常处理程序,linux shell一般将这种异常报告为段错误(segmentation fault)
维护64位的虚拟地址空间一张页表肯定是不够用的,所以要用多级页表,也就是在一张页表里面维护的是下一张页表的地址,多级之后会指向实际的物理地址,这个和ip协议的路由寻址有点相似。
Linux通过将一个虚拟内存区域与一个磁盘上的对象关联起来,以初始化这个虚拟内存区域的内容,这个过程叫做内存映射。
一旦一个虚拟页面被初始化了,它就在一个由内核维护的专门的交换文件之间换来换去。交换文件也被称为交换空间,或者交换区域。
少量使用Swap交换空间是不会影响性能,只有当RAM资源出现瓶颈或者内存泄露,进程异常时导致频繁、大量使用交换分区才会导致严重性能问题。另外使用Swap交换分区频繁,还会引起kswapd0进程(虚拟内存管理中, 负责换页的)耗用大量CPU资源,导致CPU飙升。
1、windows下的虚拟内存指的是在硬盘上建一个文件,用来放置系统非活跃性内存数据或交换数据(怎么放,放多少由操作系统决定)。
2、虚拟地址空间,指windows下每个进程的私有内存空间,大小是4G,能访问的是不到2G的空间,其余是系统保留的.这2G是能访问的,但并不是立即分配的,当进程使用多少时,才从物理内存中划分给它多少,划分的的方式是"映射",操作系统将虚拟内存的起始地址做个标记,标记成对应的物理内存的某个地址上.在这里,只有操作系统知道,进程是没有任何办法知道的。
3、这是WINDOWS的高级内存管理机制决定的.物理内存的地址空间,只有操作系统才能访问(硬件驱动也可以,但已经属于系统低层了,进程是属于用户层)进程虚拟内存空间和物理内存空间的关系仅仅是看不见的映射关系。
4、虚拟内存通常只在系统物理内存用完时,才会使用到,但这个时候系统已经非常卡了.但也不是一点用处没有,非活跃性进程的部分数据,系统是完全可以放在虚拟内存中的。
5、以上基于32位Windows系统.64位的没去看过相关的资源,不清楚有没有变动。
https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt
https://www.kernel.org/doc/html/latest/x86/x86_64/5level-paging.html
原始的x86-64架构,以4层页表并受限于此,实现了256 TiB的虚拟地址空间和64 TiB的物理地址空间。 我们已经受限于此:一些厂商提供64TiB的内存。
为了克服这一限制,即将推出的硬件将引入对5级分页的支持。它是当前页表结构的直接扩展,增加了一层翻译。
它将虚拟地址空间的限制提高到128PiB,物理地址空间的限制提高到4PiB。
QEMU 2.9及更高版本支持5级分页。
CONFIG_X86_5LEVEL=y 开启该特性。
配置 CONFIG_X86_5LEVEL=y 的内核仍然可以运行在4-level的硬件上。这种情况,会在运行时会包含一个额外的页表级别 – p4d – 。
在x86架构上,5级分页支持56位用户空间虚拟地址空间。并非所有用户空间都准备好处理宽地址。众所周知,至少有一些JIT编译器使用指针中的高位对其信息进行编码。它与具有5级分页的有效指针冲突,并导致崩溃。为了缓解这种情况,默认我们不会分配47位以上的虚拟地址空间。
但是,用户空间可以通过指定47位以上的 hint address with or without MAP_FIXED ),从整个地址空间请求分配。
若 hint address 设置在47位以上,但没有指定 MAP_FIXED ,我们将尝试按指定的地址查找未映射的区域。若它已经被占用,我们将在整个的地址空间中查找未映射的区域,而不是从47位窗口中查找。
high hint address 只会影响相关的分配,而不会影响将来的mmap()s。
在旧内核上或在没有5级分页支持的计算机上指定 high hint address 是安全的。Hint将被忽略,内核将退回到47位地址空间的分配。
该方法有助于轻松地使应用程序的内存分配器分配大地址空间,而无需手动跟踪分配的虚拟地址空间。
一个重要问题:处理与MPX的交互。MPX(没有 MAWA 扩展)无法处理47位以上的地址,因此我们需要确保无法启用MPX。我们已经在边界上方有VMA,并且一旦启用MPX,就禁止创建此类VMA。
架构定义了64位虚拟地址。工程实现支持少一些。目前支持的是48位和57位虚拟地址。
63位到最高有效实现位是sign扩展的。如果将其解释为unsighed,则会导致用户空间和内核地址之间出现漏洞。
直接映射覆盖系统中直到最高内存地址的所有内存(这意味着在某些情况下,它还可以包括PCI内存洞)。
vmalloc空间使用page fault处理程序(以init_top_pgt为参考)惰性地同步到进程的不同PML4/PML5页面中。
我们将在 EFI_pgd PGD中的 EFI runtime 服务映射到64Gb大型虚拟内存窗口中(此大小是任意的,如果需要,可以稍后提高)。这些映射不属于任何其他内核PGD,仅在 EFI runtime 调用期间可用。
请注意,如果启用了 CONFIG_RANDOMIZE_MEMORY ,则直接映射所有物理内存、vmalloc/ioremap空间和虚拟内存,都将随机化。
它们的顺序保留,但它们的基数早在boot时就偏移了。
与KASLR相比,在这里更改任何内容时都要非常小心。KASLR地址范围不得与除KASAN阴影区域以外的任何区域重叠,因为KASAN禁用了KASLR。
对于4层和5层布局, STACKLEAK_POISON 值在最后2MB
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)