1. 程式人生 > >kexec 內核快速啟動流程分析

kexec 內核快速啟動流程分析

-- 令行 並且 內存 tab 執行過程 family use -a

一、命令行

1. kexec -l $kpwd --append="$arg"

其中$kpwd =目標內核的路徑

  $arg =傳給內核的參數,與/proc/cmdline一致時表示重啟現有內核

2. kexec -e

二、執行過程

1. kexec-tools執行過程

kexec 的main函數解析參數,kexec -l 解析為調用my_load函數。

my_load函數根據路徑參數讀取內核文件到kernel_buf中,然後執行通用函數file_type[i].load,mips下對應elf_mips_load。

elf_mips_load函數主要內容是解析elf格式的kernel文件,並將所有信息存放在info

中,主要是對elf文件的ELF header, Program header table進行解析:

1) build_elf_exec_info(buf, len, &ehdr, 0) 根據header到解析elf文件到ehdr中;

2) elf_exec_load(&ehdr, info) 解析各段內容到info中,具體實現為調用add_segment()函數,與此同時給出了kernel的入口地址。

3) cmdline_buf中存放的是傳給內核的參數,也需要用add_buffer添加進info內。

4) 刪除源碼中的device tree部分。

將kernel文件解析到info

中之後,回到my_load函數進行一些檢驗等操作,然後調用kexec_load(info.entry,info.nr_segments, info.segment,info.kexec_flags),進行系統調用:syscall(__NR_kexec_load, entry, nr_segments, segments, flags)

2. kexec_load系統調用執行過程

內核在syscall_table.S,syscalls.h等內註冊了kexec_load系統調用,宏展開後最終調用kernel/kexec.c文件的SYSCALL_DEFINE4(kexec_load...)函數。該函數主要功能就是把新的內核文件裝入內存中。

kimage_alloc_init初始化內存分配,主要初始化入口信息,並使用copy_from_user函數把傳入的內核數據拷貝到image內,然後分配一張控制頁(control_code_page)。

接下來調用machine_kexec_prepare,這個函數回調之前註冊過的loongson_kexec_prepare函數,該函數是對傳入參數的類似bootloader的處理。

最主要的函數是kimage_load_segment,該函數把內核段打散成頁,先調用alloc_pages分配一張內核頁(在mips64中分配空間為0x8000 0000 0000 0000到

0xC000 0000 0000 0000共0x4000 0000 0000 0000大小的空間內),再調用kimage_add_page將該頁加入到image->entry指向的內存區域,然後進行內核數據拷貝,循環直到所有頁都分配完畢。

3. reboot執行過程

當執行kexec -e 時,進行reboot系統調用,並由kernel_kexec接管。該函數先進行重啟之前例行操作,如kernel_restart_prepare, migrate_to_reboot_cpu,machine_shutdown等,最後是調用machine_kexec(kexec_image)進行kexec模式重啟。

之前準備好的kernel被打散到內核內存中,這個函數將完成kernel的重定位,並且從image->start即entry開始執行。要做到這一點,該函數首先把entry的地址賦值給kexec_start_address,把存在image->head的地址賦給kexec_indirection_page,然後將一段內核重定位的匯編代碼使用memcpy拷貝至control_code_page內,最後執行該函數即轉入匯編執行。匯編代碼以kexec_indirection_page為索引,負責將之前分配到內存的所有頁面拷貝至目的內存中,最後一條跳轉指令跳至kexec_start_address處執行。

kexec 內核快速啟動流程分析