跳转至

进程管理

进程管理

📌 学习时间:2-3天 📌 难度级别:⭐⭐⭐ 中级 📌 前置知识:Linux基础入门、文件与目录管理


📚 章节概述

进程是 Linux 系统运行的核心单元。本章深入讲解进程的概念与生命周期、进程查看和控制工具(ps/top/htop/kill)、前台后台切换、进程优先级调整、系统资源监控工具(free/df/du/iostat/vmstat),以及 /proc 虚拟文件系统。

🎯 学习目标

  • 理解进程的概念、状态和生命周期
  • 熟练使用进程查看工具(ps/top/htop)
  • 掌握进程控制(kill/killall/pkill/nohup)
  • 熟练进行前台后台切换(fg/bg/jobs/&)
  • 理解进程优先级(nice/renice)
  • 掌握系统资源监控工具
  • 了解 /proc 文件系统

📖 1. 进程概念

1.1 进程 vs 程序

Bash
# 程序:静态的可执行文件(存在于磁盘上)
# 进程:程序的运行实例(存在于内存中)

# 一个程序可以产生多个进程
# 例如:同时打开3个终端 → 3个 bash 进程

# 每个进程有唯一的 PID(Process ID)
echo $$                      # 当前 Shell 的 PID
echo $PPID                   # 父进程的 PID
echo $!                      # 最后一个后台进程的 PID

1.2 进程状态

Bash
# Linux 进程状态(在 ps 中的标识)
# R (Running)     — 正在运行或在运行队列中
# S (Sleeping)    — 可中断睡眠(等待事件完成)
# D (Disk sleep)  — 不可中断睡眠(通常是 I/O 操作)
# T (Stopped)     — 已停止(收到 SIGSTOP/SIGTSTP)
# Z (Zombie)      — 僵尸进程(已终止,但父进程未回收)
# I (Idle)        — 闲置内核线程

# 进程状态附加标志
# < — 高优先级
# N — 低优先级
# s — 包含子进程的会话领导者
# l — 多线程
# + — 前台进程组

# 进程生命周期
# fork() → exec() → wait() → exit()
# 父进程 fork 出子进程 → 子进程 exec 执行新程序 → 子进程结束 → 父进程 wait 回收

1.3 僵尸进程与孤儿进程

Bash
# 僵尸进程 (Zombie)
# 子进程退出后,父进程没有调用 wait() 回收,进程表项仍然存在
# 危害:占用 PID 资源,大量僵尸进程会导致无法创建新进程

# 查找僵尸进程
ps aux | awk '$8 ~ /Z/ {print}'  # awk文本处理:按列提取和格式化数据
ps -eo pid,ppid,stat,cmd | grep 'Z'  # grep文本搜索:按模式匹配行

# 解决僵尸进程
# 方法1:让父进程回收(发送 SIGCHLD 给父进程)
kill -SIGCHLD <父进程PID>

# 方法2:杀死父进程(极端情况)
kill -9 <父进程PID>
# 孤儿子进程会被 init/systemd (PID=1) 接管并正确回收

# 孤儿进程 (Orphan)
# 父进程先于子进程退出,子进程被 init (PID=1) 收养
# 孤儿进程不是问题,init 会正常回收

📖 2. 进程查看

2.1 ps — 进程快照

Bash
# ps 显示进程的瞬时快照

# Unix 风格(带 -)
ps -e                        # 所有进程
ps -ef                       # 全格式显示所有进程
ps -eF                       # 额外全格式
ps -ely                      # 长格式

# BSD 风格(不带 -)
ps aux                       # 最常用:所有用户的所有进程

# ps aux 输出字段说明
# USER  PID %CPU %MEM   VSZ   RSS TTY STAT START TIME COMMAND
# root    1  0.0  0.1 22568 13496 ?   Ss   Jan10 0:05 /sbin/init
# alice 1234 2.5  1.0 512000 81000 pts/0 Sl 10:30 1:20 /usr/bin/python3

# USER  — 进程所有者
# PID   — 进程ID
# %CPU  — CPU 使用率
# %MEM  — 内存使用率
# VSZ   — 虚拟内存大小(KB)
# RSS   — 常驻内存大小(KB)
# TTY   — 终端(? 表示没有终端)
# STAT  — 进程状态
# START — 启动时间
# TIME  — 累计 CPU 时间
# COMMAND — 命令名

# 实用的 ps 命令组合
ps aux | sort -k3 -rn | head -10     # CPU 使用率 Top 10
ps aux | sort -k4 -rn | head -10     # 内存使用率 Top 10
ps -eo pid,ppid,user,%cpu,%mem,stat,cmd --sort=-%cpu | head -20
ps aux | grep nginx                  # 查找 nginx 进程
ps aux | grep "[n]ginx"              # 排除 grep 自身

# 查看进程树
ps -ef --forest                      # 树形显示
pstree                               # 专用进程树工具
pstree -p                            # 显示 PID
pstree -u alice                      # 特定用户的进程树

# 查看线程
ps -eLf                              # 显示线程
ps -T -p <PID>                       # 特定进程的线程

2.2 top — 动态进程监控

Bash
# top 实时显示进程状态和系统资源

top
# top 输出说明:
# 第1行:系统时间、运行时长、用户数、负载(1/5/15分钟)
# 第2行:任务总数、运行/睡眠/停止/僵尸数
# 第3行:CPU 使用率 (us/sy/ni/id/wa/hi/si/st)
# 第4行:内存使用
# 第5行:交换分区使用

# CPU 使用率字段说明
# us — 用户空间(user)
# sy — 内核空间(system)
# ni — 低优先级用户进程(nice)
# id — 空闲(idle)
# wa — IO等待(iowait)— 高 wa 表示IO瓶颈
# hi — 硬件中断
# si — 软件中断
# st — 虚拟机偷取时间(steal)

# top 交互命令
# P — 按 CPU 排序
# M — 按内存排序
# T — 按运行时间排序
# k — 杀死进程(输入 PID)
# r — 修改 nice 值
# 1 — 切换单CPU/多CPU显示
# c — 切换显示命令名/完整命令
# H — 切换线程显示
# f — 选择显示字段
# q — 退出
# d / s — 修改刷新间隔

# top 命令行选项
top -d 2                     # 每2秒刷新
top -p 1234                  # 只监控特定 PID
top -p 1234,5678             # 监控多个 PID
top -u alice                 # 只显示 alice 的进程
top -bn1                     # 批处理模式,输出一次(用于脚本)
top -bn1 | head -20          # 脚本中获取系统状态

2.3 htop — 增强版 top

Bash
# htop 是 top 的增强版,更美观易用
sudo apt install htop        # 安装
htop

# htop 优势
# - 彩色显示
# - 鼠标支持
# - 横向/纵向滚动
# - 树形视图
# - 可以直接搜索/过滤进程
# - 不需要输入 PID 就能操作进程

# htop 快捷键
# F1 — 帮助
# F2 — 设置
# F3 — 搜索
# F4 — 过滤
# F5 — 树形视图
# F6 — 排序
# F7/F8 — 调整 nice 值
# F9 — 杀死进程
# F10 — 退出
# t — 切换树形视图
# u — 按用户过滤

📖 3. 进程控制

3.1 kill — 发送信号

Bash
# kill 通过发送信号来控制进程

# 常用信号
# 1  SIGHUP    — 终端挂起/重新加载配置
# 2  SIGINT    — 中断(等同于 Ctrl+C)
# 3  SIGQUIT   — 退出(生成 core dump)
# 9  SIGKILL   — 强制杀死(不能被捕获或忽略)
# 15 SIGTERM   — 正常终止(默认信号,可以被捕获)
# 18 SIGCONT   — 继续执行
# 19 SIGSTOP   — 停止(不能被捕获)
# 20 SIGTSTP   — 终端停止(Ctrl+Z)

# 列出所有信号
kill -l

# 使用方法
kill PID                     # 发送 SIGTERM(默认)
kill -15 PID                 # 同上
kill -9 PID                  # 强制杀死(最后手段)
kill -1 PID                  # 发送 SIGHUP(通常用于重新加载配置)
kill -0 PID                  # 检查进程是否存在(不发送信号)

# ⚠️ 正确的杀进程顺序
# 1. 先 SIGTERM (15),让进程正常退出
kill -15 PID
sleep 5
# 2. 如果进程还在,再 SIGKILL (9)
kill -9 PID

# killall — 按名称杀死进程
killall nginx                # 杀死所有 nginx 进程
killall -9 python3           # 强制杀死所有 python3 进程
killall -u alice             # 杀死 alice 的所有进程
killall -i nginx             # 交互确认

