主题
16 · 操作系统全景:用户态、内核态与系统调用
1. 环境前提
bash
mkdir -p ~/lab/os
sudo apt update
sudo apt install -y strace1
2
3
2
3
2. 概念框(轻量课本)
text
你(用户程序 / shell / ls / curl)
│ 系统(受限)
用户态 User Mode
────────┼────────────────
内核态 Kernel Mode
│ 文件系统、进程、内存、网络驱动…
▼
硬件1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
| 词 | 一句话 |
|---|---|
| 用户态 | 普通程序所在的「受限模式」,不能随意碰硬件与别人的内存 |
| 内核态 | OS 核心代码运行的模式,管进程、内存、设备 |
| 系统调用(syscall) | 用户态向内核「点菜」的正规入口:open、read、write、fork、execve… |
| Shell | 读你输入的命令行,再 fork/exec 起进程;它自己也是用户态程序 |
不要背:系统调用有几百个。本系列只需建立直觉——几乎所有「看见文件 / 建进程 / 占端口」都经过 syscall。
3. 动手:用 strace 看见 syscall
bash
# 跟踪 ls 打开了什么、读了什么(输出较多,先看前几十行)
strace -e trace=openat,read,write,close ls ~/lab 2>&1 | head -n 40
# 只看「和文件名相关」的调用
strace -e trace=file ls /tmp 2>&1 | head -n 30
# curl 本机(若 8080 有服务更好;没有也会看到 socket 相关调用)
strace -e trace=network curl -sS -o /dev/null http://127.0.0.1/ 2>&1 | head -n 401
2
3
4
5
6
7
8
2
3
4
5
6
7
8
读输出时抓住三类名字:
| 常见 syscall | 对应你已会的命令世界 |
|---|---|
openat / read / write | cat、less、重定向 |
execve | 运行一个新程序 |
connect / socket | curl、监听端口(22 篇再深) |
bash
# 统计调用次数(哪类最忙)
strace -c ls ~/lab 2>&1 | tail -n 201
2
2
4. 与命令行篇对照
| 你在 01~02 做的 | OS 视角 |
|---|---|
| SSH 进机器开 shell | 远程已有一个 shell 进程在跑 |
敲 ls | shell fork 子进程 → execve("/bin/ls") → ls 一堆 openat/getdents |
man | 还是用户态程序,读手册文件 |
5. 动手清单
- [ ] 装好
strace - [ ] 对
ls跑一次strace -e trace=file,指出至少 2 个 syscall 名 - [ ] 对
curl跑一次strace -e trace=network(或strace -c) - [ ] 能用自己的话解释:用户态 / 内核态 / 系统调用
6. 常见翻车
| 翻车 | 处理 |
|---|---|
strace 输出刷屏 | 加 -e trace=... 过滤,或 ` |
| 权限不够跟踪别人进程 | 对自己的命令用 strace cmd;跟踪服务常需 sudo |
| 以为 shell「就是内核」 | shell 是普通程序;内核在更深一层 |
7. 官方 / 延伸
man strace、man 2 syscalls- Linux man-pages:syscalls(2)
- The Linux Kernel documentation(浏览即可,不必通读)
下一篇:进程 —— PID、父子关系与地址空间。
