检测合法的伙伴系统区间

来源:互联网 发布:都玩网络手游 编辑:程序博客网 时间:2024/05/22 14:58

假设有这样一个场景,人们在得到一个kmalloc出来的地址后,不清楚该地址是否位于合法的buddy system区间。

为了检查该区间的合法性,就可以在系统启动时,buddy system生成时、bootmem释放时,根据bootmem map

来确定哪些页框是被释放给buddy system。(除了bootmem的释放,后期还有释放init段空间,以及释放initrd空间,这里只考虑前者)

struct low_memory_buddy_region{unsigned long start;unsigned long end;};#define MAX_BUDDY_LMBR 100static struct low_memory_buddy_region lmbr[MAX_BUDDY_LMBR]={{0,0}};static int index_lmbr = 0;void add_new_lmbr(unsigned long start,unsigned long end){lmbr[index_lmbr].start = start;lmbr[index_lmbr].end = end;index_lmbr++;}void dump_all_lmbr(void){int i = 0;for(i=0;i<index_lmbr;i++)printk("buddy region low pfn[%ld-%ld]\n",lmbr[i].start,lmbr[i].end);}void traverse_bootmem_map(unsigned long *map,unsigned long start_idx,unsigned long idx){unsigned long i, m, v = 0;int new_region = 0 ;unsigned long start_pfn = 0;for (i = 0; i < idx; i += BITS_PER_LONG) {v = ~map[i / BITS_PER_LONG];if (v) {   /** Fixme when v=~0UL*/for (m = 0; m<BITS_PER_LONG; m++) {if (v & (1UL<<m)){ if(!new_region){start_pfn = i+m;new_region = 1;}}else{if(new_region){add_new_lmbr(start_pfn+start_idx,i+m+start_idx);new_region = 0;}}}}else{/*continuous zeros tell the end of region*/if(new_region){add_new_lmbr(start_pfn+start_idx,i+start_idx);new_region = 0;}}}   /** Last v's bit equals 1 tells the new region's ending*/if(v&1)add_new_lmbr(start_pfn+start_idx,idx+start_idx);}

static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat){/* first extant page of the node */pfn = PFN_DOWN(bdata->node_boot_start);idx = bdata->node_low_pfn - pfn;map = bdata->node_bootmem_map;#if 1traverse_bootmem_map(map,pfn,idx);#endif/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */if (bdata->node_boot_start == 0 ||    ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG))gofast = 1;}

#if 1#define virt_to_pfn(kaddr)(__pa(kaddr) >> PAGE_SHIFT)add_new_lmbr(virt_to_pfn(bdata->node_bootmem_map),virt_to_pfn(bdata->node_bootmem_map)+idx);#endiftotal += count;bdata->node_bootmem_map = NULL;


上述代码有两处可以改进:

1)add_new_lmbr可以对提交的区间进行排序插入,考虑到区间不是太多,采用冒泡排序(可借鉴powerpc的lmb内存管理)

2)遍历bootmem map的时候,如果某时刻取到的unsigned long位图是全f,则可以直接跳过32个页。

3)上述代码没有考虑高端内存。

ps: 发现n久不写代码,上面那么一点点代码都耗了大量时间。特别是还漏掉了位图为连续的0的情况。真是惭愧!

原创粉丝点击