linux下kernel啟動流程
阿新 • • 發佈:2018-11-10
點選檢視大圖
head.S 初始化完成後跳轉到 start_kernel 入口:
kernel-3.18/init/main.c:505:asmlinkage __visible void __init start_kernel(void)
START => 原始碼分析:
這裡要乾的事情非常多而複雜,如果需要全部理解整個過程的話需要強大的知識背景做支撐以及對核心有著深入的理解才行,基於學習的循序漸進的考量,這裡我們重點關注device driver的啟動載入流程機制.
-
asmlinkage __visible
void __
init start_kernel(void)
-
{
-
char
*command_line;
-
char
*after_dashes;
-
-
/
*
-
*
Need
to run as early as possible, to initialize the
-
*
lockdep hash:
-
*
/
-
-
/
*
有些體系結構有自己的start_kernel入口,這裡保證只初始化一次
-
系統雜湊表chainhash_table
*
/
-
lockdep_init();
-
-
set_task_stack_end_magic(&init_task);
-
-
/
*
獲取當前執行cpu的id
*
/
-
smp_setup_processor_id();
-
-
/
*
物件除錯支援初始化
*
/
-
debug_objects_early_init();
-
-
/
*
-
*
Set up the the initial canary ASAP:
-
*
/
-
-
/
*
初始化棧canary值,canary值用於防止棧溢位攻擊,這裡不太明白詳細...
*
/
-
boot_init_stack_canary();
-
-
/
*
cgrop :將一組任務在一個或多個子系統中與一組引數關聯,機制有點複雜...
*
/
-
cgroup_init_early();
-
-
/
*
關閉中斷,因為很多初始化的工作不能被中斷
*
/
-
local_irq_disable();
-
early_boot_irqs_disabled =
true;
-
-
/
*
-
*
Interrupts are still disabled. Do necessary setups, then
-
*
enable them
-
*
/
-
-
/
*
獲取當前cpu id,啟用之
*
/
-
boot_cpu_init();
-
-
/
*
高階記憶體相關,建立核心對映所需的散列表
*
/
-
page_address_init();
-
pr_notice(
"%s", linux_banner);
-
-
/
*
體系結構相關初始化,沒種體系結構都有特有的初始化入口
*
/
-
setup_arch(&command_line);
-
-
/
*
cpu遮蔽位清零
*
/
-
mm_init_cpumask(&init_mm);
-
-
/
*
將命令列引數儲存到 static_command_line 中
*
/
-
setup_command_line(command_line);
-
-
setup_nr_cpu_ids();
-
setup_per_cpu_areas();
-
smp_prepare_boot_cpu();
/
*
arch-specific boot-cpu hooks
*
/
-
-
/
*
建立系統記憶體頁區(zone)連結串列
*
/
-
build_all_zonelists(
NULL,
NULL);
-
-
/
*
cpu熱拔插相關, 這名字取得...
*
/
-
page_alloc_init();
-
-
pr_notice(
"Kernel command line: %s\n", boot_command_line);
-
-
/
*
解析啟動命令列引數
*
/
-
parse_early_param();
-
after_dashes = parse_args(
"Booting kernel",
-
static_command_line, __start___param,
-
__stop___param - __start___param,
-
-1,
-1, &unknown_bootoption);
-
if (!IS_ERR_OR_NULL(after_dashes))
-
parse_args(
"Setting init args", after_dashes,
NULL,
0,
-1,
-1,
-
set_init_arg);
-
-
/
*
執行跳轉指令?
*
/
-
jump_label_init();
-
-
/
*
-
*
These use large bootmem allocations and must precede
-
*
kmem_cache_init()
-
*
/
-
-
/
*
設定 log輸出緩衝buf
*
/
-
setup_log_buf(
0);
-
-
/
*
初始化和分配pid散列表
*
/
-
pidhash_init();
-
-
/
*
建立虛擬檔案系統(vfs)需要各種資料結構的快取
*
/
-
vfs_caches_init_early();
-
-
/
*
核心異常表排序
*
/
-
sort_main_extable();
-
-
/
*
異常捕獲設定初始化,跟體系結構相關,arm架構的實現是空函式
*
/
-
trap_init();
-
-
/
*
核心記憶體分配器初始化,初始化slab機制分配器和vmalloc機制
*
/
-
mm_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 (WARN(!irqs_disabled(),
-
"Interrupts were enabled *very* early, fixing it\n"))
-
local_irq_disable();
-
-
/
*
為 idr(一種將一個整數ID號和一個指標關聯在一起的機制) 機制建立cache
*
/
-
idr_init_cache();
-
-
/
*
rcu(read-copy-update, 核心鎖機制一類)機制初始化
*
/
-
rcu_init();
-
-
/
*
上下文tracking機制 ? 該機制被 CONFIG_CONTEXT_TRACKING_FORCE 包住了
*
/
-
context_tracking_init();
-
-
/
*
為核心基數樹演算法分配記憶體,運用於記憶體頁查詢
*
/
-
radix_tree_init();
-
/
*
init some links before init_ISA_irqs()
*
/
-
-
/
*
初始化體系結構相關irq,建立irq描述符,插入到基數屬連結串列 irq_desc_tree 中管理
*
/
-
early_irq_init();
-
init_IRQ();
-
-
/
*
時鐘相關初始化
*
/
-
tick_init();
-
rcu_init_nohz();
-
init_timers();
-
hrtimers_init();
-
softirq_init();
-
timekeeping_init();
-
time_init();
-
-
/
*
程序排程時鐘初始化
*
/
-
sched_clock_postinit();
-
-
/
*
cpu 效能相關monitor
*
/
-
perf_event_init();
-
-
/
*
gdb等debug工具設定相關
*
/
-
profile_init();
-
-
/
*
smp下跨cpu的函式傳遞初始化
*
/
-
call_function_init();
-
WARN(!irqs_disabled(),
"Interrupts were enabled early\n");
-
early_boot_irqs_disabled =
false;
-
-
/
*
使能中斷
*
/
-
local_irq_enable();
-
-
/
*
slab 分配器後期初始化
*
/
-
kmem_cache_init_late();
-
-
/
*
-
*
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.
-
*
/
-
-
/
*
終端控制檯輸出初始化
*
/
-