# pkill — 按模式匹配杀死进程
pkill nginx                  # 杀死进程名匹配 nginx 的
pkill -f "python script.py"  # 按完整命令行匹配
pkill -u alice               # 杀死 alice 的所有进程
pkill -t pts/0               # 杀死特定终端的所有进程

# pgrep — 按模式查找进程 PID
pgrep nginx                  # 查找 nginx 进程的 PID
pgrep -l nginx               # 同时显示进程名
pgrep -a nginx               # 显示完整命令
pgrep -u alice               # 查找 alice 的进程

3.2 前台与后台切换

Bash
# 后台运行
command &                    # 在后台运行命令
sleep 100 &                  # 示例

# 查看后台任务
jobs                         # 查看当前 Shell 的后台任务
jobs -l                      # 显示 PID

# 前台/后台切换
Ctrl + Z                     # 暂停当前前台进程(放入后台,状态为 Stopped)
bg                           # 让最近暂停的进程在后台继续运行
bg %2                        # 让第2个后台任务在后台运行
fg                           # 将最近的后台任务切换到前台
fg %1                        # 将第1个后台任务切换到前台

# 实际场景示例
vim file.txt                 # 正在编辑文件
# 按 Ctrl+Z               # 暂停 vim
ls -la                       # 做其他事情
fg                           # 回到 vim

# nohup — 忽略挂断信号(退出终端后进程继续运行)
nohup command &              # 标准输出默认写入 nohup.out
nohup command > output.log 2>&1 &  # 指定输出文件

# disown — 将后台任务与当前 Shell 分离
command &
disown %1                    # 退出 Shell 后,进程继续运行
disown -a                    # 分离所有后台任务

# screen / tmux — 终端复用器(更好的方案)
# tmux 示例
tmux new -s mysession        # 创建新会话
# 运行长时间任务...
# Ctrl+B, D                 # 分离会话(断开SSH不影响)
tmux attach -t mysession     # 重新连接会话
tmux ls                      # 列出所有会话

📖 4. 进程优先级

4.1 nice 与 renice

Bash
# Linux 进程调度优先级
# Nice 值范围:-20(最高优先级)到 19(最低优先级)
# 默认 nice 值为 0
# 只有 root 可以设置负 nice 值(提高优先级)

# 查看 nice 值
ps -eo pid,ni,cmd | head
nice                         # 显示当前默认 nice 值

# 以指定优先级启动进程
nice -n 10 command           # 以 nice 值 10 启动
nice -n -5 command           # 以 nice 值 -5 启动(需要 root)

# 修改运行中的进程优先级
renice -n 5 -p PID           # 修改单个进程
renice -n 10 -u alice        # 修改 alice 的所有进程
renice -n -5 -g developers   # 修改 developers 组的所有进程

# 在 top 中修改(按 r 键)
# 输入 PID → 输入新 nice 值

# 实际场景
# 降低编译任务优先级,不影响系统其他任务
nice -n 15 make -j4

# 提高关键服务优先级
sudo renice -n -10 -p $(pgrep nginx)  # $()命令替换:执行命令并获取输出

4.2 实时优先级

Bash
# Linux 还有实时调度策略
# SCHED_FIFO   — 先进先出实时调度
# SCHED_RR     — 时间片轮转实时调度
# SCHED_OTHER  — 普通调度(CFS,默认)

# 查看调度策略
chrt -p PID

# 设置实时调度
sudo chrt -f 50 command       # FIFO 策略,优先级 50
sudo chrt -r 50 command       # RR 策略,优先级 50

📖 5. 系统资源监控

5.1 free — 内存使用

Bash
free -h                       # 人类可读格式
free -m                       # 以 MB 显示
free -g                       # 以 GB 显示
free -s 5                     # 每5秒刷新
free -t                       # 显示总计

# 输出说明
#               total   used   free   shared  buff/cache  available
# Mem:          15Gi    5.2Gi  2.1Gi  512Mi   8.1Gi       9.4Gi
# Swap:         2.0Gi   0Bi    2.0Gi

# 关键字段
# total      — 总内存
# used       — 已使用(含 buff/cache)
# free       — 完全空闲
# shared     — 共享内存
# buff/cache — 缓冲区和缓存(可回收)
# available  — 实际可用(free + 可回收的 buff/cache)

