Skip to content

2. 核心思想:Kernel、系统调用与进程模型 ​

Linux 看似复杂,但底层只回答三个问题:

  1. 谁在用 CPU?(进程调度)
  2. 谁在用内存?(内存管理)
  3. 怎么和外部世界交互?(I/O、网络、文件系统)

本章先建立几个核心概念的直觉。

2.1 Kernel Space vs User Space ​

Linux 把内存分成两个世界:

  • Kernel Space(内核空间):操作系统内核运行的区域,拥有最高权限,可以直接访问硬件;
  • User Space(用户空间):普通应用程序运行的区域,权限受限,不能直接访问硬件。

用户空间的程序想读文件、开网络连接、申请内存,都必须通过 系统调用(system call) 进入内核空间。

这种隔离有两个好处:

  1. 安全:用户程序不能随便破坏系统;
  2. 稳定:一个用户程序崩溃不会导致整个系统崩溃。

2.2 系统调用:用户与内核的“电话” ​

系统调用是用户程序请求内核服务的唯一正规渠道。

常见系统调用:

系统调用作用
fork创建新进程
execve加载并执行新程序
read / write读写文件或 socket
open / close打开/关闭文件
mmap内存映射文件或分配内存
brk / sbrk调整堆内存大小
clone创建线程或 namespace
exit终止进程

系统调用的开销:每次系统调用都要从用户态切换到内核态,再切回来,这涉及上下文切换和特权级切换。频繁的系统调用会成为性能瓶颈。2020 年代的重要缓解手段是 io_uring:把 I/O 请求批量写入共享环形队列,内核批量执行,可把高频 I/O 的系统调用次数降低一到两个数量级(详见架构设计)。

2.3 进程、线程与协程 ​

进程(Process) ​

进程是操作系统资源分配的基本单位。每个进程有独立的:

  • 地址空间(虚拟内存);
  • 打开的文件描述符;
  • 信号处理;
  • cgroup 和 namespace 归属。

线程(Thread) ​

线程是 CPU 调度的基本单位。同一进程内的多个线程共享:

  • 地址空间;
  • 文件描述符;
  • 代码段和数据段。

但每个线程有自己的:

  • 程序计数器;
  • 寄存器;
  • 栈。

在 Linux 里,线程本质上也是进程,只是它们共享很多资源。clone() 系统调用可以控制共享哪些资源。

协程(Coroutine) ​

协程是用户态的轻量级调度单位,由程序自己管理,不经过操作系统。Python 的 asyncio、Go 的 goroutine、C++20 的 co_await 都是协程。

概念调度者切换开销地址空间
进程操作系统大独立
线程操作系统中共享
协程用户程序 / 运行时小共享

2.4 文件即一切(Everything is a File) ​

Unix/Linux 的一个核心设计哲学是:几乎所有东西都是文件。

  • 普通文件是文件;
  • 目录是文件;
  • 设备(/dev/sda、/dev/nvidia0)是文件;
  • 进程信息(/proc/<pid>/status)是文件;
  • 网络 socket 也是文件描述符。

这种统一抽象让 Linux 可以用同一套接口(open/read/write/close/ioctl)操作千差万别的东西。

2.5 Namespace:进程的“视图隔离” ​

Linux Namespace 让一组进程看到“自己的一份系统视图”。

Namespace隔离内容
PID进程 ID
Mount文件系统挂载点
Network网络设备、IP、路由
UTS主机名和域名
IPCSystem V IPC 和 POSIX message queues
User用户和组 ID
Cgroupcgroup 根目录
Time系统时间(较新)

容器(Docker/Kubernetes Pod)就是利用 namespace 实现的隔离。注意:namespace 提供的是视图隔离,不是资源限制。资源限制由 cgroup 负责。

2.6 Cgroup:资源的“硬边界” ​

cgroup(control group)是 Linux 用来对进程组做资源限制和统计的机制。

主要资源子系统:

子系统控制内容
cpuCPU 使用(shares、quota、period)
cpuacctCPU 使用统计
memory内存限制和统计
blkio块设备 I/O 限制
pids进程数限制
devices设备访问权限
net_cls / net_prio网络流量标记和优先级

