Linux 内核简介
一、Linux 系统的基本组成
从操作系统运行的角度来看,一个基本的 Linux 系统可以理解为:
Linux 系统 = Linux 内核(Kernel) + 根文件系统(Root Filesystem)
其中:
- Linux 内核:负责直接管理 CPU、内存、磁盘、网卡等硬件资源,并向用户空间程序提供系统调用接口。
- 根文件系统:包含系统运行所需的目录、命令、动态链接库、配置文件、服务程序以及各种用户空间程序,例如
/bin、/usr、/etc、/var等。
严格来说,一个完整的 Linux 发行版还包括 GNU 工具、systemd、Shell、软件包管理器、桌面环境等大量用户空间软件。
二、Linux 内核的主要功能
Linux 内核主要负责以下几个方面。
1. 进程管理(Process Management)
负责管理系统中运行的进程和线程,包括:
- 创建和销毁进程
- CPU 调度
- 进程状态管理
- 上下文切换
- 进程优先级
- 进程间通信
例如:
ps
top
htop
看到的进程最终都由内核负责调度。
2. 内存管理(Memory Management)
内核负责管理系统的物理内存和虚拟内存,包括:
- 物理内存分配
- 虚拟内存管理
- 地址空间映射
- 内存分页(Paging)
- Swap
- 内存保护
- Page Cache
现代 Linux 使用虚拟内存机制。
程序通常并不是直接使用物理内存地址,而是运行在自己的虚拟地址空间(Virtual Address Space)中,由 CPU 的 MMU 和内核共同完成虚拟地址到物理地址的映射。
可以简单理解为:
进程使用的虚拟地址
↓
页表(Page Table)
↓
MMU 地址转换
↓
实际物理内存地址
虚拟内存可以让每个进程拥有相对独立的地址空间,同时提供内存隔离、共享内存、按需分页等机制。
3. 文件系统(Filesystem)
Linux 内核提供 VFS(Virtual File System,虚拟文件系统)层,用统一的接口支持不同文件系统。
例如:
ext4
XFS
Btrfs
F2FS
FAT
NTFS
ISO9660
SquashFS
NFS
tmpfs
procfs
sysfs
应用程序通常只需要调用:
open()
read()
write()
close()
而不需要关心底层究竟是 ext4、XFS 还是其他文件系统。
大致结构:
用户程序
↓
系统调用
↓
VFS
↓
具体文件系统驱动
↓
块设备驱动
↓
磁盘 / SSD / USB 等硬件
4. 设备驱动(Device Drivers)
内核通过设备驱动控制硬件,例如:
- 硬盘
- NVMe SSD
- USB
- 网卡
- 显卡
- 声卡
- 键盘
- 鼠标
- 蓝牙设备
Linux 的很多驱动既可以:
直接编译进内核
也可以:
编译成可动态加载的内核模块。
5. 网络协议栈(Network Stack)
Linux 内核内部实现了完整的网络协议栈,例如:
Socket
↓
TCP / UDP
↓
IPv4 / IPv6
↓
网络设备层
↓
网卡驱动
↓
网卡
此外还包括:
- Routing
- Netfilter
- nftables
- 网络命名空间
- Bridge
- VLAN
- TCP/IP
- IPv6
因此 Linux 的网络功能很大一部分实际上是在内核中实现的。
6. 安全机制(Security)
Linux 内核提供大量安全机制,例如:
- UID / GID
- 文件权限
- Capability
- Namespace
- seccomp
- Linux Security Modules(LSM)
- SELinux
- AppArmor
- 内核密码学框架(Kernel Crypto API)
需要注意:
SELinux 并不是简单的“Linux 内核自带安全功能”,而是基于 Linux Security Modules(LSM)框架实现的一套强制访问控制机制。
三、IPC:进程间通信
IPC 全称:
Inter-Process Communication
即:
进程间通信。
因为不同进程通常拥有相互隔离的虚拟地址空间,所以一个进程不能随意直接访问另一个进程的内存。
因此操作系统提供了 IPC 机制,使进程之间能够交换数据和同步状态。
常见 IPC 包括:
System V IPC
消息队列(Message Queue)
共享内存(Shared Memory)
信号量集(Semaphore Set)
除此之外,Linux 还提供:
Pipe 管道
FIFO 命名管道
Signal 信号
Socket 套接字
Unix Socket Unix 域套接字
mmap 内存映射
其中共享内存通常具有很高的通信效率,因为多个进程可以映射同一块物理内存。
四、宏内核与微内核
操作系统内核在架构设计上经常讨论两种模型:
Monolithic Kernel 宏内核 / 单体内核
Microkernel 微内核
1. 微内核(Microkernel)
微内核只把最核心的功能放在内核态,例如:
进程调度
基础内存管理
IPC
中断处理
而文件系统、网络、设备驱动等功能可以运行在独立的用户态服务中。
结构类似:
用户空间
├─ 文件系统服务
├─ 网络服务
├─ 驱动服务
└─ 其他服务
↕ IPC
------------------
微内核
------------------
硬件
优点:
- 模块隔离较好
- 某个服务崩溃不一定导致整个内核崩溃
- 架构更加模块化
缺点之一是不同服务之间可能需要频繁 IPC 和上下文切换。
典型微内核或微内核家族包括:
MINIX 3
QNX
Mach
seL4
需要纠正一个常见说法:Windows NT 并不是严格意义上的纯微内核。
现代 Windows NT 通常被描述为混合内核(Hybrid Kernel)架构,其设计受到微内核思想影响,但大量系统组件仍运行在内核态。
2. 宏内核 / 单体内核(Monolithic Kernel)
Linux 属于:
Monolithic Kernel(宏内核 / 单体内核)
核心系统功能运行在同一个内核地址空间,例如:
进程管理
内存管理
VFS
网络协议栈
设备驱动
安全子系统
大致结构:
用户程序
↓
系统调用
↓
┌─────────────────────────────┐
│ Linux Kernel │
│ │
│ Process Management │
│ Memory Management │
│ VFS │
│ Network Stack │
│ Security │
│ Device Drivers │
│ Kernel Modules │
└─────────────────────────────┘
↓
硬件
但是 Linux 又支持高度模块化。
因此:
Linux = 单体内核 + 可加载内核模块
部分功能不需要永久编译进核心内核,可以编译成模块,在系统运行过程中动态加载或卸载。
五、Linux 内核模块
Linux 内核模块通常以:
.ko
结尾。
.ko 表示:
Kernel Object
例如:
ext4.ko
xfs.ko
nvme.ko
virtio_blk.ko
e1000.ko
可以使用:
lsmod
查看当前已经加载的模块。
加载模块:
modprobe 模块名
例如:
modprobe ext4
卸载模块:
modprobe -r ext4
或者:
rmmod ext4
六、Linux 内核文件存放位置
Linux 内核启动文件通常存放在:
/boot/
在很多 x86 Linux 发行版中,可以看到:
/boot/vmlinuz-6.x.x
例如:
/boot/vmlinuz-6.8.0
但是需要注意:
并不是所有 CPU 架构都使用 vmlinuz 这个名字。
例如 ARM64 Linux 经常直接使用:
/boot/Image
还可能看到:
Image.gz
zImage
bzImage
具体名称取决于 CPU 架构、发行版以及构建方式。
七、vmlinux、vmlinuz、bzImage 等名称
vmlinux
vmlinux 通常指 Linux 内核构建过程中产生的未压缩 ELF 内核映像。
例如:
vmlinux
它通常包含 ELF 信息和符号信息,因此经常用于:
- 内核调试
- crash 分析
- GDB
- 符号解析
可以粗略记忆为:
vm + linux
其中 vm 与 Linux 历史上的虚拟内存支持有关。
vmlinuz
很多 Linux 发行版的 /boot 中可以看到:
vmlinuz
它表示经过压缩、可用于启动的 Linux 内核映像。
可以用历史上的命名方式帮助记忆:
vmlinux
↓
压缩
↓
vmlinuz
不过不要简单理解成:
z = zip
vmlinuz 中的 z 历史上表示压缩后的内核映像,并不意味着它一定使用 ZIP 格式。
具体压缩算法可能根据内核配置和架构而不同,例如:
gzip
bzip2
LZMA
XZ
LZO
LZ4
Zstd
因此更准确的理解是:
vmlinuz是用于启动的压缩 Linux 内核映像,而不是“一个普通的 ZIP 文件”。
八、Linux 内核模块存放位置
内核模块通常存放在:
/lib/modules/<kernel-version>/
例如:
/lib/modules/6.8.0/
现代发行版中 /lib 经常是指向 /usr/lib 的符号链接,因此实际也可能看到:
/usr/lib/modules/<kernel-version>/
可以使用:
uname -r
查看当前正在运行的内核版本。
因此:
ls /lib/modules/$(uname -r)/
可以查看当前内核对应的模块目录。
模块和内核版本必须匹配,否则通常无法正常加载。
九、为什么需要 initramfs?
Linux 启动过程中存在一个非常重要的问题:
内核想挂载真正的根文件系统,但挂载根文件系统所需要的驱动或其他组件可能又存放在真正的根文件系统里面。
例如真正的根文件系统是:
/dev/nvme0n1p2
文件系统为:
ext4
但假设:
NVMe 驱动
ext4 驱动
LVM
RAID
磁盘加密支持
没有直接编译进内核,而是作为模块存在于真正的根文件系统中。
那么就出现:
我要挂载根文件系统
↓
需要磁盘 / 文件系统驱动
↓
驱动在根文件系统里
↓
但是根文件系统还没有挂载
形成“先有鸡还是先有蛋”的启动问题。
解决办法就是:
initramfs。
十、initramfs 是什么?
initramfs 全称:
Initial RAM Filesystem
即:
初始内存文件系统。
启动时,引导程序会把:
Linux Kernel
+
initramfs
一起加载到内存。
例如:
/boot/vmlinuz-linux
/boot/initramfs-linux.img
然后启动过程大致变成:
UEFI / BIOS
↓
Bootloader
GRUB / systemd-boot 等
↓
加载 Linux Kernel
↓
加载 initramfs
↓
Kernel 启动
↓
解包 initramfs
↓
建立临时根文件系统
↓
运行 initramfs 中的 /init
↓
加载真正根文件系统所需要的驱动
↓
找到磁盘
↓
解密 / RAID / LVM(如果需要)
↓
挂载真正的 Root Filesystem
↓
切换到真正的根文件系统
↓
启动 PID 1
↓
systemd / 其他 init
↓
启动完整 Linux 用户空间
十一、initramfs 与 ramdisk 的区别
学习 Linux 时经常把 initramfs 简单称为:
RAM Disk(内存磁盘)
这样理解启动原理没有太大问题,但严格来说:
initramfs 和传统 initrd/ramdisk 并不是完全相同的东西。
传统:
initrd
=
Initial RAM Disk
更接近于:
在内存中创建一个块设备,再把文件系统挂载到这个块设备上。
现代 Linux 更常见的是:
initramfs
=
Initial RAM Filesystem
它通常是一个压缩的 cpio 归档,启动时由内核解包到内存中的 rootfs。
因此现代 Linux 更准确的说法应该是:
Linux 启动早期通常使用 initramfs 提供一个临时的初始根文件系统。
十二、为什么有些系统可以不用 initramfs?
initramfs 并不是绝对必须的。
如果启动真正根文件系统所需要的所有驱动都已经:
直接编译进 Linux 内核
那么内核理论上可以直接挂载真正的根文件系统。
例如:
磁盘控制器驱动 → built-in
ext4 → built-in
根文件系统设备 → 内核可以直接识别
那么:
Kernel
↓
直接识别磁盘
↓
直接挂载 RootFS
就不一定需要 initramfs。
但现代发行版为了兼容:
LVM
RAID
LUKS 磁盘加密
NVMe
不同文件系统
不同存储控制器
Live ISO
网络启动
通常都会使用 initramfs。
十三、Linux 启动过程中最重要的几个文件
可以把它们记成:
/boot/
├── vmlinuz-* ← Linux 内核(x86 常见)
├── Image ← ARM64 常见内核映像
├── initramfs-*.img ← 初始根文件系统
└── grub/ ← GRUB 相关文件
内核模块:
/lib/modules/<kernel-version>/
或者:
/usr/lib/modules/<kernel-version>/
真正的 Linux 用户空间:
/
├── etc
├── usr
├── var
├── root
├── home
├── dev
├── proc
├── sys
└── ...
十四、最终需要建立的整体认识
Linux 系统可以从启动过程理解成:
UEFI / BIOS
│
▼
Bootloader
│
┌──────────┴──────────┐
▼ ▼
Linux Kernel initramfs
│ │
└──────────┬──────────┘
▼
临时根文件系统
│
▼
加载内核模块
│
▼
识别真正的磁盘
│
▼
挂载真正的 RootFS
│
▼
switch_root
│
▼
PID 1
│
▼
systemd
│
▼
各种系统服务 / 用户程序
因此可以把几个核心概念总结为:
Kernel(内核)
负责管理 CPU、内存、进程、文件系统、网络、驱动和安全等核心资源。
Kernel Module(内核模块)
.ko 文件,可以在运行时动态加载到内核中,为内核增加驱动或其他功能。
initramfs(初始内存文件系统)
Linux 启动早期使用的临时根文件系统,主要负责准备真正根文件系统所需要的驱动和环境。
Root Filesystem(根文件系统)
Linux 正常运行后的主要用户空间环境,包含 /usr、/etc、/var 等目录以及大量程序和配置文件。
最终可以浓缩成一句话:
Bootloader 把 Kernel 和 initramfs 加载到内存 → Kernel 借助 initramfs 准备存储设备和驱动 → 挂载真正的 RootFS → 启动 PID 1 → 进入完整 Linux 用户空间。
浙公网安备 33010602011771号