1. 程式人生 > >《Linux核心原理與分析》第四周作業

《Linux核心原理與分析》第四周作業

課本:第3章 MenuOS的構造 內容總結

  • 計算機的“三大法寶”
    • 儲存程式計算機
    • 函式呼叫堆疊
    • 中斷
  • 作業系統的“兩把寶劍”
    • 中斷上下文切換:儲存現場和恢復現場
    • 程序上下文切換
      在接觸linux核心原始碼時,linux是基於一個穩定版的核心Linux-3.18.6。其核心原始碼的目錄結構如下:

      其中,arch目錄是與體系結構相關的子目錄列表,裡面存放了許多CPU體系結構的相關程式碼。arch目錄中的程式碼在linux核心程式碼中佔比相當龐大,主要是因為arch目錄中的程式碼可以使linux核心支援不同的CPU和體系結構。本課程實驗是基於x86構架,所以只需要關心x86目錄下的內容。
      除了arch目錄以外,還有如下幾個關鍵目錄:
  • block:存放linux儲存體系中關於塊裝置管理的程式碼。
  • crypto:存放常見的加密演算法的C語言程式碼。
  • Documentation:存放一些文件。
  • drivers:驅動目錄,裡面分門別類地存放了linux核心支援的所有硬體裝置的驅動原始碼。
  • firmware:韌體。
  • fs:即file system(檔案系統),裡面列出了linux支援的各種檔案系統的實現。
  • include:標頭檔案目錄,存放公共標頭檔案。
  • init:初始化,存放linux核心啟動時的初始化程式碼,其中main.c檔案就在這個目錄下,這是整個linux核心啟動的起點,main.c中的start_kernel函式是初始化linux核心啟動的起點。
  • ipc:即inter-process communication(程序間通訊),其目錄下為linux支援的IPC程式碼實現。
  • kernel:即linux核心,這個資料夾下存放著核心本身需要的一些核心程式碼檔案。
  • lib:共用的庫檔案,裡面是一些公用的庫函式。在核心程式設計中不能使用C語言的標準庫函式,這裡的lib目錄下的庫函式就是來替代那些標準庫函式的。
  • mm:即memory management(記憶體管理),存放linux的記憶體管理程式碼。
  • net:該目錄下是網路相關的程式碼,例如TCP/IP協議棧等。
  • 此外還有一些與聲音、安全、指令碼、工具相關的目錄
    瞭解了核心的基本結構和基本功能,為下面的實驗進行打下了基礎和鋪墊。

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

使用實驗樓的shell環境,其已經在虛擬機器中搭建好了menuOS,所以我們通過兩個簡單的命令就可以把linux系統和一個簡單的檔案系統執行起來:

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

其中,qemu模擬kernel;bzImage是vmLinux經過gzip壓縮後的檔案;vmLinux是編譯出來的最原始的核心ELF檔案;initrd是“initial ramdisk”的縮寫,是用來初始化記憶體根檔案系統。根檔案系統一般包括記憶體根檔案系統和磁碟檔案系統,普通linux使用者一般感受不到這個記憶體根檔案系統的存在,因為在普通linux系統在啟動時,是boot loader將儲存介質中的initrd檔案載入到記憶體,核心啟動時先訪問initrd檔案系統,然後再切換到磁碟檔案系統。本次實驗簡化為只使用了initrd根檔案系統,建立了一個rootfs.img,其中只有一個init功能,用menu程式替代init。核心啟動完成後進入menu程式。效果如下圖所示:

可以看到,menu專案支援3個命令:help、version和quit。
下面,使用gdb跟蹤除錯核心,輸入以下命令:

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

效果如下:

水平分割視窗,啟動gdb,輸入以下命令:

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之前,也可以在之後

執行效果如下:

在start_kernel處設定了斷點,使用continue命令讓程式執行到斷點位置,如下圖所示:

可以看到在程式執行到start_kernel斷點處,qemu視窗中的執行效果。下面再在rest_init處為核心程式碼增加一個斷點,執行效果如下: