文章目录
- [Linux 面试完全指南(Go 校招向)](#Linux 面试完全指南(Go 校招向))
-
- 一、文件系统
- 二、进程管理
-
- 进程状态
- [进程 vs 线程 vs 协程](#进程 vs 线程 vs 协程)
- 进程间通信(IPC)
- 常用进程命令
- 三、内存管理
- [四、I/O 模型(面试核心)](#四、I/O 模型(面试核心))
-
- [五种 I/O 模型](#五种 I/O 模型)
- [select / poll / epoll 对比(面试必考)](#select / poll / epoll 对比(面试必考))
- 五、网络
-
- [TCP 三次握手 & 四次挥手(面试必背)](#TCP 三次握手 & 四次挥手(面试必背))
- [TCP vs UDP](#TCP vs UDP)
- 常用网络命令
- [六、磁盘与 I/O](#六、磁盘与 I/O)
- 七、性能排查(面试超级加分)
- 八、常用文本处理命令
- [九、Shell 脚本基础](#九、Shell 脚本基础)
- 十、系统管理常用命令
- 十一、文件描述符与限制
- 十二、面试高频问题速答
- 十三、一张图记住核心
Linux 面试完全指南(Go 校招向)
一、文件系统
目录结构
/
├── bin/ # 基础命令(ls、cp、mv)
├── sbin/ # 系统管理命令(root 才能用)
├── etc/ # 配置文件(nginx.conf、hosts)
├── home/ # 普通用户主目录
├── root/ # root 用户主目录
├── var/ # 可变数据(日志、缓存)
├── tmp/ # 临时文件(重启后清空)
├── proc/ # 虚拟文件系统,映射内核和进程状态(不占磁盘)
├── sys/ # 虚拟文件系统,硬件和内核信息
├── dev/ # 设备文件(磁盘、终端)
├── lib/ # 共享库
├── usr/ # 用户程序和数据
└── mnt/ # 临时挂载点
重要 :/proc 目录不是真实文件,是内核暴露给用户空间的接口:
bash
cat /proc/cpuinfo # CPU 信息
cat /proc/meminfo # 内存信息
cat /proc/1234/status # PID 1234 的进程状态
cat /proc/net/tcp # 网络连接状态
inode 与文件存储原理(面试高频)
Linux 文件系统中,文件由两部分组成:
inode(索引节点) 数据块(block)
┌─────────────────────┐ ┌─────────────────────┐
│ 文件类型 │ ┌────▶│ 文件实际内容 │
│ 权限(rwx) │ │ └─────────────────────┘
│ 所有者/组 │ │
│ 文件大小 │ │
│ 时间戳(atime/mtime)│ │
│ 数据块指针 ──────────┼────┘
└─────────────────────┘
目录文件内容:
文件名 → inode 号 的映射表
核心 :文件名存在目录中,inode 不存文件名。删除文件 = 目录中删除文件名→inode 映射 + inode 引用计数减 1,计数归零才真正释放数据块。
硬链接 vs 软链接:
bash
# 硬链接:两个文件名指向同一个 inode
ln file.txt hard_link.txt
# 特点:删除原文件,硬链接仍可访问;不能跨文件系统;不能链接目录
# 软链接(符号链接):类似快捷方式,存储的是目标路径
ln -s file.txt soft_link.txt
# 特点:删除原文件,软链接失效;可跨文件系统;可链接目录
面试答法:inode 是文件的元数据结构,存储权限、大小、数据块位置等,不含文件名。硬链接是同一 inode 的多个目录项,引用计数归零才删除数据;软链接是存储目标路径的特殊文件,原文件删除则失效。
文件权限
- rwx r-x r--
│ │ │ └── other(其他用户):只读
│ │ └─────── group(同组用户):读+执行
│ └──────────── owner(所有者):读+写+执行
└──────────────── 文件类型(-普通文件,d目录,l链接,b块设备)
权限数字:r=4,w=2,x=1
rwxr-xr-- = 754
bash
chmod 755 script.sh # 设置权限
chmod +x script.sh # 添加执行权限
chown user:group file.txt # 修改所有者
# 特殊权限
chmod u+s /usr/bin/passwd # SUID:以文件所有者身份执行
chmod g+s /shared/ # SGID:新建文件继承目录的组
二、进程管理
进程状态
创建(fork) → 就绪(R) ─── 获得CPU ──→ 运行(R)
│
←── CPU时间片用完 ────────┤
│
←── 等待I/O/锁/信号 ────▶ 睡眠
│可中断(S) / 不可中断(D)
←── 收到信号唤醒 ─────────┘
│
终止
│
父进程未回收 → 僵尸(Z)
D 状态(不可中断睡眠):进程在等待磁盘 I/O 或内核操作,不响应任何信号(包括 kill -9)。D 状态过多通常意味着 I/O 问题。
僵尸进程(Z) :进程已退出,但父进程未调用 wait() 回收,PCB 残留。大量僵尸进程会耗尽 PID 资源。
进程 vs 线程 vs 协程
| 对比项 | 进程 | 线程 | 协程(Go goroutine) |
|---|---|---|---|
| 资源隔离 | 独立地址空间 | 共享进程地址空间 | 共享线程栈 |
| 切换开销 | 大(页表切换) | 中(寄存器切换) | 极小(用户态切换) |
| 通信方式 | IPC(管道/消息队列/共享内存) | 共享内存+锁 | channel |
| 创建开销 | 大 | 中 | 极小(初始栈 2KB) |
| 崩溃影响 | 不影响其他进程 | 影响整个进程 | panic 影响整个进程 |
进程间通信(IPC)
管道(Pipe) ─── 单向、只能父子进程间用
命名管道(FIFO) ─── 单向、任意进程间用,有文件路径
消息队列 ─── 有结构的消息传递
共享内存 ─── 最快的 IPC,直接映射同一块内存
信号量(Semaphore) ─── 进程间同步/互斥
信号(Signal) ─── 异步通知(kill -9、SIGTERM)
Socket ─── 可跨机器通信
共享内存为什么最快:不需要内核参与数据拷贝,进程直接读写同一块物理内存,没有系统调用开销。代价是需要自己做同步(信号量)。
常用进程命令
bash
ps aux # 查看所有进程
ps aux | grep go-service # 查找特定进程
top # 动态查看进程(CPU/内存排序)
htop # 更友好的 top(需安装)
kill -9 <PID> # 强制杀死进程(SIGKILL,不可忽略)
kill -15 <PID> # 优雅终止(SIGTERM,可捕获处理)
kill -l # 列出所有信号
pstree -p # 进程树
lsof -p <PID> # 查看进程打开的文件
lsof -i :8080 # 查看占用 8080 端口的进程
strace -p <PID> # 追踪进程系统调用(排查卡死)
三、内存管理
虚拟内存
每个进程拥有独立的虚拟地址空间 ,通过页表映射到物理内存:
进程A虚拟地址空间 物理内存
┌────────────────┐ ┌──────────┐
│ 内核空间 │ │ 进程A数据 │
│───────────────│ │ 进程B数据 │
│ 栈(向下增长) │──┐ │ 共享库 │
│ │ │ │ 内核 │
│ 堆(向上增长) │──┼────▶│ ... │
│ │ │ └──────────┘
│ BSS(未初始化)│ │
│ Data(已初始化)│ │ 磁盘(Swap)
│ Text(代码段) │──┘ ┌──────────┐
└────────────────┘ │ 换出的页 │
└──────────┘
缺页中断:访问的虚拟地址对应物理页不在内存中,触发中断,内核从磁盘载入数据到内存,更新页表,继续执行。
Swap 空间:物理内存不足时,将不常用的内存页换出到磁盘,为当前进程腾出空间。频繁 Swap 会导致性能下降(磁盘 I/O 远慢于内存)。
内存分配
malloc/new 申请内存
│
├─ 小内存(< 128KB):调整 brk 指针,扩展堆
└─ 大内存(≥ 128KB):mmap 映射一块匿名内存
Go 内存分配:
goroutine 栈(初始 2KB,按需增长)
堆(GC 管理,tcmalloc 思路,分级 span)
内存相关命令
bash
free -h # 查看内存使用(-h 人性化显示)
# 输出示例:
# total used free shared buff/cache available
# Mem: 15Gi 8Gi 2Gi 500Mi 5Gi 6Gi
# available = free + buff/cache 中可回收的部分,是真正可用内存
vmstat 1 # 每秒刷新:内存、swap、I/O、CPU
cat /proc/meminfo # 详细内存信息
# 查看进程内存
cat /proc/<PID>/status | grep VmRSS # 物理内存占用
pmap -x <PID> # 进程内存映射详情
四、I/O 模型(面试核心)
五种 I/O 模型
以"读取网络数据"为例,整个过程分两个阶段:
-
等待数据到达内核缓冲区
-
将数据从内核缓冲区拷贝到用户空间
-
阻塞 I/O(Blocking I/O)
用户进程: recv() ────阻塞等待──────────────▶ 返回
内核: 等待数据 → 数据到达 → 拷贝到用户空间
特点:两个阶段都阻塞,简单但一个线程只能处理一个连接 -
非阻塞 I/O(Non-blocking I/O)
用户进程: recv() → 立即返回EAGAIN → 轮询 → recv() → 数据就绪 → 返回
特点:第一阶段不阻塞,但需要不断轮询,消耗 CPU -
I/O 多路复用(Multiplexing)← 最重要
用户进程: select/poll/epoll(fd集合) ─阻塞─▶ 某fd就绪 → recv() → 返回
特点:一个线程监听多个 fd,有数据才读,不浪费 -
信号驱动 I/O
用户进程: 注册 SIGIO 信号 → 继续执行 → 收到信号 → 调用 recv()
特点:第一阶段异步,实际拷贝还是同步,较少使用 -
异步 I/O(AIO)
用户进程: aio_read() → 立即返回 → 继续干别的 → 收到完成通知
特点:两个阶段全异步,真正的异步,Linux 支持不完善
-
select / poll / epoll 对比(面试必考)
select:
- 传入一个 fd_set 位图,内核遍历所有 fd 检查是否就绪
- 返回后用户还要遍历所有 fd 找就绪的
- 最大限制 1024 个 fd
- 每次调用都要把 fd_set 从用户空间拷贝到内核
poll:
- 用链表替代位图,无 1024 限制
- 其他问题与 select 相同(仍是 O(n) 遍历)
epoll:
- epoll_create:创建 epoll 实例(内核红黑树 + 就绪链表)
- epoll_ctl:注册/修改/删除监听的 fd(加入红黑树)
- epoll_wait:只返回就绪的 fd(从就绪链表取),O(1)
- 使用事件驱动(fd 就绪时内核回调加入就绪链表)
- 无 fd 数量限制,性能不随连接数增长而下降
| 对比项 | select | poll | epoll |
|---|---|---|---|
| fd 数量限制 | 1024 | 无 | 无 |
| 时间复杂度 | O(n) | O(n) | O(1) |
| fd 拷贝 | 每次调用拷贝 | 每次调用拷贝 | 只注册时拷贝一次 |
| 就绪通知 | 遍历全部 fd | 遍历全部 fd | 只返回就绪 fd |
| 适用场景 | 连接少 | 连接少 | 高并发(Nginx/Redis) |
epoll 两种工作模式:
- LT(水平触发,默认):只要 fd 有数据,每次 epoll_wait 都通知。数据没读完下次还会通知,编程容易。
- ET(边缘触发):fd 状态变化时只通知一次。必须一次性读完所有数据(循环 read 直到 EAGAIN),性能更高但编程复杂。Nginx 使用 ET 模式。
面试答法:epoll 相比 select/poll 的核心优势是 O(1) 的就绪检测。epoll 在内核维护一棵红黑树存所有监听的 fd,一个就绪链表存就绪的 fd。fd 就绪时内核通过回调直接加入就绪链表,epoll_wait 只需从链表取结果,不用遍历所有 fd,因此高并发下性能不退化。
五、网络
TCP 三次握手 & 四次挥手(面试必背)
三次握手(建立连接):
Client Server
│─── SYN(seq=x) ────────────▶ │ SYN_SENT → SYN_RCVD
│◀── SYN+ACK(seq=y,ack=x+1) ──│
│─── ACK(ack=y+1) ───────────▶ │ ESTABLISHED
ESTABLISHED
为什么三次:两次不够(服务端不知道自己的发送能力正常),四次浪费(第二步合并了 SYN+ACK)
四次挥手(断开连接):
Client Server
│─── FIN ───────────────────▶ │ CLOSE_WAIT
│◀── ACK ──────────────────── │ (服务端可能还有数据要发)
│ │
│◀── FIN ─────────────────── │ LAST_ACK
│─── ACK ───────────────────▶ │ CLOSED
TIME_WAIT(等待 2MSL)
CLOSED
为什么四次:断开是单向的,各自独立关闭,所以多了一步
为什么 TIME_WAIT 等 2MSL:
① 确保最后一个 ACK 能到达(防止对端重发 FIN)
② 让本次连接的旧数据包在网络中消失,防止影响新连接
TCP vs UDP
| 对比项 | TCP | UDP |
|---|---|---|
| 连接 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认、重传、排序) | 不可靠 |
| 顺序 | 保证顺序 | 不保证 |
| 流量控制 | 有(滑动窗口) | 无 |
| 拥塞控制 | 有 | 无 |
| 速度 | 较慢 | 快 |
| 适用场景 | HTTP、数据库、文件传输 | DNS、视频直播、游戏 |
常用网络命令
bash
# 查看网络连接
netstat -antp # 所有 TCP 连接及进程(-n 不解析域名)
ss -antp # 更快的 netstat 替代品
ss -s # 连接数量统计
# 查看端口占用
lsof -i :8080
ss -lntp | grep 8080
# 网络诊断
ping -c 4 google.com # 测试连通性(ICMP)
traceroute google.com # 路由追踪
curl -v http://api.example.com/health # 测试 HTTP 接口
wget -O- http://example.com # 下载内容
# 网络抓包
tcpdump -i eth0 port 8080 -w capture.pcap # 抓包保存
tcpdump -i eth0 'tcp and port 80' # 过滤 HTTP
# 查看网络接口
ip addr # 查看 IP 地址
ip route # 查看路由表
六、磁盘与 I/O
bash
# 磁盘使用
df -h # 文件系统磁盘使用(-h 人性化)
du -sh /var/log/* # 目录大小(-s 汇总,-h 人性化)
du -sh * | sort -rh | head # 找出最大的目录/文件
# I/O 性能
iostat -x 1 # 每秒刷新磁盘 I/O 统计
# %util 接近 100% = 磁盘瓶颈
iotop # 查看哪个进程在做 I/O(需 root)
# 文件查找
find /var/log -name "*.log" -mtime -7 # 7天内修改的 log 文件
find / -size +100M # 大于 100MB 的文件
七、性能排查(面试超级加分)
系统负载高排查思路
bash
# 第一步:看整体
top / htop
# 关注:
# load average:1/5/15 分钟平均负载,> CPU核数说明过载
# %CPU us/sy/wa:用户态/内核态/等待I/O 的 CPU 占比
# wa (iowait) 高 → I/O 瓶颈
# sy 高 → 系统调用过多或内核问题
uptime # 只看负载
# 第二步:找问题进程
ps aux --sort=-%cpu | head # CPU 占用最高的进程
ps aux --sort=-%mem | head # 内存占用最高的进程
# 第三步:深入分析
strace -p <PID> # 进程在执行什么系统调用
lsof -p <PID> # 进程打开了哪些文件/连接
cat /proc/<PID>/stack # 进程内核调用栈(排查 D 状态)
CPU 高排查
bash
# 1. 找到高 CPU 进程
top → 按 P 排序(CPU)
# 2. 找到该进程内哪个线程高
top -H -p <PID> # 显示线程级 CPU 使用
# 3. 转换线程 ID 为 16 进制
printf "%x\n" <TID>
# 4. Go 程序:使用 pprof
# 代码中添加:
import _ "net/http/pprof"
go func() { http.ListenAndServe(":6060", nil) }()
# 采集 30s CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# 在 pprof 交互界面:top10 / web(可视化火焰图)
内存高排查
bash
# 1. 查看内存使用
free -h
cat /proc/meminfo | grep -E "MemAvailable|Cached|Buffers"
# 2. 找内存大户
ps aux --sort=-%mem | head
# 3. Go 程序内存泄漏排查
curl http://localhost:6060/debug/pprof/heap > heap.prof
go tool pprof heap.prof
# top10 查看内存分配热点
# list <函数名> 查看具体行
磁盘 I/O 高排查
bash
iostat -x 1
# 关注 %util(使用率)、await(平均等待时间,ms)
# %util > 80% 说明磁盘接近饱和
# 找 I/O 大户
iotop -o # 只显示有 I/O 的进程
# 查看写入最多的文件
lsof -p <PID> | grep REG # 进程打开的普通文件
网络问题排查
bash
# 连接数异常
ss -s # 查看各状态连接数
ss -antp | grep TIME_WAIT | wc -l # TIME_WAIT 数量
# TIME_WAIT 过多的处理
# /etc/sysctl.conf 添加:
net.ipv4.tcp_tw_reuse = 1 # 允许复用 TIME_WAIT 连接
net.ipv4.tcp_fin_timeout = 30 # 减少 FIN_WAIT2 等待时间
net.ipv4.tcp_max_tw_buckets = 5000 # 限制 TIME_WAIT 最大数量
# 丢包排查
netstat -s | grep -E "retransmit|failed"
八、常用文本处理命令
bash
# grep:文本搜索
grep -r "ERROR" /var/log/ # 递归搜索
grep -n "panic" app.log # 显示行号
grep -v "DEBUG" app.log # 排除 DEBUG 行
grep -E "ERROR|WARN" app.log # 正则,多关键字
grep -A 3 -B 3 "panic" app.log # 显示匹配行的前后 3 行
# awk:列处理
awk '{print $1, $4}' access.log # 打印第 1、4 列
awk -F: '{print $1}' /etc/passwd # 以 : 为分隔符
awk '$9 == "500" {print}' access.log # 过滤 HTTP 500 日志
awk '{sum += $1} END {print sum}' data # 求和
# sed:流编辑
sed 's/old/new/g' file.txt # 替换(不修改文件)
sed -i 's/old/new/g' file.txt # 替换(直接修改文件)
sed -n '10,20p' file.txt # 打印第 10-20 行
sed '/DEBUG/d' app.log # 删除含 DEBUG 的行
# sort & uniq:排序去重
sort -rn file.txt # 按数字逆序排
sort | uniq -c | sort -rn # 统计词频
# 组合使用(分析日志)
# 统计 Nginx 访问最多的 IP Top10:
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# 统计 HTTP 状态码分布:
awk '{print $9}' access.log | sort | uniq -c | sort -rn
九、Shell 脚本基础
bash
#!/bin/bash
set -e # 任意命令失败则退出
set -u # 使用未定义变量则报错
# 变量
NAME="world"
echo "Hello, ${NAME}"
# 条件判断
if [ -f "/etc/config" ]; then # -f 文件存在
echo "config exists"
elif [ -d "/etc/config.d" ]; then # -d 目录存在
echo "dir exists"
else
echo "not found"
fi
# 字符串比较用 [[ ]],更安全
if [[ "$NAME" == "world" ]]; then
echo "match"
fi
# 循环
for i in {1..5}; do
echo $i
done
for file in /var/log/*.log; do
echo "processing: $file"
done
# 函数
check_service() {
local service=$1 # local 限制变量作用域
if systemctl is-active "$service" &>/dev/null; then
echo "$service is running"
return 0
else
echo "$service is stopped"
return 1
fi
}
check_service nginx
# 常用判断
[ -z "$VAR" ] # 字符串为空
[ -n "$VAR" ] # 字符串非空
[ $a -eq $b ] # 数字相等(-ne -lt -gt -le -ge)
十、系统管理常用命令
bash
# 系统信息
uname -a # 内核版本
cat /etc/os-release # 发行版信息
hostname # 主机名
date # 当前时间
uptime # 运行时间和负载
# 用户管理
whoami # 当前用户
id # 用户 UID/GID
su - username # 切换用户
sudo command # 以 root 执行
last # 登录历史
# 服务管理(systemd)
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl status nginx
systemctl enable nginx # 开机自启
systemctl disable nginx
journalctl -u nginx -f # 查看服务日志(-f 实时)
journalctl -u nginx --since "1 hour ago"
# 定时任务
crontab -e # 编辑当前用户 crontab
crontab -l # 列出当前用户定时任务
# 格式:分 时 日 月 周 命令
# 0 2 * * * /opt/backup.sh # 每天凌晨 2 点执行备份
# */5 * * * * /opt/check.sh # 每 5 分钟执行
# 环境变量
export PATH=$PATH:/usr/local/go/bin
env # 查看所有环境变量
echo $PATH
source ~/.bashrc # 重新加载配置
十一、文件描述符与限制
bash
# 查看系统文件描述符限制
ulimit -n # 当前用户最大打开文件数(默认 1024)
ulimit -n 65535 # 临时修改(当前会话)
# 永久修改:/etc/security/limits.conf 添加:
# * soft nofile 65535
# * hard nofile 65535
# 查看进程的 fd 使用
ls -la /proc/<PID>/fd | wc -l # 进程打开的 fd 数量
cat /proc/sys/fs/file-max # 系统级最大 fd 数
# 高并发服务器必做的内核参数优化(/etc/sysctl.conf)
net.core.somaxconn = 65535 # TCP 全连接队列大小
net.ipv4.tcp_max_syn_backlog = 65535 # 半连接队列大小
net.ipv4.tcp_tw_reuse = 1 # 复用 TIME_WAIT
net.ipv4.ip_local_port_range = 1024 65535 # 可用端口范围
vm.swappiness = 10 # 尽量少用 Swap
十二、面试高频问题速答
Q:Linux 中进程和线程的区别?
进程是资源分配的基本单位,有独立的地址空间;线程是 CPU 调度的基本单位,共享进程的地址空间和资源。创建线程比进程开销小,但线程崩溃会影响整个进程,进程间不互相影响。Go 中的 goroutine 是用户态的轻量级"线程",由 Go runtime 调度,初始栈只有 2KB,切换开销极小。
Q:select、poll、epoll 的区别?
select 和 poll 每次调用都要把所有 fd 从用户空间拷贝到内核,然后遍历所有 fd 检查就绪状态,时间复杂度 O(n),select 还有 1024 限制。epoll 用红黑树在内核中维护监听的 fd,fd 就绪时通过回调加入就绪链表,epoll_wait 只需从链表取结果,时间复杂度 O(1),适合高并发场景。
Q:TCP 为什么是三次握手,不是两次?
两次握手只能保证一方知道双方都能收发,但不能保证另一方也知道。第三次握手是客户端告诉服务端"我收到你的 SYN+ACK 了",双方都确认了各自的发送和接收能力。另外,两次握手无法防止历史失效的连接请求导致的资源浪费。
Q:TIME_WAIT 状态是什么,为什么要等 2MSL?
主动关闭连接的一方在发送最后一个 ACK 后进入 TIME_WAIT,等待 2MSL(最大报文存活时间,通常 60s)。原因:① 确保最后的 ACK 能到达对端,若对端没收到会重发 FIN,2MSL 足够等待重传;② 让本次连接的所有报文在网络中失效,防止旧报文影响新连接。
Q:inode 是什么?删除文件时发生了什么?
inode 是存储文件元数据的结构,包含权限、大小、数据块地址等,不包含文件名。删除文件时,先从目录中删除文件名到 inode 的映射,inode 的硬链接计数减 1,当计数为 0 时才真正释放 inode 和数据块。这就是为什么文件被进程占用时删除,进程仍可访问文件,直到进程关闭 fd 才释放空间。
Q:Linux 系统 CPU 使用率高怎么排查?
分步骤:①
top看整体,确认是用户态(us)还是内核态(sy)还是 I/O 等待(wa)高;②ps aux --sort=-%cpu找高 CPU 进程;③top -H -p <PID>找高 CPU 线程;④ Go 程序用 pprof 生成 CPU profile 分析热点函数;⑤strace -p <PID>看进程在执行什么系统调用。
Q:什么是零拷贝?
传统文件发送需要 4 次数据拷贝:磁盘→内核缓冲区→用户缓冲区→Socket 缓冲区→网卡。零拷贝使用
sendfile系统调用,数据直接从内核缓冲区传到 Socket 缓冲区,跳过用户空间,只需 2 次拷贝,减少 CPU 开销和上下文切换。Kafka、Nginx 都利用零拷贝提升性能。
Q:如何查看一个端口是否被占用?
ss -lntp | grep <端口号>或lsof -i :<端口号>,可以看到占用的进程名和 PID。
Q:load average 和 CPU 使用率有什么区别?
CPU 使用率是 CPU 的繁忙程度(0-100%)。load average 是平均活跃进程数,包括正在运行(R状态)和等待 I/O(D状态)的进程。CPU 使用率高但 load 不高说明是 CPU 密集;load 高但 CPU 使用率不高说明是 I/O 等待(磁盘/网络瓶颈)。load average 超过 CPU 核数说明有进程在排队等待。
十三、一张图记住核心
文件系统:
inode(元数据)+ 数据块(内容)+ 目录(文件名→inode映射)
硬链接共享 inode,软链接存路径,引用计数归零才释放
进程:
Namespace 隔离 + Cgroups 限制 = 容器基础
进程间通信:管道 / 消息队列 / 共享内存(最快)/ Signal / Socket
I/O 模型(从低到高):
阻塞 → 非阻塞轮询 → I/O多路复用(epoll) → 异步I/O
epoll:红黑树存fd + 就绪链表 + 事件回调 = O(1) 高并发
排查三板斧:
CPU 高 → top → pprof
内存高 → free/ps → pprof heap
I/O 高 → iostat/iotop → lsof
网络问题 → ss/netstat → tcpdump
总结 :Linux 面试核心考点是 I/O 模型 (epoll 原理)、进程与线程 、TCP 握手挥手 、文件系统(inode),以及能不能用命令排查线上问题。掌握这几个方向,加上能说出排查思路,Linux 面试基本没问题。