本帖最后由 硬核王同学 于 2023-12-24 23:05 编辑
1.请简述Linux内核在理想情况下页面分配器(page allocator)是如何分配出连续物理页面的。
答:在理想情况下,Linux内核的页面分配器会使用伙伴系统算法来分配连续的物理页面。这算法将可用内存划分为不同大小的块,并使用二进制树来跟踪可用和已分配的块。当请求分配连续页面时,分配器会搜索合适大小的块,然后通过合并操作来获得所需大小的连续页面。内核中分配物理内存页面的常用接口函数是alloc_pages(),它用于分配一个或者多个连续的物理页面,分配的页面个数只能是2的整数次幂。它的参数有两个,gfp_mask表示分配掩码,order表示分配级数。
2.在页面分配器中,如何从分配掩码(gfp_mask)中确定可以从哪些zone中分配内存?
答:分配掩码其实被定义成一个unsigned类型的变量。它被定义在include/linux/gfp.h文件中,它包含了关于内存管理区修饰符的标志,主要用于表示应当从哪些内存管理区中来分配物理内存。内存管理区修饰符使用gfp_mask的低4位来表示,其中包括GFP_DMA、GFP_HIGHMEM、_GFP_DMA32等标志,它们用于指示内核在哪些内存区域中进行分配。例如,GFP_DMA表示应该从DMA区域分配内存,而GFP_HIGHMEM表示应该从高端内存区域分配内存。通过检查分配掩码中的这些标志位,页面分配器可以确定从哪些zone中分配内存。
3.页面分配器是按照什么方向来扫描zone的?
答:Linux内核的页面分配器(buddy allocator)通常是按照从高到低的内存地址进行扫描。
4.为用户进程分配物理内存时,分配掩码应该选用GFP_KERNEL,还是GFP_HIGHUSER_ MOVABLE呢?
答:当为用户进程分配物理内存时,通常应该选择GFP_KERNEL分配掩码。
GFP_KERNEL是Linux内核中最常用的分配掩码,它用于分配内核空间中的内存。用户进程在运行时一般在内核空间中执行,因此使用GFP_KERNEL可以确保分配的内存位于内核空间中,可以直接访问和使用。
另一方面,GFP_HIGHUSER_ MOVABLE则是用于分配高端用户空间中的可移动内存。高端用户空间是指进程虚拟地址的较高部分,用于分配大于1GB的用户进程内存。GFP_HIGHUSER_ MOVABLE用于分配可通过move_pages接口移动的内存,这对于某些需要内存迁移功能的特殊应用情况可能有用,例如在NUMA系统中优化内存访问。
总之,对于大多数普通用户进程来说,应该使用GFP_KERNEL分配掩码来分配内存。只有在需要特殊的内存迁移功能或者高端用户空间时,才需要考虑使用GFP_HIGHUSER_ MOVABLE。对于大多数常规用户进程,GFP_KERNEL通常是最合适的选择。
|