长篇连载--arm linux演艺---第十回 -------------------------------------------------------------------------------- 书接上回, 下面是init_mm的初始化,init_mm定义在/arch/arm/kernel/init_task.c: struct mm_struct init_mm = INIT_MM(init_mm); 从本回开始的相当一部分内容是和内存管理相关的,凭心而论,操作系统的内存管理是很复杂的,牵扯到处理器的硬件细节和软件算法, 限于篇幅所限制,请大家先仔细读一读arm mmu的部分, 中文参考资料:linux内核源代码情景对话, linux2.4.18原代码分析。
init_mm.start_code = (unsigned long) &_text; 内核代码段开始 init_mm.end_code = (unsigned long) &_etext; 内核代码段结束 init_mm.end_data = (unsigned long) &_edata; 内核数据段开始 init_mm.brk = (unsigned long) &_end; 内核数据段结束 每一个任务都有一个mm_struct结构管理任务内存空间,init_mm是内核的mm_struct,其中设置成员变量* mmap指向自己,意味着内核只有一个内存管理结构,设置* pgd=swapper_pg_dir,swapper_pg_dir是内核的页目录,在arm体系结构有16k,所以init_mm定义了整个kernel的内存空间,下面我们会碰到内核线程,所有的内核线程都使用内核空间,拥有和内核同样的访问权限。 memcpy(saved_command_line, from, COMMAND_LINE_SIZE); //clear command array saved_command_line[COMMAND_LINE_SIZE-1] = '/0'; //set the end flag parse_cmdline(&meminfo, cmdline_p, from); //将bootloader的参数拷贝到cmdline_p, bootmem_init(&meminfo); 定义在arm/mm/init.c 这个函数在内核结尾分一页出来作位图,根据具体系统的内存大小映射整个ram
下面是一个非常重要的函数 paging_init(&meminfo, mdesc); 定义在arm/mm/init.c 创建内核页表,映射所有物理内存和io空间,对于不同的处理器,这个函数差别很大, void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) { void *zero_page, *bad_page, *bad_table; int node; //static struct meminfo meminfo __initdata = { 0, }; memcpy(&meminfo, mi, sizeof(meminfo)); /* * allocate what we need for the bad pages. * note that we count on this going ok. */ zero_page = alloc_bootmem_low_pages(PAGE_SIZE); bad_page = alloc_bootmem_low_pages(PAGE_SIZE); bad_table = alloc_bootmem_low_pages(TABLE_SIZE); 分配三个页出来,用于处理异常过程,在armlinux中,得到如下地址: zero_page=0xc0000000 bad page=0xc0001000 bad_table=0xc0002000 欲知后事如何,且听 arm linux 下回分解
|