歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核學習第三周 Linux啟動過程分析

Linux內核學習第三周 Linux啟動過程分析

日期:2017/3/2 17:15:52   编辑:Linux內核

一.知識點回顧

1.計算機的“三個法寶”:存儲程序計算機,中斷,函數調用堆棧;

2.操作系統的“兩把寶劍”:中斷上下文的切換(保存現場和恢復現場),進程上下文的切換。

二.實驗內容

1.啟動menuos

執行命令 cd LinuxKernel/
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

menuos啟動成功。

2.利用gdb跟蹤調試內核

  1. qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 關於-s和-S選項的說明:
  2. # -S freeze CPU at startup (use ’c’ to start execution)
  3. # -s shorthand for -gdb tcp::1234 若不想使用1234端口,則可以使用-gdb tcp:xxxx來取代-s選項

另打開一個shell窗口

  1. gdb
  2. (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加載符號表
  3. (gdb)target remote:1234 # 建立gdb和gdbserver之間的連接,按c 讓qemu上的Linux繼續運行
  4. (gdb)break start_kernel # 斷點的設置可以在target remote之前,也可以在之後

設置斷點rest_init()

三.總結

1.start_kernel函數

start_kernel函數完成linux內核的初始化。幾乎每個內核部件都是由這個函數進行初始化的。

調用sched_init函數初始化調度程序;

電泳trap_init函數和init_IRQ函數來完成IDT初始化;

調用time_init()函數來初始化系統日期和時間;

調用kernel_thread()函數為進程1創建內核線程,這個內核線程又會創建其他的內核線程並執行。

2init_task進程和idle進程

init_task進程在Linux中屬於一個比較特殊的進程,它是內核開發者人為制造出來的,而不是其他進程通過do_fork來完成。Linux在無進程概念的情況下將一直從初始化部分的代碼執行到start_kernel,然後再到其最後一個函數調用rest_init。從rest_init開始,Linux開始產生進程,因為init_task是靜態制造出來的,pid=0,它試圖將從最早的匯編代碼一直到start_kernel的執行都納入到init_task進程上下文中。在rest_init函數中,內核將通過下面的代碼產生第一個真正的進程(pid=1):

  1. static noinline void __init_refok rest_init(void)
  2. {
  3. ...
  4. kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
  5. ...
  6. cpu_idle();
  7. }

kernel_init函數最有意思的地方在於它會通過調用kernel_execve來執行根文件系統下的/sbin/init文件(所以此前系統根文件系統必須已經就緒),kernel_execve對用戶空間程序/sbin/init的調用發起自int $0x80,這是個從內核空間發起的系統調用,與call_usermodehelper函數本質上是完全一樣的。

而此時init_task的任務基本上已經完全結束了,它將淪落為一個idle task,事實上在更早前的sched_init()函數中,通過init_idle(current, smp_processor_id())函數的調用就已經把init_task初始化成了一個idle task,init_idle函數的第一個參數current就是&init_task,在init_idle中將會把init_task加入到cpu的運行隊列中,這樣當運行隊列中沒有別的就緒進程時,init_task(也就是idle task)將會被調用,它的核心是一個while(1)循環,在循環中它將會調用schedule函數以便在運行隊列中有新進程加入時切換到該新進程上。

Copyright © Linux教程網 All Rights Reserved