cod*_*ler 5 memory-management virtual-memory linux-kernel
在我读过的有关Linux内核中HIGHMEM的几乎所有书籍和文章中,他们都说在使用3:1 split的情况下,内核并不是可以使用所有的1GB内存进行映射。通常为896MB左右,其余部分用于内核数据结构,内存映射,页表等。
我的问题是,这些数据结构到底是什么?通常通过页表地址寄存器访问页表,对吗?页表的基地址通常存储为物理地址。现在为什么需要为整个表保留虚拟地址空间?
同样,我了解了内核代码本身所占据的空间。这与虚拟地址空间有什么关系?是不是因为存储代码而消耗了物理内存?
最后,这些数据结构为何必须保留128MB的空间?为什么不能按要求在整个1GB地址空间中使用它们,就像内核中的任何其他常规数据结构一样?
我已经遍历了LDD3,Professional Linux Kernel Architecture和堆栈溢出的一些帖子(例如:为什么Linux Kernel ZONE_NORMAL限制为896 MB?)和较旧的LWN 文章,但没有找到相同的具体信息。
对于页表,MMU 确实不会关心页表本身是否没有映射到虚拟地址空间中——出于地址转换的目的,那没关系。但是当内核需要修改页表时,它们确实需要映射到虚拟地址空间中——并且内核不能只是“及时”地映射它们,因为它需要修改页表本身来完成那。这是一个先有鸡还是先有蛋的问题,这意味着页表需要始终保持映射状态。
内核代码也存在类似的问题。对于要执行的代码,它必须映射到虚拟地址空间中 - 如果执行页表修改的代码本身不存在,我们就会遇到类似的先有鸡还是先有蛋的问题。鉴于此,更容易始终保留整个内核代码的映射,以及内核模式堆栈和由代码访问的任何内核数据结构,您不希望可能出现页面错误。这种数据结构的一个大例子是struct page
结构数组,代表每个物理内存页。