1、可以看到QEMU 已經運行而且被“凍結”。(有幾個文件沒有,不影響後續操作)
2、另外打開一個窗口,進入linuxkernel目錄,輸入gdb 回車
3、輸入:(gdb)file linux-3.18.6/vmlinux
(gdb)target remote:1234
(gdb)break start_kernel
4、輸入c 回車,可以看到內核繼續啟動,最後停在了start_kernel處:
更多gdb指令:
顯示和查找程序源代碼
(1)list :顯示10行代碼,但是我為什麼沒有顯示成功呢?
(2)list 5,10:顯示源文件第五行到第十行的代碼
(3)list t4.c:5,10:顯示源文件中第五行到第十行的代碼,在跳是含有多個源文件的次序時使用;
(4)list get_sum:顯示get_sum函數周圍的代碼//什麼叫周圍的代碼呢?
(5)list t4.c :get_sum:顯示源文件t4.c中第五行到第十行的代碼,在跳是含有多個源文件的次序時使用;
(6)如果在調試中運行linux命令,則可以在gdb的提示符下輸入shell命令. (gdb)shell ls
(7)search forward用來從當前行向前查找第一個匹配的字符串;
search get_sum forward get_sum
(8)reverse_search 用來從當前行想前查找第一個匹配的字符串: Example: reverse_search main
設置和管理斷點:
(1)以行號設置斷點:(gdb)break 7
(2)以函數名設置斷點:(gdb)break get_sum
(3)以條件表達式設置斷點:方法一:break 行號或者函數名 if 條件. Example: (gdb)break 7 if i==99
方法二:watch 條件表達式,下面是具體的舉例:
方法三:awatch;用來給表達式設置斷點,在表達式的值發生改變或者表達式的值杯讀取的時候,程序暫時停止;
(4).查看當前設置的斷點:info breakpoints
(5)使用“disable 斷點編號”命令可以是某個斷點失效,程序運行到該段點時不會停下來而是繼續運行。
(6)使用“enable 斷點編號”命令可以是某個斷點恢復有效。
徹底的刪除某個斷點,可以使用clear或者delete命令。
(1)clear:刪除程序中所有的斷點;
(2)clear 行號:刪除此行中的斷點
(3)clear 函數名:刪除該函數的斷點
(4)delete 斷點編號:刪除指定編號的斷點。如果一次要刪除多個斷點,各個斷點編號以空格隔開。
控制程序的執行:
(1)continue命令:讓程序繼續運行,直到下一個斷點或者運行完為止。格式:continue
(2)kill命令:用於結束當前程序的調試
(3)next和step命令
區別:如果遇到函數,next會把函數調用當作一條語句來執行,再次輸入next會執行函數調用後的語句;
而step則會跟蹤進入函數,一次一條的執行函數內的代碼,直到函數內的代碼執行完,在進行函數調用後的語句;
(4)nexti和stepi命令:用來單步執行一條機器指令,注意不是單步執行一條魚據。單步執行一條語句使用next和step命令。通常一條語句有多條機器指令構成的。
注意的是:gdb的一些命令可以簡寫,比如list可以用li來代替,continue命令可以用cont來代替。
5、繼續輸入 list start_kernel 查看start_kernel函數為中心上下10行的代碼
然後接著輸入list 查看後續的代碼(每輸入一次list,向後顯示10行)
我們繼續輸入list跟蹤start_kernel以後的代碼,看看後面的執行過程:
可以看到,在start_kernel之後是一大堆的初始化操作,初始化外設、時鐘、寄存器等。後面還有很多操作,這裡不作過多的截圖展示,
6、後面進入rest_init函數:
四、總結:
在start_kernel中調用了一系列的初始化函數,已完成內核本身的設置:設置與體系結構相關的環境、進程調度器初始化、控制台初始化、系統IRQ初始化、內存初始化等。在Start_kernel函數的最後調用了rest_init()函數,在rest_init中建立了init線程,並在最後調用cpu_idle()函數。
可以這樣理解:start_kernel最後clone出一個新的進程,也就是init進程,然後原來的進程就去執行cpu_idle()函數了,也就變成了idle進程,當發生一次進程調度後,init進程被調度運行。
核心進程init()主要進行一些外設初始化的工作包括SMP(Symmetric Multi-Processing 對稱多處理)的初始化,以及調用do_basic_setup()完成外設及其驅動程序的加載和初始化,當do_basic_setup()函數返回init() ,init() 又打開了、dev/console設備,重定向輸出文件到控制台,最後通過kernel——execve加載執行init程序。
追蹤到init後可以修改文件系統,比如把顯示的MENUOS修改為MYOS,修改quit指令,讓其退出文件系統等:
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
在init/initramfs.c文件中: