萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux 核心原始碼閱讀入門:從架構認識到新增系統呼叫實作

Linux 核心原始碼龐大複雜,初學者常不知從何下手。本文不探討深奧機制,而是提供一套入門閱讀方法:先理解原始碼目錄架構,再透過「新增一個系統呼叫」的完整實作,掌握核心分析的基本脈絡。

一、核心原始碼目錄架構

核心原始碼通常位於 /usr/src/linux,版本號慣例:偶數為穩定版(如 2.2.5),奇數為開發版。主要頂層目錄說明:

  • arch/:硬體架構相關程式碼,i386 對應 x86 平台。
  • include/:核心編譯所需標頭檔,include/linux 為架構無關,include/asm-i386 為 x86 專用。
  • init/:核心初始化程式碼(main.c、Version.c),研究核心運作的最佳切入點。
  • mm/:架構無關的記憶體管理(分頁配置/釋放等)。
  • kernel/:核心主要函數實作,sched.c 為排程器核心。
  • drivers/:所有裝置驅動程式,依類型分子目錄(block、char、net 等)。
  • fs/:各類檔案系統實作(ext2、fat 等)。
  • net/、ipc/、lib/、scripts/:網路、進程通訊、核心函式庫、配置腳本。

各目錄下的 Makefile 與 .depend 有助於理解檔案相依關係,README 則提供目錄用途說明。

二、實戰:為核心新增一個系統呼叫

平台環境

  • 硬體:Intel Pentium II
  • 作業系統:Red Hat Linux 6.0
  • 核心版本:2.2.5

核心啟動與系統呼叫機制追蹤

  1. 開機流程:BIOS → MBR → arch/i386/kernel/setup.S(保護模式初始化) → arch/i386/kernel/head.S(建立 IDT 表,含系統呼叫總入口 system_call)。
  2. 第一個核心函數:start_kernel()(init/main.c)呼叫 trap_init()(arch/i386/kernel/traps.c),透過 set_system_gate(SYSCALL_VECTOR, &system_call) 將系統呼叫掛在中斷 0x80。
  3. 中斷總控程式:arch/i386/kernel/entry.S 以組合語言實作,負責保存狀態、驗證呼叫號、依 sys_call_table 跳轉至對應服務例程、恢復狀態返回用戶空間。
  4. 系統呼叫向量表:定義於 include/asm-i386/unistd.h,sys_call_table 定義於 arch/i386/kernel/entry.S。

修改原始碼新增 sys_addtotal 系統呼叫

  1. 新增服務例程(於 kernel/sys.c):
asmlinkage int sys_addtotal(int numdata) {
    int i = 0, enddata = 0;
    while (i <= numdata) enddata += i++;
    return enddata;
}
  1. 註冊至 sys_call_table(修改 arch/i386/kernel/entry.S):
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork)    /* 190 */
/* add by I */
.long SYMBOL_NAME(sys_addtotal)
.rept NR_syscalls-191
.long SYMBOL_NAME(sys_ni_syscall)
.endr
  1. 宣告呼叫號(修改 include/asm-i386/unistd.h),分配新的系統呼叫編號。

三、總結

透過具體實作,不僅學會新增系統呼叫,更掌握了核心原始碼分析的核心方法論:理解目錄架構 → 追蹤關鍵函數呼叫鏈 → 實際修改驗證。這份艱辛的投入將換取對作業系統底層運作的深度洞見與專業程式設計素養。

copyright © 萬盛學電腦網 all rights reserved