bootmem API总结
bootmem_init()函数执行完成后,linux启动初期的bootmem分配器就初始化完成了,可以调用bootmem提供的API分配内存。
这些API在include/linux/bootmem.h中定义
1.alloc_bootmem与alloc_bootmem_pages的不同之处在于分配内存时的对齐方式不同,
alloc_bootmem以cache_line大小对齐,
alloc_bootmem_pages以页大小对齐。
#define alloc_bootmem(x) \ __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_pages(x) \ __alloc_bootmem(x, PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
2.alloc_bootmem在分配失败时会panic,而alloc_bootmem_nopanic分配失败时返回NULL。
#define alloc_bootmem(x) \ __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_nopanic(x) \ __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
3.alloc_bootmem预留出DMA分配区;alloc_bootmem_low从0开始分配。
#define alloc_bootmem(x) \ __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low(x) \ __alloc_bootmem_low(x, SMP_CACHE_BYTES, 0)
4.在多节点的系统中,有多个bootmem分配器构成的链表。
alloc_bootmem没有指定节点信息,分配时遍历bootmem分配器链表,遇到第一个分配成功的就返回。
alloc_bootmem_node则在指定的节点的bootmem分配器上分配内存。
#define alloc_bootmem(x) \ __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_node(pgdat, x) \ __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
5.释放内存
/** * free_bootmem_node - mark a page range as usable * @pgdat: node the range resides on * @physaddr: starting address of the range * @size: size of the range in bytes * * Partial pages will be considered reserved and left as they are. * * The range must reside completely on the specified node. */ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr, unsigned long size) { unsigned long start, end; start = PFN_UP(physaddr); end = PFN_DOWN(physaddr + size); mark_bootmem_node(pgdat->bdata, start, end, 0, 0); } /** * free_bootmem - mark a page range as usable * @addr: starting address of the range * @size: size of the range in bytes * * Partial pages will be considered reserved and left as they are. * * The range must be contiguous but may span node boundaries. */ void __init free_bootmem(unsigned long addr, unsigned long size) { unsigned long start, end; start = PFN_UP(addr); end = PFN_DOWN(addr + size); mark_bootmem(start, end, 0, 0); }