cgroup v1 把各子系统挂载到不同目录;cgroup v2 统一了层级结构,功能更强大,并且已经成为事实标准——Kubernetes 1.25+ 默认使用 cgroup v2,systemd 也默认挂载 v2。

Kubernetes 的 CPU limit/request、memory limit/request,最终都翻译成 cgroup 配置。

2.7 eBPF:内核的“可编程扩展点” ​

前面说系统调用是用户进入内核的“正门”,但它只能做内核预先定义好的事。eBPF(extended Berkeley Packet Filter)是 2020 年代 Linux 最重要的新机制:它允许用户把一段经过验证的、安全的字节码程序“注入”内核,挂在钩子(hook)上运行,而不需要写内核模块、不需要重启机器。

它能做什么:

  • 可观测:无侵入地统计系统调用、TCP 重传、文件 I/O、off-cpu 时间(bpftrace、bcc、Pixie、Beyla);
  • 网络:在内核协议栈早期处理包,Cilium 用 eBPF 替代 kube-proxy 实现 Service 负载均衡;
  • 调度:sched_ext(6.12 合入主线)把 CFS 之外的一个完整调度类交给 BPF 程序实现——你可以用几十行 BPF 代码热替换整个 CPU 调度策略;
  • 安全:Tetragon、Falco 用 eBPF 做运行时威胁检测。

2025-2026 年的几个标志性进展:6.17 加入标准字符串处理 kfuncs;6.18 支持密码学签名的 BPF 程序(为“非特权用户加载受审计的 BPF 程序”铺路)和 bpf_task_work(允许在中断上下文安排可睡眠的延迟执行);7.0 加入 fsession 和更快的 BTF 类型查找;7.1/7.2 持续扩充 arena、可调整大小 hash map、sleepable tracepoint 等能力;7.3 甚至允许 binfmt_misc 的二进制格式匹配交给 BPF 程序处理。eBPF 正在从“专家玩具”变成 AI 平台的默认基础设施。

本节只建立直觉,eBPF 的实战用法见最佳实践一章。

2.8 权限模型 ​

Linux 权限基于:

  • 用户(User) 和 组(Group);
  • 读(r)、写(w)、执行(x) 三种权限;
  • 文件所有者、所属组、其他用户三类主体。

现代 Linux 还有更细粒度的安全机制:

  • SELinux:基于标签的强制访问控制(MAC);
  • AppArmor:基于路径的强制访问控制;
  • Capabilities:把 root 权限拆分成多个独立能力(如 CAP_SYS_ADMIN、CAP_NET_ADMIN)。

容器安全经常涉及这些机制。

2.9 延迟 vs 吞吐 ​

Linux 设计经常要在延迟和吞吐之间取舍:

  • 延迟(Latency):一个请求从发起到完成的时间;
  • 吞吐(Throughput):单位时间内完成的请求数量。

AI 训练通常追求吞吐(尽量多算数据);AI 推理通常追求低延迟(尽快响应一个请求)。Linux 的调度器、I/O 调度器、网络参数都要根据场景调整。

2.10 核心概念速查表 ​

概念一句话解释
Kernel Space内核运行的特权内存区域
User Space普通程序运行的受限内存区域
System Call用户程序请求内核服务的接口
Process资源分配的基本单位,有独立地址空间
ThreadCPU 调度的基本单位,共享进程资源
Coroutine用户态轻量级调度单位
Namespace进程的视图隔离机制
Cgroup进程组的资源限制和统计机制
eBPF内核中的安全可编程扩展点,可观测/网络/调度/安全都靠它
sched_ext用 eBPF 实现整个 CPU 调度器的新机制(6.12+)
File Descriptor内核中打开文件或资源的引用
Capability细粒度的 root 权限拆分

2.11 本节小结 ​

Linux 的核心思想可以总结为:

  1. 内核空间和用户空间分离,通过系统调用交互;
  2. 进程是资源单位,线程是调度单位;
  3. 一切皆文件,统一了 I/O 接口;
  4. Namespace 做隔离,Cgroup 做限制;
  5. eBPF 让内核可编程,sched_ext 是它在调度上的标志性应用;
  6. 延迟和吞吐是永恒的权衡。

下一节,我们把镜头拉近,看 Linux 内核的整体架构。

Released under CC-BY-SA-4.0 License.