2012-07-18 46 views
3

几乎所有关于Linux内核中HIGHMEM的书籍和文章,他们都说在使用3:1分割时,并不是所有的1GB都可用于内核映射。通常它的大小为896MB左右,其余部分用于内核数据结构,内存映射,页表等。什么数据结构使用128MB的1GB Linux内核空间?

我的问题是,这些数据结构究竟是什么?页表通常通过页表地址寄存器访问,对吧?并且页表的基地址通常被存储为物理地址。现在为什么需要为整个表保留一个虚拟地址空间?

同样,我读了关于占用空间的内核代码本身。这与虚拟地址空间有什么关系?这不是用于存储代码的物理内存吗?

最后,这些数据结构,为什么他们要保留128MB的空间?为什么不能按照需要在整个1GB地址空间中使用它们,就像内核中的任何其他正常数据结构一样?

我已经通过LDD3专业Linux内核架构和几个帖子在这里堆栈溢出(如:Why Linux Kernel ZONE_NORMAL is limited to 896 MB?)和一个较旧的LWN article,但没有找到相同的具体信息。

回答

2

至于页表,这是真的,如果页面表本身的虚拟地址空间没有映射的MMU根本不会在乎 - 为地址转换的目的,这将是确定。但是当内核需要修改页表时,他们需要在虚拟地址空间中映射它们 - 并且内核不能仅仅在“及时”映射它们,因为它需要自己修改页表要做到这一点。这是一个鸡与鸡蛋的问题,这意味着页表需要始终保持映射。

内核代码存在类似的问题。对于要执行的代码,它必须映射到虚拟地址空间中 - 如果执行页表修改的代码本身不存在,那么我们会遇到类似的鸡与蛋问题。考虑到这一点,将内核代码的全部内容随时映射,以及内核模式堆栈和任何内核数据结构通过代码进行访问会更容易,因为您不希望发生页面错误。这种数据结构的一个大例子是代表每个物理内存页面的struct page结构数组。

0

128MB的储备是不针对特定的数据结构,即总是使用它。
它是虚拟内存,为各种用户保留,可能会使用它。通常情况下,并未全部使用。

关于物理和虚拟内存:每次分配需要三样东西 - 一个物理页面,一个页面当前虚拟和映射连接两个。 Linux几乎不会直接使用物理地址,它总是通过虚拟地址转换。
对于大多数内核内存分配(称为lowmem),这种转换非常简单 - 从虚拟地址中减去一些常量以获得物理内存。但是,仍然使用虚拟地址。

即使在最大的机器上,当虚拟内存空间(4GB)比物理内存大得多 时,也会编写Linux内存管理。在这种情况下,浪费虚拟地址不是问题。今天,当物理内存很大时,这会导致效率低下和问题。

vmalloc虚拟地址范围是由vmalloc任何呼叫者使用。例如:
1.加载内核驱动程序(使用modprobeinsmod)。
2.内核模块通常与vmalloc一起分配。替代函数kmalloc曾经被限制为128K,并且其大小达到2的幂,所以vmalloc通常是大分配的首选。

+0

如果没有为特定数据结构保留128MB,为什么我们不能使用整个1G内核虚拟空间映射到某个虚拟地址?这样,如果一个系统有1GB的物理内存,则根本不需要使用HIGHMEM。在基于896MB的设置中,需要HIGHMEM来利用大于896MB的任何物理内存。同样,当我们为某些东西(甚至不使用它)保留128MB时,虚拟地址范围变得不可用于'vmalloc'。正如你所说的,一切都是通过虚拟地址访问的。他们为什么浪费任何虚拟地址? – codetwiddler 2012-07-19 14:33:06

+0

@codetwiddler,这是相当复杂的......浪费虚拟地址是不好的,但它并非没有用处。基本点是有两种方法可以将虚拟地址连接到物理地址 - 直接映射(lowmem)和任意动态映射(vmalloc)。每个人都必须使用一个单独的虚拟地址范围,所以他们不会发生冲突。 – ugoren 2012-07-19 14:37:04

+0

同意一切,我知道有两种方法及其用途。现在,具体来说,如果我有1GB的物理内存,我需要使用HIGHMEM来访问超过896MB,因为这个1GB-896MB块被保留。那是什么目的,它是多么复杂?该保留应该有一些结构或与该空间相关的东西,或者至少是指向某个地方的指针,如果该保留是静态的,我认为它应该是相当重要的实体。 – codetwiddler 2012-07-19 16:40:35