入学诊断
24 道题,覆盖命令行、Shell、系统编程、计算机系统、内核、网络六个面。不要查资料,20 分钟做完。目的不是考倒你,而是判断从哪条路线开始、哪些章可以跳。
A 组 · 命令行(4 题)
A1. 一条命令列出当前目录下所有 .log 文件,按大小从大到小,只显示前 5 个,并带人类可读的大小。
A2. cmd > out.txt 2>&1 与 cmd 2>&1 > out.txt 的区别是什么?
A3. 解释 find . -name '*.c' -print0 | xargs -0 grep -l 'TODO' 中两个 -0 的作用。如果去掉会怎样?
A4. chmod 4755 ./tool 与 chmod 755 ./tool 的安全差异是什么?现代 Linux 上更推荐的替代方案是什么?
B 组 · Shell(3 题)
B1. 下面脚本在 curl 失败时会不会退出?为什么?
#!/bin/bash
set -e
curl -fsS https://example.com/data > data.json
echo "downloaded"
B2. 写一行 Bash,把变量 $1 中所有空格替换成下划线;再写一行,把路径的扩展名去掉。
B3. trap 'rm -f "$tmp"' EXIT INT TERM 中,为什么 EXIT 和 INT 都要写?只写 EXIT 会漏掉什么?
C 组 · 系统编程(5 题)
C1. read(fd, buf, 4096) 返回 1024 代表什么?返回 0 代表什么?返回 -1 且 errno == EINTR 时应该怎么做?
C2. open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644) 中 0644 受 umask 影响吗?如果想让文件最终权限确定是 0644,应该怎么做?
C3. fork() 之后,父进程和子进程谁先运行?fork() 返回值在两边分别是什么?vfork() 为什么危险?
C4. 写一个正确的 pthread 条件变量等待循环,说明为什么必须用 while 而不是 if。
C5. write(fd, buf, n) 返回 n 是否意味着数据已经落盘?fsync()、fdatasync()、O_SYNC 各保证什么?
D 组 · 计算机系统(4 题)
D1. -1 的 32 位补码是什么?(unsigned)-1 与 INT_MAX + 1 在 C 里分别是什么行为(有符号溢出 vs 无符号回绕)?
D2. 解释 x86-64 下 call 指令对 %rsp 和返回地址做了什么;leave 与 ret 各做什么。
D3. 一个 64 位虚拟地址,4 KiB 页,四级页表各 9 位,页内偏移多少位?一级页表项覆盖多大地址范围?
D4. 两个线程同时执行 counter++(counter 是 int 全局变量),为什么可能丢失更新?给出两种修复方式并说明代价。
E 组 · 内核(4 题)
E1. 用户态调用 getpid() 时,CPU 特权级如何变化?syscall 指令与 int 0x80 的主要区别是什么?
E2. task_struct、thread_info、内核栈三者在 x86-64 上是什么关系?
E3. malloc(1GB) 成功返回是否意味着 1 GB 物理内存已经分配?mmap 之后第一次写会发生什么?
E4. 自旋锁和互斥锁的核心区别是什么?为什么自旋锁的临界区里不能睡眠?
F 组 · 网络(4 题)
F1. 从 192.168.1.10:54321 访问 10.0.0.5:443,写出 TCP 三次握手的四个关键报文(SYN、SYN-ACK、ACK)的源/目的地址与端口,以及 seq/ack 的变化。
F2. listen(fd, 128) 的 128 在现代 Linux 上对应哪个队列?队列满了以后内核默认怎么处理?ss -lnt 的 Send-Q/Recv-Q 分别表示什么?
F3. epoll 的水平触发(LT)与边缘触发(ET)区别是什么?ET 模式下为什么必须把 fd 设为非阻塞,并且一次 read 要读到 EAGAIN?
F4. 一台服务器 8 核、16 GB 内存,要支撑 100 万条空闲 TCP 连接,最可能先撞到哪些限制?给出至少四个可调项与对应命令。
评分与路线建议
| 得分 | 判断 | 建议起点 |
|---|---|---|
| 0–8 | 命令行与系统基础薄弱 | 路线 A,从 0.1 开始;第 1 篇只读 1.1/1.2/1.6 |
| 9–15 | 会用但说不清机制 | 路线 B,从 1.2 开始;第 0 篇快速过 0.2–0.6 |
| 16–20 | 系统编程有经验,内核/网络零散 | 路线 B 后半 + 路线 C;从 2.1 与 3.1 并行 |
| 21–24 | 基础扎实,缺的是路径与证据 | 路线 C;直接读第 3/4 篇,项目选 A1 或 C1 |
答案与简要解释
| 题 | 答案 | 关键点 |
|---|---|---|
| A1 | ls -lhS *.log | head -5 | -S 按大小、-h 人类可读;ls 对无匹配会报错,严格写法用 find |
| A2 | 前者把 stdout 和 stderr 都重定向到文件;后者先复制 stderr 到当前 stdout(终端),再把 stdout 指向文件 | 重定向从左到右求值 |
| A3 | -print0/-0 用 NUL 分隔,避免文件名含空格/换行被拆开;去掉会把空格当分隔符 | xargs 默认按空白分词 |
| A4 | 4755 是 setuid root,任何用户执行都以 root 运行;现代用 capability(如 cap_net_bind_service)或 systemd 的 User=/AmbientCapabilities= | 最小权限 |
| B1 | 会退出(curl -f 失败返回非零,set -e 生效);但 curl 在 if/&&/|| 里时不退出 | set -e 有语境例外 |
| B2 | ${1// /_};${path%.*}(去掉最后一个 . 及之后) | 参数展开 |
| B3 | EXIT 覆盖正常退出与 exit;INT/TERM 覆盖被信号杀死的情况(默认信号处理不会触发 EXIT,除非 trap 后 exit) | 清理要覆盖所有退出路径 |
| C1 | 短读,读到 1024 字节;0 是 EOF;EINTR 应重试(检查 errno,重新调用) | 短读/EOF/中断 |
| C2 | 受影响;umask 会清掉位。要确定权限,先 umask(0) 或用 fchmod() | open 的 mode 不是最终权限 |
| C3 | 不确定,由调度器决定;父进程得到子 PID,子进程得到 0;vfork 共享地址空间,子进程不能 return/修改数据,必须 _exit 或 exec | fork 语义 |
| C4 | while (!ready) pthread_cond_wait(&cv, &m);;if 会被虚假唤醒和多个唤醒绕过 | 条件变量必须循环 |
| C5 | 不意味着落盘,只到 page cache;fsync 刷数据+元数据,fdatasync 只刷数据(及必要元数据),O_SYNC 每次写同步 | 持久化语义 |
| D1 | 32 个 1;有符号溢出是未定义行为(UB),无符号是模 2^32 回绕 | UB 与回绕 |
| D2 | call 把返回地址压栈并跳转;leave 等价 mov %rbp,%rsp; pop %rbp;ret 弹出返回地址并跳转 | 栈帧 |
| D3 | 偏移 12 位;每级 9 位,一级页表项覆盖 2^(9+9+9+12)=2^39=512 GiB | 页表位数 |
| D4 | counter++ 读-改-写非原子;用互斥锁或 atomic_fetch_add;锁有竞争/阻塞成本,原子操作依赖 CAS/缓存一致性 | 数据竞争 |
| E1 | 用户态 → 内核态(ring 3 → ring 0);syscall 是 x86-64 快速入口,int 0x80 是 32 位中断门,后者更慢且 ABI 不同 | 特权级切换 |
| E2 | task_struct 是进程描述符;x86-64 上 thread_info 在 task_struct 内(不再放内核栈底);内核栈是独立 THREAD_SIZE 区域 | 结构关系 |
| E3 | 不意味着;malloc 只拿到虚拟地址,首次写触发缺页,内核才分配物理页/零页 | 延迟分配 |
| E4 | 自旋锁忙等、适合极短临界区且不可睡眠;互斥锁睡眠等待;自旋锁持有期间睡眠会导致死锁/浪费 CPU(单核更严重) | 睡眠与原子上下文 |
| F1 | SYN: 10.0.0.5:443 → 192.168.1.10:54321, seq=x;SYN-ACK: 反向, seq=y, ack=x+1;ACK: 正向, seq=x+1, ack=y+1 | 三次握手 |
| F2 | accept 队列(accept queue)与 SYN 队列(syn queue);tcp_abort_on_overflow=0 时默认丢弃/忽略 ACK;ss -lnt 的 Send-Q 是 backlog 上限,Recv-Q 是当前已完成握手等待 accept 的连接数 | 两个队列 |
| F3 | LT 只要可读就持续通知;ET 只在状态变化时通知一次。ET 必须非阻塞并读到 EAGAIN,否则会漏事件/阻塞 | epoll 语义 |
| F4 | fd 上限(ulimit -n/fs.file-max)、端口范围(ip_local_port_range)、内存(tcp_mem、sk_buff)、conntrack 表(nf_conntrack_max)、backlog(somaxconn)、epoll 实例与内核对象开销 | 百万连接 |
做完后把错题对应的章节标在路线图上;错 3 题以上的板块,从该板块的第一章开始读。