跟蹤分析Linux核心的啟動過程

2021-07-10 11:31:34 字數 1793 閱讀 8696

在linux作業系統中,系統的啟動都是從start_kernel()這個函式開始的。start_kernel()是核心的彙編與c語言的交接點,在該函式以前,核心的**都是用彙編寫的,完成一些最基本的初始化與環境設定工作,比如核心**載入記憶體並解壓縮(現在的核心一般都經過壓縮),cpu 的最基本初始化,為c**的執行設定環境(c**的執行是有一定環境要求的,比如stack的設定等)。這裡乙個不太確切的比喻是start_kernel()就像是c**中的main()。我們知道對應用程式設計師而言,main()是他的入口,但實際上程式的入口是被包在了c庫中,在鏈結階段,linker會把它鏈結入你的程式中。而它的任務中有一項就是為main()準備執行環境。main()中的argc,argv 等都不是平白無故來的,都是在呼叫main()以前的**做的準備。

下面我們用gdb在linux下進行跟蹤除錯:

進入核心檔案目錄使用qemu -kernel linux-3.18.6/arch/x86/boot/bzimage -initrd rootfs.img -s -s命令啟動核心,-s選項表示在cpu初始化時凍結核心。

在終端分割出乙個視窗用於gdb除錯

file linux-3.18.6/vmlinux # 在gdb介面中targe remote之前載入符號表

target remote:1234 # 建立gdb和gdbserver之間的連線,按c 讓qemu上的linux繼續執行

break start_kernel # 斷點的設定可以在target remote之前,也可以在之後

使用break命令在start_kernel處設定斷點,按c繼續執行核心到斷點位置

此時使用list命令可以看到start_kernel位置的**

//該函式是linux核心的入口,其前面的**都是用彙編編寫

總結:在start_kernel()中linux將完成整個系統的核心初始化。核心初始化的最後一步就是啟動init程序這個所有程序的祖先。在start_kerkel()中函式的最後一步是執行rest_init這個函式,該函式的第一條語句為

kernel_thread(init, null, clone_fs | clone_sighand);

/*建立乙個核心執行緒,實際上就是核心程序,linux核心是不支援類似windows nt一樣的執行緒概念的。linux本質上只支援程序。這裡的init只是乙個函式,不要與init process搞混淆了。*/

核心建立的核心執行緒(系統中第乙個核心態程序)執行init()函式,在init()函式的結尾就是啟動init程序。這裡的run_init_process就是通過 execve()來執行 init 程式。這裡首先執行「/sbin/init」,如果失敗再執行「/etc/init」,然後是「/bin/init」,然後是「/bin/sh」(也就是說,init 可執行檔案可以放在上面**中尋找的 4 個目錄中都可以),如果都失敗,則可以通過在系統啟動時在新增的啟動引數來指定 init,比如 init=/home/wzhou/init。這裡是核心初始化結束並開始使用者態初始化的陰陽界。即使用者態第乙個程序由此建立!

跟蹤分析Linux核心的啟動過程

說明 在實驗樓裡做該實驗時,發現實驗樓環境老卡死,折騰幾個小時都如此,根本沒有辦法完成作業。因此此處只能提供一張截圖。後面的內容都是根據老師的課程整理出來的。開啟shell 使用gdb跟蹤除錯核心 gdb file linux 3.18.6 vmlinux 說明 在gdb介面中targe remot...

跟蹤分析Linux核心的啟動過程

1.除錯gdb 1 執行qemu 2 執行gdb並鏈結remote 3 設定斷點break start kernel,break rest init 2.分析start kernel 在斷點處停止 分析start kernel asmlinkage visible void init start k...

實驗三 跟蹤分析Linux核心的啟動過程

linux核心分析 mooc課程 一 linux核心原始碼 arch目錄下儲存有各個平台的源 fs檔案系統linux核心的原始碼放在kernel目錄中。原始碼的目錄結構如下圖所示 二 乙個簡單的linux系統menuos 三 使用gdb跟蹤除錯linux核心的方法 s freeze cpu at s...