天天看点

【存储管理】物理页面的分配

用于分配给DMA的内存页面必须是连续的,其实对于物理内存空间质地一致性的考虑,即使不用于DMA的内存页面也是连续分配的。一个进程分配若干连续的物理内存页面通过alloc_pages来完成。

(1)根据质地的一致性要求,linux中有两个alloc_pages,编译时根据编译选项决定取舍。选择NUMA时,说明最低物理地址和最高物理地址之间存在空洞,空洞的空间当然是非均质的,因此在地址不连续的物理地址空间也要像在质地不均匀的物理地址空间那样划分出若干连续的节点;为此在存储空间不连续的系统中,每一个模块都有若干个节点,都有一个pg_data_t队列,然后按照各个管理区一一尝试;后面的__alloc_pages与连续空间的UMA中的类似,,gfp_mask控制所选择区的位置去向。

(2)__alloc_pages首先在所有页面的管理区中循环,一次考察各个管理区的空闲页面总量,大于低水位时,直接通过rmqueue从该管理区中分配,否则唤醒kreclaimd_wait中的kreclaimd,让她帮助回收一些页面备用。在rmqueue中取得管理区的zone符合的按块区域的free_area_t(zone->free_area+order),首先尝试恰好的,然后依次尝试,并且通过memlist_entry()从非空队列里取得第一个结构的page元素,memlist_del删除。

(3)如果给定所有的页面管理区都失败了,就只好加大力度尝试(降低水位要求和不活跃干净页面也考虑进去);使用PAGES_HIGH,PAGES_LOW依次调用__alloc_pages_limit来尝试;在__alloc_pages_limit中的reclaim_page从页面管理区的inactive_clean_list队列中回收页面后,再尝试。

(4)如果还是不行的,这些管理区的页面已经严重短缺了;首先唤醒内核线程kswapd,让它设法换出一些页面,然后使用PAGES_MIN再试一次。查看task_struct结构中的flags字段的PF_MEMALLOC=0(不是公务线程),此时用page_launder将页面换出变成干净页面加以回收,然后使用rmqueue再试,如果还是不行,就唤醒kswapd(唤醒睡眠的进程),让分配页面的进程睡眠等待。

(5)如果是执行公务的进程(kswapd,kreclaimd),最后还是不行时,以最低下限来尝试。其实大部分情况下,在第一个页面管理区就会成功,不过,设计一个系统需要何等周密的考虑。