看来在Windows 32位上,内核将从完全4G的用户虚拟内存空间中预留1G的虚拟内存,并将一些内核空间映射到这个1G空间。
所以我的问题是:
我认为
cat /proc/pid/map
只能看到某个进程的用户空间布局..
谢谢!
实际上,在没有/3G
启动选项的32位Windows上,内核映射到最高2GB的线性地址空间,为用户进程留下2GB的空间。
Linux也做了类似的事情,但它将内核映射到最高1GB的线性空间,从而为用户进程留下了3GB的空间。
我不知道你是否可以通过使用/ proc文件系统来查看整个内存布局。 对于我为学生设计的一个实验,我创建了一个微小的设备驱动程序,允许用户查看物理内存地址,并获取多个控制寄存器的内容,如CR3(目录页基址)。
通过使用这两个操作,可以遍历当前进程(正在执行此操作的进程)的目录页面,查看哪些页面存在,哪些是由用户和内核拥有,还是由内核拥有,哪些是读/写或只读等。有了这些信息,他们必须显示一个显示内存使用情况的地图,包括内核空间。
看看这个PDF。 这是我在课程中所做的所有实验的编译版本。 http://www.atc.us.es/asignaturas/tpbn/PracticasTPBN2011.pdf
在PDF的第36页(文档的第30页),您将看到内存映射的外观。 这是练习#3练习#3的结果。
文本是西班牙文,但我相信你可以使用翻译或类似的东西,如果有一些你不明白的东西。 该实验室假设学生以前阅读过有关分页系统的工作原理以及如何解释目录和页面条目的布局。
地图是这样的。 一个16×64块。 块中的每个单元格表示当前进程虚拟地址空间的4MB。 这个地图应该是立体的,因为有一个4MB的地区可以通过一个有1024个条目(页面)的页面表来描述,并不是所有的页面都可以存在,但为了保持地图清晰,这个练习要求用户折叠这些地区,显示描述当前页面的第一页条目的内容,希望该页表中的所有后续页面共享相同的属性(实际上可能不一定是真实的)。
这张图与内核2.6.X一起使用。 其中不使用PAE
,使用PSE
(来自控制寄存器CR4
PAE
和PSE
是两位字段)。 PAE
启用2MB页面, PSE
启用4MB页面。 4KB页面始终可用。
. : PDE not present, or page table empty. X : 4MB page, supervisor. R : 4MB page, user, read only. * : 4MB page, user, read/write. x : Page table with at least one entry describing a supervisor page. r : Page table with at least one entry describing an user page, read only. + : Page table with at least one entry describing an user page, read/write. ................................r............................... ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ................................................................ ...............................+..............................+. xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..x...........................xx
你可以看到有3GB的内存空间,在这种情况下几乎是空的(这个过程只是一个小小的C应用程序,使用少于4MB,全部包含在一个页表中,其第一个当前页是一个只读页,假定是程序代码的一部分,或者是静态字符串)。
在3GB边界附近有两个小区域读/写,它们可能属于用户程序加载的共享库。
最后4行(256个目录条目)几乎全部属于内核。 有224个实际存在和使用的条目。 这些映射了第一个896MB的物理内存,这是内核所在的空间。 在超过896MB RAM的系统中,内核使用最后32个条目访问超过896MB标记的物理内存。
在32位的Linux上有没有类似的情况?
是。 在32位Linux上,默认情况下,内核为自己的使用保留地址空间的高四分之一(从C0000000到内存顶部的1G)。
如果是这样,我们怎么能看到整个内存布局?
你不能。 /proc/pid/maps
只显示用户空间中的映射。 内核内存不能从用户空间应用程序访问,所以不显示。
请记住使用这种安排的原因 – 当内核处于活动状态时,它需要能够安装自己的映射,同时仍然保持活动的用户空间映射(例如,它可以从用户空间复制数据)。 它通过为自己保留高内存范围来实现这一点。
内核中内存映射的位置与内核本身之外的任何内容都不相关,所以除了偶然事件或某些调试消息之外,内核映射都不会暴露给用户空间。