1. 程式人生 > >x86系統引導(5)

x86系統引導(5)

再次回到asmlinkage void __init start_kernel(void)函式

asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
lock_kernel();
page_address_init();
printk(linux_banner);
setup_arch(&command_line);上幾篇分析的主要是這個函式。


setup_per_cpu_areas();/* 設定smp中每個cpu區域偏移量資訊 */
/*
* Mark the boot cpu "online" so that it can call console drivers in
* printk() and can access its per-cpu storage.
*/
smp_prepare_boot_cpu();設定引導cpu在工作狀態

/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
sched_init();對程序排程機制的初始化
build_all_zonelists();
page_alloc_init();
printk("Kernel command line: %s\n", saved_command_line);
parse_early_param();對命令列進行解析,只是做一些字串的處理
parse_args("Booting kernel", command_line, __start___param,
  __stop___param - __start___param,
  &unknown_bootoption);

對命令列進行分析,並執行對應的函式。原始碼如下:

/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
int parse_args(const char *name,
      char *args,
      struct kernel_param *params,
      unsigned num,
      int (*unknown)(char *param, char *val))
{
char *param, *val;
DEBUGP("Parsing ARGS: %s\n", args);
while (*args) {
int ret;

args = next_arg(args, &param, &val);
ret = parse_one(param, val, params, num, unknown);

主要是這兩個函式,涉及到一個結構體,如下:

typedef int (*param_set_fn)(const char *val, struct kernel_param *kp);
typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp);
struct kernel_param {
const char *name;
unsigned int perm;
param_set_fn set;
param_get_fn get;
void *arg;
};

從命令列中找到對應的命令,然後執行kernel_param結構體中對應的函式。

static int parse_one(char *param,
    char *val,
    struct kernel_param *params, 
    unsigned num_params,
    int (*handle_unknown)(char *param, char *val))
{
unsigned int i;

/* Find parameter */
for (i = 0; i < num_params; i++) {
if (parameq(param, params[i].name)) {
DEBUGP("They are equal!  Calling %p\n",
      params[i].set);
return params[i].set(val, &params[i]);執行對應的函式。
}
}
.....
}

.....

}
......
}
}.....
}
sort_main_extable();/* 異常處理呼叫函式表排序 */
trap_init();設定終端門和陷阱門
rcu_init();/* 初始化RCU(Read-Copy Update) */
init_IRQ();中斷初始化
pidhash_init();pidhash表初始化
init_timers();
softirq_init();軟中斷
time_init();定時器初始化

/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
console_init();控制檯初始化
if (panic_later)
panic(panic_later, panic_param);
profile_init();
local_irq_enable();開中斷
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
initrd_start < min_low_pfn << PAGE_SHIFT) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
   "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
initrd_start = 0;
}
#endif
vfs_caches_init_early();
mem_init();記憶體
kmem_cache_init();
numa_policy_init();
if (late_time_init)
late_time_init();
calibrate_delay();
pidmap_init();
pgtable_cache_init();
prio_tree_init();
anon_vma_init();
#ifdef CONFIG_X86
if (efi_enabled)
efi_enter_virtual_mode();
#endif
fork_init(num_physpages);
proc_caches_init();
buffer_init();
unnamed_dev_init();
security_init();
vfs_caches_init(num_physpages);建立專用的slab緩衝區佇列
radix_tree_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
check_bugs();


acpi_early_init(); /* before LAPIC and SMP init */


/* Do the rest non-__init'ed, we're now alive */
rest_init();

系統的初始化過程有很多函式,可以到具體用時在查,有很多函式只看名字就知道它的大致作用,就不說了。