linux内核学习1 start_kernel()

默认为3.9.1版本内核

为什么要从这个函数开始?个人习惯吧,我比较懒,就从内核初始化入口开始。

-----------------------------------------------------------------------------------------------------

先看一张图,start_kernel函数调用关系图:

linux内核学习1 start_kernel()_第1张图片

为啥要看这个?我想知道谁掉用了它!挨个看一下比较好~

void __init x86_64_start_reservations(char *real_mode_data)
{
	/* version is always not zero if it is copied */
	if (!boot_params.hdr.version)
		copy_bootdata(__va(real_mode_data));//复制bootdata?

	reserve_ebda_region();//预留dbda区域?

	start_kernel();
}


void __init x86_64_start_kernel(char * real_mode_data)
{
	int i;

	/*
	 * Build-time sanity checks on the kernel image and module
	 * area mappings. (these are purely build-time and produce no code)
	 */
	BUILD_BUG_ON(MODULES_VADDR < KERNEL_IMAGE_START);
	BUILD_BUG_ON(MODULES_VADDR-KERNEL_IMAGE_START < KERNEL_IMAGE_SIZE);
	BUILD_BUG_ON(MODULES_LEN + KERNEL_IMAGE_SIZE > 2*PUD_SIZE);
	BUILD_BUG_ON((KERNEL_IMAGE_START & ~PMD_MASK) != 0);
	BUILD_BUG_ON((MODULES_VADDR & ~PMD_MASK) != 0);
	BUILD_BUG_ON(!(MODULES_VADDR > __START_KERNEL));
	BUILD_BUG_ON(!(((MODULES_END - 1) & PGDIR_MASK) ==
				(__START_KERNEL & PGDIR_MASK)));
	BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) <= MODULES_END);

	/* Kill off the identity-map trampoline */
	reset_early_page_tables();

	/* clear bss before set_intr_gate with early_idt_handler */
	clear_bss();

	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
		set_intr_gate(i, &early_idt_handlers[i]);
	load_idt((const struct desc_ptr *)&idt_descr);

	copy_bootdata(__va(real_mode_data));

	/*
	 * Load microcode early on BSP.
	 */
	load_ucode_bsp();

	if (console_loglevel == 10)
		early_printk("Kernel alive\n");

	clear_page(init_level4_pgt);
	/* set init_level4_pgt kernel high mapping*/
	init_level4_pgt[511] = early_level4_pgt[511];

	x86_64_start_reservations(real_mode_data);
}

信息量太大了,好吧,我承认我看不懂。。。等我能看懂了再来更新之。

下面直接看start_kernel函数:

