什麼是「核心」#

廣義的作業系統 = 核心(Kernel) + 使用者空間程式(Userspace)。當我們說 “Linux”,多數時候指的其實是 GNU/Linux ── 一個 Linux 核心 + GNU 工具鏈 + 各種使用者程式組成的發行版。核心本身是一個程式:開機後常駐記憶體、擁有最高權限、負責管理硬體與調度其他程式。

從程式角度看,核心做四件事:

  1. 管理硬體:CPU 排程、記憶體配置、I/O 派發
  2. 提供抽象:把「磁碟磁區」抽象成「檔案」、把「實體 RAM」抽象成「虛擬位址空間」
  3. 隔離與保護:讓行程互不干擾、防止使用者程式直接存取硬體
  4. 提供介面:透過 syscall 給 userspace 調用

Monolithic vs Microkernel#

比較項Monolithic(如 Linux)Microkernel(如 Mach、L4、seL4)
架構所有子系統都在核心位址空間執行只把最少功能放核心,其餘做成服務
通訊函式呼叫,速度快IPC 訊息傳遞,有 context switch
穩定性一個 bug 可能拖垮整個核心服務崩潰可重啟
開發複雜需要謹慎處理鎖、邊界介面清楚但效能難調
例子Linux、FreeBSD、Windows NT 系QNX、seL4、Fuchsia Zircon

Linux 是 Monolithic,但支援可載入模組(LKM),所以在運行時可以把驅動、檔案系統等動態插入核心 ── 這常被稱為 “modular monolithic”。它不是 microkernel,模組仍與核心共享位址空間,沒有 IPC 邊界。

1992 年的 Tanenbaum-Torvalds debate 就是在爭這件事。Tanenbaum 認為 monolithic 是 80 年代的設計,Torvalds 反駁說「微核心理論上漂亮,但實務上還沒人寫出能用的」。三十多年後 Linux 統治了伺服器、手機、雲端、嵌入式 ── 這個爭議的實務答案算是揭曉了。

Linux 子系統地圖#

核心不是一坨 C 程式碼,內部有清晰的子系統劃分:

            +---------------------------------------------+
            |              System Call Interface          |
            +---------------------------------------------+
                              |
   +----------+   +----------+|+----------+   +----------+
   | Process  |   |  Memory  |||   VFS    |   | Network  |
   |  Mgmt    |   |  Mgmt    |||          |   |  Stack   |
   +----------+   +----------+|+----------+   +----------+
                              |
            +---------------------------------------------+
            |              Device Drivers                 |
            +---------------------------------------------+
                              |
            +---------------------------------------------+
            |          Architecture-dependent code        |
            +---------------------------------------------+
                              |
                          [ Hardware ]

對應到 source tree(linux/ 根目錄):

目錄內容
arch/架構相關(x86、arm64、riscv),boot、context switch、MMU
kernel/行程、排程、訊號、時間、locking、tracing
mm/記憶體管理(buddy、slab、vmalloc、page fault、reclaim)
fs/VFS 與各檔案系統(ext4、xfs、btrfs、proc、sysfs)
net/網路協定堆疊(TCP/IP、netfilter、socket)
drivers/各種裝置驅動(占了核心一半以上的程式碼量)
include/標頭檔
init/開機流程(start_kernel() 在這)
lib/通用工具函式(rbtree、xarray、kfifo 等)
block/區塊裝置層(bio、request queue、I/O scheduler)
security/LSM(SELinux、AppArmor、Smack)
Documentation/內建文件(讀核心前建議先逛這裡)

開機流程速覽#

BIOS/UEFI
   │
   ▼
Bootloader(GRUB、systemd-boot)
   │  載入 vmlinuz + initramfs 到記憶體
   ▼
arch/<arch>/boot 啟動程式
   │  解壓 vmlinuz、設定基本環境
   ▼
start_kernel()  ──  init/main.c
   │  初始化:記憶體、排程、IRQ、檔案系統
   ▼
rest_init() → kernel_init()
   │  掛載 initramfs,執行 /init 或 /sbin/init
   ▼
PID 1(systemd / OpenRC / SysV init)
   │  啟動 userspace 服務
   ▼
       使用者登入

start_kernel() 是核心進入 C 程式碼的第一個函式,它的呼叫順序大致決定了核心的初始化階段:早期記憶體初始化 ➡️ trap/IRQ 初始化 ➡️ scheduler ➡️ timekeeping ➡️ 各子系統 init ➡️ 最終 fork 出 PID 1。

發行版(Distribution)#

「Linux 核心」是一個 git repo,但「Linux 發行版」是把核心 + GNU 工具 + 套件管理 + 預設配置打包成可安裝的作業系統。常見家族:

家族代表套件管理風格
Debian 系Debian、Ubuntu、Mintdpkg/apt穩定、保守
Red Hat 系RHEL、CentOS Stream、Fedora、Rockyrpm/dnf企業級、SELinux 預設啟用
Arch 系Arch、Manjaropacmanrolling release、極簡
SUSE 系openSUSE、SLESrpm/zypper企業向,YaST 配置工具
Embedded/IoTYocto、Buildroot、OpenWrt自訂可裁剪、用於嵌入式
容器最小化Alpine、Distrolessapk / 無musl libc、極小映像

選哪一個發行版幾乎不影響核心本身,影響的是套件版本、預設配置、init system(systemd vs OpenRC)、libc(glibc vs musl)。

核心版本與編號#

6.7.4
│ │ │
│ │ └── stable patch(bug fix)
│ └──── feature release(每 ~10 週一次)
└────── major(很少跳,2.6 → 3.0、3.19 → 4.0、4.20 → 5.0 都是因為小數點長度)

長期支援版(LTS)每年由 Greg Kroah-Hartman 從某個 x.y 版本宣告,維護 2~6 年。發行版(如 Ubuntu LTS、Debian stable)通常基於 LTS 核心。

想看自己跑的版本:uname -r。想知道核心 source 對應哪個 commit:/proc/version 或編譯時 embedded 的 LOCALVERSION

使用者空間 vs 核心空間#

這是理解 Linux 一切的起點:

┌────────────────────────────────────────┐
│           Kernel space                 │  ← 高位址,所有行程共用
│  vmalloc / direct-map / kernel text    │     特權等級 0(x86 ring 0 / ARM EL1)
├────────────────────────────────────────┤
│           User space                   │  ← 每個行程獨立
│  stack / heap / .text / .data / mmap   │     特權等級 3(x86 ring 3 / ARM EL0)
└────────────────────────────────────────┘
                  0
  • 在 64-bit Linux,核心 + 使用者空間共用一個 48-bit 或 57-bit 虛擬位址空間(依 page table levels)
  • 使用者程式不能直接存取核心位址 ── 嘗試存取會觸發 page fault ➡️ SIGSEGV
  • 進入核心的合法門路只有三個:syscalltrap/exceptioninterrupt

每次 syscall 都會切換特權等級(user ➡️ kernel),這個切換不便宜(數百個 cycle),所以高效能程式會盡量批次化 syscall(如 io_uringsendmmsg)。

接下來讀什麼#