首先,進入實驗樓提供的虛擬機環境,咱們仍是使用QEMU來啓動內核:linux
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
其中,-S參數能夠在啓動內核時「凍結」CPU,而-s參數能夠在虛擬運行的內核中搭建一個gdb服務器,默認端口爲1234,也能夠使用-gdb tcp:xxxx來取代-s選項。這樣咱們就能夠經過gdb調試內核啓動過程了。shell
打開另一個終端,啓動gdb,咱們來連接內核並添加幾個斷點:服務器
(gdb) file linux-3.18.6/vmlinux # 在gdb界面中targe remote以前加載符號表 (gdb) target remote:1234 # 創建gdb和gdbserver之間的鏈接,按c讓qemu上的Linux繼續運行 (gdb) break start_kernel # 斷點的設置能夠在target remote以前,也能夠在以後 (gdb) break init_kernel (gdb) break trap_init (gdb) break rest_init (gdb) break run_init_process
設置完成後,就能夠按c+回車來執行程序到下一個斷點了,也能夠用list命令列出源碼上下文的內容。如下就是個人啓動過程:tcp
執行到init/main.c的start_kernel:函數
執行到kernel_init:學習
執行到run_init_process:spa
init進程啓動完畢,進入命令行:命令行
總結:經過此次學習,對從Linux內核從初始化到init進程啓動有了一個初步的概念。Linux從無進程狀態下啓動start_kernel,直到它調用rest_init()開始產生進程。在rest_init()中,經過init_task產生idle進程,其pid=0。以後kernel在rest_init()中的這一句生成pid=1的進程,也是第一個用戶進程:調試
kernel_thread(kernel_init, NULL, CLONE_FS);
當運行隊列中沒有別的就緒進程時,init_task(也就是idle)將會被調用,它的核心是一個while(1)循環,在循環中它將會調用schedule函數以便在運行隊列中有新進程加入時切換到該新進程上。rest