asmlinkage void __init start_kernel(void)
{
	char * command_line;
	extern const struct kernel_param __start___param[], __stop___param[];

	/*
	 * Need to run as early as possible, to initialize the
	 * lockdep hash:
	 */
	lockdep_init();/*内核调试模块,用于检查内核互斥机制潜在的死锁问题*/
	smp_setup_processor_id();/* 指定当前的cpu的逻辑号,这个函数对应于对称多处理器的设置,当系统中只有一个cpu的情况,此函数为空,什么也不做 */  
	debug_objects_early_init();

	/*
	 * Set up the the initial canary ASAP:
	 */
	boot_init_stack_canary();/*初始化栈canary值,canary值用于防止栈溢出攻击的堆栈的保护字*/

	cgroup_init_early();/*一组进程的行为控制,做数据结构和其中链表的初始化*/

	local_irq_disable();/*关闭当前CUP中断*/
	early_boot_irqs_disabled = true;

/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
	tick_init();/*初始化内核时钟系统*/
	boot_cpu_init();/*激活当前CPU*/
	page_address_init();/*高端内存相关,未定义的话为空函数*/
	printk(KERN_NOTICE "%s", linux_banner);
	setup_arch(&command_line);/*内核架构相关初始化函数*/
	mm_init_owner(&init_mm, &init_task);/*初始化init_mm结构体*/
	mm_init_cpumask(&init_mm);
	setup_command_line(command_line);/*对command_line进行备份与保存*/
	setup_nr_cpu_ids();/*以下三个函数针对SMP处理器,不是SMP处理器都为空函数*/
	setup_per_cpu_areas();
	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */

	build_all_zonelists(NULL, NULL);/*设置内存相关节点和其中的内存域数据结构*/
	page_alloc_init();
	/*打印与解析内核启动参数*/
	printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
	parse_early_param();
	parse_args("Booting kernel", static_command_line, __start___param,
		   __stop___param - __start___param,
		   -1, -1, &unknown_bootoption);

	jump_label_init();

	/*
	 * These use large bootmem allocations and must precede
	 * kmem_cache_init()
	 */
	setup_log_buf(0);/*使用bootmem分配一个启动信息的缓冲区*/
	pidhash_init();/*使用bootmem分配并初始化PID散列表*/
	vfs_caches_init_early();/*前期VFS缓存初始化*/
	sort_main_extable();/*对内核异常表进行排序*/
	trap_init();/*对内核陷阱异常经行初始化,ARM架构中位空函数*/
	mm_init();/*初始化内核内存分配器,启动信息中的内存信息来自此函数中的mem_init函数*/

	/*
	 * 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();/*初始化调度器数据结构并创建运行队列*/
	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();/*禁用抢占和中断,早期启动时期,调度是极其脆弱的*/
	if (!irqs_disabled()) {
		printk(KERN_WARNING "start_kernel(): bug: interrupts were "
				"enabled *very* early, fixing it\n");
		local_irq_disable();
	}
	idr_init_cache();/*为IDR机制分配缓存*/
	perf_event_init();/*CPU性能检测机制初始化*/
	rcu_init();/*内核RCU机制初始化*/
	radix_tree_init();/*内核radix树算法初始化*/
	/* init some links before init_ISA_irqs() */
	early_irq_init();/*前期外部中断描述符初始化*/
	init_IRQ();/*架构相关中断初始化*/
	init_timers();/*以下5个函数是软中断和内核时钟机制初始化*/
	hrtimers_init();
	softirq_init();
	timekeeping_init();
	time_init();
	profile_init();/*profile子系统初始化,内核的性能调试工具*/
	call_function_init();
	if (!irqs_disabled())
		printk(KERN_CRIT "start_kernel(): bug: interrupts were "
				 "enabled early\n");
	early_boot_irqs_disabled = false;
	local_irq_enable();/*开启总中断*/

	kmem_cache_init_late();/*slab分配器后期初始化*/

	/*
	 * 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);

	lockdep_info();/*打印lockdep调试模块信息*/

	/*
	 * Need to run this when irqs are enabled, because it wants
	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
	 * too:
	 */
	locking_selftest();
	/*检查initrd的位置是否符合要求*/
#ifdef CONFIG_BLK_DEV_INITRD
	if (initrd_start && !initrd_below_start_ok &&
	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
		printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
		    "disabling it.\n",
		    page_to_pfn(virt_to_page((void *)initrd_start)),
		    min_low_pfn);
		initrd_start = 0;
	}
#endif
	page_cgroup_init();
	debug_objects_mem_init();
	kmemleak_init();/*内存泄露检测机制的初始化*/
	setup_per_cpu_pageset();/*设置每个CPU的页组并初始化*/
	numa_policy_init();/*分一致性内存访问(NUMA)初始化*/
	if (late_time_init)
		late_time_init();
	sched_clock_init();/*初始化调度时钟*/
	calibrate_delay();
	pidmap_init();/*PID分配映射初始化*/
	anon_vma_init();
#ifdef CONFIG_X86
	if (efi_enabled(EFI_RUNTIME_SERVICES))
		efi_enter_virtual_mode();
#endif
	thread_info_cache_init();
	cred_init();/*任务信用系统初始化*/
	fork_init(totalram_pages);/*进程创建机制初始化*/
	proc_caches_init();/*进程caches初始化*/
	buffer_init();/*缓存系统初始化,创建缓存头空间,并检查其大小限制*/
	key_init();/*内核密钥管理系统初始化*/
	security_init();/*内核安全框架初始化*/
	dbg_late_init();/*内核调试系统后期初始化*/
	vfs_caches_init(totalram_pages);/*虚拟文件系统缓存初始化*/
	signals_init();/*信号管理系统初始化*/
	/* rootfs populating might need page-writeback */
	page_writeback_init();/*页回写机制初始化*/
#ifdef CONFIG_PROC_FS
	proc_root_init();/*proc文件系统初始化*/
#endif
	cgroup_init();/*control group正式初始化*/
	cpuset_init();/*CPUSET初始化*/
	taskstats_init_early();/*任务状态早期初始化函数,为任务获取高速缓存并初始化互斥机制*/
	delayacct_init();/*任务延迟机制初始化*/

	check_bugs();

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

	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
		efi_late_init();
		efi_free_boot_services();
	}

	ftrace_init();

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

参考文章: http://blog.chinaunix.net/uid-20746260-id-3176497.html

你可能感兴趣的:(linux内核学习1 start_kernel())