Skip to content

进程概念

什么是进程

进程(Process)是操作系统中正在运行的程序实例。每个进程都有独立的内存空间、资源和执行状态。

进程的基本属性

属性说明
PID进程 ID,每个进程的唯一标识符
PPID父进程 ID
UID运行进程的用户 ID
GID运行进程的用户组 ID
优先级进程调度优先级(nice 值)
状态运行、睡眠、停止、僵尸等

进程状态

状态标志说明
R运行中(Running)
S可中断睡眠(Sleeping)
D不可中断睡眠(通常等待 IO)
T已停止(Stopped)
Z僵尸进程(Zombie)
I空闲内核线程

查看进程

bash
# 查看当前用户进程
ps

# 查看所有进程(BSD 风格)
ps aux

# 查看所有进程(UNIX 风格)
ps -ef

# 动态查看进程(每隔 2 秒刷新)
top

# 更友好的 top 替代品
htop

# 查看进程树
pstree
pstree -p         # 显示 PID
pstree -u         # 显示用户名

进程的父子关系

bash
#!/bin/bash

echo "当前脚本 PID: $$"
echo "父进程 PID: $PPID"

# 查看进程父子关系
ps -f -p $$

前台与后台进程

bash
# 前台进程:占用终端,等待完成
sleep 10

# 后台进程:不占用终端,加 & 符号
sleep 10 &
echo "后台进程 PID: $!"   # $! 获取最后一个后台进程的 PID

# 将前台进程挂起并放到后台
# 先按 Ctrl+Z 挂起,再执行:
bg

# 将后台进程调回前台
fg
fg %1     # 指定作业编号

进程的创建

Shell 脚本中每执行一个外部命令,都会创建一个子进程:

bash
#!/bin/bash

echo "父进程 PID: $$"

# fork 子进程执行命令
ls -la

# 使用括号创建子 shell
(
    echo "子 shell PID: $$"   # 注意:子 shell 中 $$ 是父进程 PID
    echo "实际 PID: $BASHPID"
)

# 使用 exec 替换当前进程(不创建子进程)
# exec ls -la   # 执行完 ls 后进程结束

进程与环境变量

bash
# 子进程继承父进程的导出变量
export MY_VAR="hello"

bash -c 'echo "子进程中:$MY_VAR"'  # 输出 hello

# 未导出的变量不会传递给子进程
LOCAL_VAR="local"
bash -c 'echo "子进程中:$LOCAL_VAR"'  # 输出空

进程的退出

bash
#!/bin/bash

# 正常退出
exit 0

# 异常退出
exit 1

# 获取上一个命令的退出状态
ls /nonexistent
echo "退出状态: $?"   # 非 0 表示失败

# 退出状态约定
# 0    - 成功
# 1    - 通用错误
# 2    - 用法错误
# 126  - 命令不可执行
# 127  - 命令未找到
# 128+ - 收到信号退出(如 130 = Ctrl+C)

僵尸进程

僵尸进程是已退出但父进程尚未调用 wait() 回收的进程:

bash
# 查看僵尸进程
ps aux | grep 'Z'

# 僵尸进程由父进程负责清理
# 如果父进程不处理,重启相关服务或系统来清理