# ⚠️ 面试重点
# free 看起来很小不代表内存不够
# 关键看 available 字段
# Linux 会利用空闲内存做缓存,提高性能
# 需要时缓存会自动释放

5.2 df — 磁盘空间

Bash
df -h                         # 人类可读的磁盘使用
df -hT                        # 显示文件系统类型
df -i                         # 显示 inode 使用情况
df -h /home                   # 特定挂载点

# 输出说明
# Filesystem  Type  Size  Used Avail Use% Mounted on
# /dev/sda1   ext4   50G   20G   27G  42% /
# tmpfs       tmpfs 7.8G     0  7.8G   0% /dev/shm

5.3 du — 目录大小

Bash
du -h /var/log                # 目录大小(递归)
du -sh /var/log               # 目录总大小(summary)
du -sh /var/log/*             # 子目录大小
du -sh /var/log/* | sort -rh | head -10  # 最大的前10个
du -h --max-depth=1 /var      # 只显示一级子目录
du -ah . | sort -rh | head -20  # 当前目录下最大的文件/目录

# ncdu — 交互式磁盘使用分析(推荐)
sudo apt install ncdu
ncdu /var/log                 # 交互式浏览

5.4 iostat — I/O 统计

Bash
# 安装 sysstat 包
sudo apt install sysstat

iostat                        # 基本 I/O 统计
iostat -x 1 5                 # 扩展统计,每1秒刷新,共5次
iostat -d -x                  # 设备级别的详细统计

# 关键指标
# tps    — 每秒 I/O 请求数
# kB_read/s — 每秒读取 KB
# kB_wrtn/s — 每秒写入 KB
# %util  — 设备使用率(>80% 可能有I/O瓶颈)
# await  — I/O 平均等待时间(毫秒)
# svctm  — I/O 平均服务时间

5.5 vmstat — 虚拟内存统计

Bash
vmstat 1 10                   # 每1秒输出一次,共10次

# 输出说明
# procs --------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
#  1  0      0 2100000 800000 6000000  0    0    10    20  500 1000 5  2 92  1

# procs:
#   r — 运行队列长度(等待CPU的进程数,>CPU核数可能有CPU瓶颈)
#   b — 不可中断睡眠的进程数(通常是I/O等待)

# memory:
#   swpd — 使用的交换空间
#   free — 空闲内存
#   buff — 缓冲区
#   cache — 缓存

# swap:
#   si — 从交换区读入(swap in)
#   so — 写入交换区(swap out)— 持续不为0则内存不足

# io:
#   bi — 块设备读入(block in)
#   bo — 块设备写出(block out)

# cpu:
#   us/sy/id/wa — 同 top

5.6 其他监控工具

Bash
# uptime — 系统运行时间和负载
uptime
# 10:30:00 up 45 days, 3:20, 2 users, load average: 0.15, 0.10, 0.05
# 负载:1/5/15分钟平均负载(单核<1、4核<4 为正常)

# sar — 综合性能分析(sysstat)
sar -u 1 5                    # CPU 使用率
sar -r 1 5                    # 内存使用
sar -b 1 5                    # I/O 统计
sar -n DEV 1 5                # 网络统计

# dstat — 综合监控(一个命令看所有)
sudo apt install dstat
dstat                         # 综合显示 CPU/磁盘/网络/内存
dstat -cdnm                   # 指定显示项

# glances — 更美观的监控工具
pip install glances
glances

# lsof — 列出打开的文件
lsof                          # 所有打开的文件
lsof -i :80                   # 使用80端口的进程
lsof -u alice                 # alice 打开的文件
lsof -p PID                   # 特定进程打开的文件
lsof +D /var/log               # 打开了 /var/log 目录下文件的进程

# strace — 跟踪系统调用(调试利器)
strace command                # 跟踪命令的系统调用
strace -p PID                 # 跟踪运行中的进程
strace -c command             # 统计系统调用
strace -e trace=open,read command  # 只跟踪特定系统调用

📖 6. /proc 文件系统

Bash
# /proc 是虚拟文件系统,提供内核和进程信息的接口
# 不占用磁盘空间,只存在于内存中

# 系统信息
cat /proc/cpuinfo              # CPU 信息
cat /proc/meminfo              # 内存信息
cat /proc/version              # 内核版本
cat /proc/loadavg              # 系统负载
cat /proc/uptime               # 运行时间
cat /proc/filesystems          # 支持的文件系统
cat /proc/mounts               # 挂载信息
cat /proc/cmdline              # 内核启动参数

# 进程信息 /proc/PID/
ls /proc/1/                    # PID 为 1 的进程信息

cat /proc/PID/status           # 进程状态
cat /proc/PID/cmdline          # 启动命令
cat /proc/PID/environ          # 环境变量
cat /proc/PID/maps             # 内存映射
cat /proc/PID/fd/              # 打开的文件描述符
ls -l /proc/PID/fd/            # 文件描述符指向
cat /proc/PID/io               # I/O 统计
cat /proc/PID/limits           # 资源限制
readlink /proc/PID/exe         # 可执行文件路径
readlink /proc/PID/cwd         # 当前工作目录

# 实用示例

# 查看进程打开的文件数
ls /proc/PID/fd/ | wc -l

# 查看系统最大文件描述符数
cat /proc/sys/fs/file-max

# 查看当前连接数
cat /proc/net/tcp | wc -l

# 修改内核参数(临时)
echo 1 > /proc/sys/net/ipv4/ip_forward     # 开启 IP 转发
echo 65535 > /proc/sys/fs/file-max          # 增大文件描述符限制

# 永久修改内核参数
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p                     # 立即生效

📖 7. 面试要点

高频面试题

Q1:什么是僵尸进程?如何解决?

僵尸进程是已经结束但父进程没有调用 wait() 回收的进程。它占用进程表项(PID),不占 CPU 和内存。查找:ps aux | grep Z。解决:发送 SIGCHLD 给父进程让其回收,或杀死父进程让 init 回收。

Q2:SIGTERM 和 SIGKILL 的区别?

SIGTERM (15) 是"请求"进程终止,进程可以捕获此信号并做清理工作(关闭文件、释放资源)。SIGKILL (9) 是"强制"终止,不能被捕获或忽略,进程立即被内核杀死。应该先 SIGTERM,等几秒后如果进程还存在再 SIGKILL。

Q3:如何找出 CPU/内存使用最高的进程?

Bash
# CPU Top 10
ps aux --sort=-%cpu | head -11  # |管道:将前一命令的输出作为后一命令的输入

# 内存 Top 10
ps aux --sort=-%mem | head -11

# 或用 top 中按 P(CPU)或 M(内存)排序

Q4:系统负载(load average)是什么意思?如何判断系统负载是否正常?

Load average 表示在⅕/15分钟内平均等待 CPU 的进程数。对于 N 核系统,load average 小于 N 表示 CPU 没有饱和。如 4 核系统 load average 为 3.5 是正常的,15.0 则严重过载。关注 15 分钟的值来判断趋势。

Q5:free 命令中 buff/cache 是什么?为什么 free 很小但系统正常?

buffer 是块设备的 I/O 缓冲,cache 是文件系统的页缓存。Linux 会利用空闲内存做缓存提高性能,需要时自动释放。看 available 字段才能反映实际可用内存。free 值很小但 available 很大说明系统内存充足。

Q6:如何让进程在退出终端后继续运行?

Bash
# 方法1:nohup
nohup command > output.log 2>&1 &

# 方法2:disown
command &
disown %1

# 方法3:screen / tmux(推荐)
tmux new -s session_name
# 运行任务
# Ctrl+B D 分离

🔧 练习题

基础练习

  1. 使用 ps aux 找出 CPU 使用率最高的 5 个进程
  2. 启动一个后台进程,使用 jobs 查看,然后切换到前台
  3. 使用 kill 发送 TERM 和 KILL 信号,观察区别
  4. 使用 free -h 分析当前系统内存使用情况

进阶练习

  1. 查看 /proc/cpuinfo 获取 CPU 核数和型号
  2. 使用 lsof -i :PORT 查找占用某端口的进程
  3. 编写脚本持续监控系统负载,超过阈值时发出警告
  4. 查找并处理系统中的僵尸进程

✅ 自我检查

  • 理解进程状态(R/S/D/T/Z)
  • 能熟练使用 ps/top/htop
  • 掌握 kill 信号和正确的杀进程方式
  • 能进行前后台进程切换
  • 理解 nice 值和进程优先级
  • 能用 free/df/du/iostat/vmstat 监控系统
  • 了解 /proc 文件系统

上一章04-用户与权限管理 下一章06-Shell脚本编程