全部博文(685)
分类: LINUX
2015-01-06 11:29:52
上一篇主要是与具体体系有关的数据结构,并最后遗留了个问题:
那么,这些数据结构怎样发挥作用的呢?特别是,ARM-Linux内核怎样根据这些数据结构建立起地址映射呢?
1、从系统的初始化说起。系统引导以后,CPU进入内核的总入口,即代码段的起点stext.在stext中,CPU首先从自身读出CPU的型号及其所在的机型,把有关的信息存放在processor_id和machine_arch_type两个全局变量中,然后就转入start_kernel()。
asmlinkage void __init start_kernel(void)
{
......
setup_arch(&command_line);
这个函数的代码与具体的CPU机型有关,主要在系统初始化阶段完成一下操作:
......
mem_init();
kmem_cache_sizes_init();
.......
}
对于MMU,一个具体的页面目录就是一种具体的映射,可是对内核则还需要有一些附加的信息。从内核的角度,一种具体的映射是通过一个mm_struct数据结构加以描述和管理的,其中内核的mm_struct数据结构init_mm有着特殊的重要性:
struct mm_struct init_mm = INIT_MM(init_mm);
#define INIT_MM(name) \
{ \
mm_rb: RB_ROOT, \
pgd: swapper_pg_dir, \
mm_users: ATOMIC_INIT(2), \
mm_count: ATOMIC_INIT(1), \
mmap_sem: __RWSEM_INITIALIZER(name.mmap_sem), \
page_table_lock: SPIN_LOCK_UNLOCKED, \
mmlist: LIST_HEAD_INIT(name.mmlist), \
}
准确的说法应该是内核线程的mm_struct数据结构,或内核线程的映射,这是因为在这个映射中不包含任何用户空间的映射。系统中所有的内核线程都共享同一个映射,那就是init_mm。特别的,内核线程init的mm_struct数据结构就是init_mm。
每个进程或线程都有个进程控制块,这里面就有个指针mm指向自己的mm_struct数据结构。而mm_struct结构中,则有个指针pgd指向它的首层页面目录。
/*
* We place the page tables 16K below TEXTADDR. Therefore, we must make sure
* that TEXTADDR is correctly set. Currently, we expect the least significant
* "short" to be 0x8000, but we could probably relax this restriction to
* TEXTADDR > PAGE_OFFSET + 0x4000
*
* Note that swapper_pg_dir is the virtual address of the page tables, and
* pgtbl gives us a position-independent reference to these tables. We can
* do this because stext == TEXTADDR
*
* swapper_pg_dir, pgtbl and krnladr are all closely related.
*/
#if (TEXTADDR & 0xffff) != 0x8000
#error TEXTADDR must start at 0xXXXX8000
#endif
.globl SYMBOL_NAME(swapper_pg_dir)
.equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000
.macro pgtbl, reg, rambase
adr \reg, stext
sub \reg, \reg, #0x4000
.endm
/*