一个新手问题。 我正在做一些内核研究,并对ZONE_NORMAL的896MB大小限制感到困惑。 我不明白为什么内核不能直接将4G物理内存映射到内核空间。 有些文件提到了页面地图的大小限制。 但考虑4G内存有2 ^ 20页,每个“结构页”是4个字节,mem_map只有4MB。 这不应该是问题。 希望你能给我一些启发。
谢谢
内核限制为896 MB的原因是出于性能原因。
内核可用空间越多意味着用户空间可用的地址空间越少 。 这个3/1分割意味着用户进程可以分配的最大地址空间是3千兆字节 – 当然,由于内存碎片,实际上它似乎开始失败大约2.5千兆字节。
不同的分割可用:2/2和1/3分割为内核分配两千兆字节的地址空间,为用户空间分配两千兆字节,内核分配三千兆字节,用户空间分配一千兆字节的地址空间。 (这个firefox
现在消耗1249兆字节,所以它不能适应这三分之一分割内核之一。)
有一些内核(可能是供应商?)支持所谓的4:4拆分 – 为内核提供4千兆字节的地址空间,为用户空间提供4千兆字节的地址空间。 这些对于具有32或64千兆字节内存的32位系统非常有用 – 因为大型系统可能具有许多磁盘,大量的IO在运行,并且需要对块设备和网络流量进行显着的缓冲。 但是,这些4:4内核在进入和退出每个系统调用时都需要刷新TLB缓存。 这些TLB刷新在“小型”系统上引入显着的减速,并且只有在额外内存可以缓存足够的磁盘/网络资源以提高系统性能的“大型”系统上才值得。
其他的分割不会引起这个TLB刷新,因为当CPU处于用户状态或主管状态时,TLB维护一个表示页面是否可用的权限位:内核页面总是被映射的,但是只有当CPU的主管标志被设置。 所以在退出进入内核的进程时,进入和退出内核是很快的。 当上下文切换时,TLB当然需要被刷新。
当然,内核可以映射所有可用的内存。
在Linux中,所有银行提供的内存被分类为“节点”。 这些节点用来表示每个银行有多少内存。 每个节点的内存分为“区域”。 当前定义的区域是ZONE_DMA
, ZONE_HIGHMEM
和ZONE_HIGHMEM
。
某些设备使用ZONE_DMA
进行数据传输,并映射到较低的物理内存范围(最多16 MB)。
ZONE_NORMAL
区域中的内存由内核映射到线性地址空间的上部区域。 大多数操作只能在ZONE_NORMAL
; 所以这是性能最关键的区域。 ZONE_NORMAL
从16 MB变为896 MB。
为什么?
内存的一部分保留给内存数据结构,用于存储关于内存映射和页表的信息。 这在x86上是128 MB。 因此,在内核可以访问的1GB物理内存中(在典型配置中,1GB是为内核预留的),128MB是保留的。 因此,这个128 MB的内核虚拟地址不会直接映射到物理内存。 这为ZONE_NORMAL
留下了最多896 MB。 所以,即使有1 GB的物理内存,用户空间实际上也只有896 MB。
为了更好地理解这个主题,我建议你看看Linux设备驱动程序( pdf )的第15章。