上次我們寫過了 Linux 啟動詳細流程,這次單獨解析 start_kernel 函數(shù)。
如下請參考注釋:
Linux kernel-6.1/init/main.c
asmlinkage?__visible?void?__init?__no_sanitize_address?start_kernel(void)
{
?char?*command_line;
?char?*after_dashes;
?set_task_stack_end_magic(&init_task);/*設置任務棧結束魔術數(shù),用于棧溢出檢測*/
?smp_setup_processor_id();/*跟?SMP?有關(多核處理器),設置處理器?ID*/
?debug_objects_early_init();/*?做一些和?debug?有關的初始化?*/
?init_vmlinux_build_id();
?cgroup_init_early();/*?cgroup?初始化,cgroup?用于控制?Linux?系統(tǒng)資源*/
?local_irq_disable();/*?關閉當前?CPU?中斷?*/
?early_boot_irqs_disabled?=?true;
?/*
??*?Interrupts?are?still?disabled.?Do?necessary?setups,?then
??*?enable?them.
??*?中斷關閉期間做一些重要的操作,然后打開中斷
??*/
?boot_cpu_init();/*?跟?CPU?有關的初始化?*/
?page_address_init();/*?頁地址相關的初始化?*/
?pr_notice("%s",?linux_banner);/*?打印?Linux?版本號、編譯時間等信息?*/
?early_security_init();
?
?/*?系統(tǒng)架構相關的初始化,此函數(shù)會解析傳遞進來的
?* ATAGS 或者設備樹(DTB)文件。會根據(jù)設備樹里面
?*?的?model?和?compatible?這兩個屬性值來查找
?* Linux 是否支持這個單板。此函數(shù)也會獲取設備樹
?*?中?chosen?節(jié)點下的?bootargs?屬性值來得到命令
?*?行參數(shù),也就是?uboot?中的?bootargs?環(huán)境變量的
?*?值,獲取到的命令行參數(shù)會保存到?command_line?中
?*/
?setup_arch(&command_line);
?setup_boot_config();
?setup_command_line(command_line);/*?存儲命令行參數(shù)?*/
?
?/*?如果只是?SMP(多核?CPU)的話,此函數(shù)用于獲取
?* CPU 核心數(shù)量,CPU 數(shù)量保存在變量 nr_cpu_ids 中。
?*/
?setup_nr_cpu_ids();
?setup_per_cpu_areas();/*?在?SMP?系統(tǒng)中有用,設置每個?CPU?的?per-cpu?數(shù)據(jù)?*/
?smp_prepare_boot_cpu();?/*?arch-specific?boot-cpu?hooks?*/
?boot_cpu_hotplug_init();
?build_all_zonelists(NULL);/*?建立系統(tǒng)內存頁區(qū)(zone)鏈表?*/
?page_alloc_init();/*?處理用于熱插拔?CPU?的頁?*/
?/*?打印命令行信息?*/?
?pr_notice("Kernel?command?line:?%sn",?saved_command_line);
?/*?parameters?may?set?static?keys?*/
?jump_label_init();
?parse_early_param();/*?解析命令行中的?console?參數(shù)?*/
?after_dashes?=?parse_args("Booting?kernel",
??????static_command_line,?__start___param,
??????__stop___param?-?__start___param,
??????-1,?-1,?NULL,?&unknown_bootoption);
?print_unknown_bootoptions();
?if?(!IS_ERR_OR_NULL(after_dashes))
??parse_args("Setting?init?args",?after_dashes,?NULL,?0,?-1,?-1,
??????NULL,?set_init_arg);
?if?(extra_init_args)
??parse_args("Setting?extra?init?args",?extra_init_args,
??????NULL,?0,?-1,?-1,?NULL,?set_init_arg);
?/*?Architectural?and?non-timekeeping?rng?init,?before?allocator?init?*/
?random_init_early(command_line);
?/*
??*?These?use?large?bootmem?allocations?and?must?precede
??*?kmem_cache_init()
??*/
?setup_log_buf(0);/*?設置?log?使用的緩沖區(qū)*/
?vfs_caches_init_early();?/*?預先初始化?vfs(虛擬文件系統(tǒng))的目錄項和索引節(jié)點緩存*/
?sort_main_extable();/*?定義內核異常列表?*/
?trap_init();/*?完成對系統(tǒng)保留中斷向量的初始化?*/
?mm_init();/*?內存管理初始化?*/
?ftrace_init();
?/*?trace_printk?can?be?enabled?here?*/
?early_trace_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();/*?初始化調度器,主要是初始化一些結構體?*/
?if?(WARN(!irqs_disabled(),
???"Interrupts?were?enabled?*very*?early,?fixing?itn"))
??local_irq_disable();/*?檢查中斷是否關閉,如果沒有的話就關閉中斷?*/
?radix_tree_init();/*?基數(shù)樹相關數(shù)據(jù)結構初始化?*/
?maple_tree_init();
?/*
??*?Set?up?housekeeping?before?setting?up?workqueues?to?allow?the?unbound
??*?workqueue?to?take?non-housekeeping?into?account.
??*/
?housekeeping_init();
?/*
??*?Allow?workqueue?creation?and?work?item?queueing/cancelling
??*?early.??Work?item?execution?depends?on?kthreads?and?starts?after
??*?workqueue_init().
??*/
?workqueue_init_early();
?rcu_init();/*?初始化?RCU,RCU?全稱為?Read?Copy?Update(讀-拷貝修改)?*/
?/*?Trace?events?are?available?after?this?*/
?trace_init();/*?跟蹤調試相關初始化?*/
?if?(initcall_debug)
??initcall_debug_enable();
?context_tracking_init();
?/*?init?some?links?before?init_ISA_irqs()?*/
?
?/*?初始中斷相關初始化,主要是注冊?irq_desc?結構體變
?*?量,因為 Linux 內核使用 irq_desc 來描述一個中斷。
?*/
?early_irq_init();
?init_IRQ();/*?中斷初始化?*/
?tick_init();/*?tick?初始化?*/
?rcu_init_nohz();
?init_timers();/*?初始化定時器?*/
?srcu_init();
?hrtimers_init();/*?初始化高精度定時器?*/
?softirq_init();/*?軟中斷初始化?*/
?timekeeping_init();
?time_init();/*?初始化系統(tǒng)時間?*/
?/*?This?must?be?after?timekeeping?is?initialized?*/
?random_init();
?/*?These?make?use?of?the?fully?initialized?rng?*/
?kfence_init();
?boot_init_stack_canary();
?perf_event_init();
?profile_init();
?call_function_init();
?WARN(!irqs_disabled(),?"Interrupts?were?enabled?earlyn");
?early_boot_irqs_disabled?=?false;
?local_irq_enable();/*?使能中斷?*/
?kmem_cache_init_late();/*?slab?初始化,slab?是?Linux?內存分配器?*/
?/*
??*?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.
??*/
?/*?初始化控制臺,之前?printk?打印的信息都存放
??*?緩沖區(qū)中,并沒有打印出來。只有調用此函數(shù)
??*?初始化控制臺以后才能在控制臺上打印信息。
??*/
?console_init();
?if?(panic_later)
??panic("Too?many?boot?%s?vars?at?`%s'",?panic_later,
????????panic_param);
?lockdep_init();
?/*
??*?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();/*?鎖自測?*/?
?/*
??*?This?needs?to?be?called?before?any?devices?perform?DMA
??*?operations?that?might?use?the?SWIOTLB?bounce?buffers.?It?will
??*?mark?the?bounce?buffers?as?decrypted?so?that?their?usage?will
??*?not?cause?"plain-text"?data?to?be?decrypted?when?accessed.
??*/
?mem_encrypt_init();
#ifdef?CONFIG_BLK_DEV_INITRD
?if?(initrd_start?&&?!initrd_below_start_ok?&&
?????page_to_pfn(virt_to_page((void?*)initrd_start))?<?min_low_pfn)?{
??pr_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
?setup_per_cpu_pageset();
?numa_policy_init();
?acpi_early_init();
?if?(late_time_init)
??late_time_init();
?sched_clock_init();
?/*?測定?BogoMIPS?值,可以通過?BogoMIPS?來判斷?CPU?的性能
?* BogoMIPS 設置越大,說明 CPU 性能越好。
?*/
?calibrate_delay();
?pid_idr_init();
?anon_vma_init();/*?生成?anon_vma?slab?緩存?*/?
#ifdef?CONFIG_X86
?if?(efi_enabled(EFI_RUNTIME_SERVICES))
??efi_enter_virtual_mode();
#endif
?thread_stack_cache_init();
?cred_init();/*?為對象的每個用于賦予資格(憑證)?*/
?fork_init();/*?初始化一些結構體以使用?fork?函數(shù)?*/
?proc_caches_init();/*?給各種資源管理結構分配緩存?*/
?uts_ns_init();
?key_init();/*?初始化密鑰?*/
?security_init();/*?安全相關初始化?*/
?dbg_late_init();
?net_ns_init();
?vfs_caches_init();/*?虛擬文件系統(tǒng)緩存初始化?*/
?pagecache_init();
?signals_init();/*?初始化信號?*/
?seq_file_init();
?proc_root_init();/*?注冊并掛載?proc?文件系統(tǒng)?*/
?nsfs_init();
?/*?初始化?cpuset,cpuset?是將?CPU?和內存資源以邏輯性
?*?和層次性集成的一種機制,是?cgroup?使用的子系統(tǒng)之一
?*/
?cpuset_init();
?cgroup_init();/*?初始化?cgroup?*/
?taskstats_init_early();/*?進程狀態(tài)初始化?*/
?delayacct_init();
?poking_init();
?check_bugs();/*?檢查寫緩沖一致性?*/
?acpi_subsystem_init();
?arch_post_acpi_subsys_init();
?kcsan_init();
?/*?Do?the?rest?non-__init'ed,?we're?now?alive?*/
?/*?調用?rest_init?函數(shù)?*/
?/*?創(chuàng)建?init、kthread、idle?線程?*/
?arch_call_rest_init();
?prevent_tail_call_optimization();
}
閱讀全文