Skip to content

Unix / Linux - 进程

进程 (process) 是一个运行中程序的实例。每次您在类 Unix 系统上执行命令或运行应用程序时,都会创建一个或多个进程。操作系统管理这些进程,分配 CPU 时间和内存等资源。

每个进程由一个进程 ID (Process ID, PID) 唯一标识,它是一个非负整数。系统使用 PID 来跟踪和管理各个进程。

进程还有一个父进程 ID (Parent Process ID, PPID),它是创建该进程的进程的 PID。这形成了一个进程的层次结构,最终追溯到初始系统进程(通常是 PID 为 1 的 init 或 systemd)。

当您运行命令时,可以在两种主要模式下进行:

默认情况下,命令在前台运行。Shell 会等待进程完成,然后才返回命令提示符 ($)。当前台进程运行时,您通常无法在该终端中输入新命令。

进程通常从键盘接收输入(标准输入,standard input),并将输出发送到屏幕(标准输出,standard output 和标准错误,standard error)。

# This command runs in the foreground. The prompt won't return until it finishes.
$ sleep 10
# (Waits 10 seconds)
$

您通常可以通过按 Ctrl + C 来中断前台进程。

后台进程 (background process) 独立于 Shell 运行。您会立即获得命令提示符,允许您在后台进程继续执行的同时运行其他命令。

要在后台运行命令,在命令行末尾附加一个与号 (&)。

# Run the sleep command in the background
$ sleep 60 &
[1] 12345 # The shell reports the Job ID ([1]) and the PID (12345)
$ # Prompt returns immediately, sleep continues for 60 seconds

后台进程与键盘输入断开连接。如果它们尝试从标准输入读取,通常会暂停(变为停止状态)。除非重定向,否则它们的输出仍然会发送到终端。

当后台作业完成时,Shell 通常会打印一个通知:

$ # (After 60 seconds)
[1]+ Done sleep 60

ps (process status) 命令显示关于运行中进程的信息。其用法在不同的 Unix 版本之间略有差异,但存在一些常见的调用方式。

基本用法(显示与当前终端关联的进程):

$ ps
PID TTY TIME CMD
5678 pts/0 00:00:00 bash
12389 pts/0 00:00:00 ps

用于更全面列表的常用选项:

  • System V 风格: ps -ef (或 ps -eF 用于额外详细信息)
  • -e:显示所有进程。
  • -f:完整格式列表 (UID, PID, PPID, C, STIME, TTY, TIME, CMD)。
  • BSD 风格: ps aux (或 ps auxww 用于更宽的命令输出)
  • a:显示所有用户的进程。
  • u:用户导向格式 (USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMAND)。
  • x:显示未连接到终端的进程(如守护进程)。

使用 System V 风格的示例:

$ ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:00 ? 00:00:05 /sbin/init
root 2 0 0 09:00 ? 00:00:00 [kthreadd]
...
user 5678 5670 0 09:15 pts/0 00:00:00 /bin/bash
root 8901 1 0 09:20 ? 00:00:01 /usr/sbin/sshd -D
user 12345 5678 0 10:05 pts/0 00:00:00 sleep 60
user 12390 5678 0 10:06 pts/0 00:00:00 ps -ef

关键列通常包括:

  • USER / UID:运行进程的用户。
  • PID:进程 ID。
  • PPID:父进程 ID。
  • %CPU:CPU 使用率。
  • %MEM:内存使用率。
  • STIME / START:启动时间。
  • TTY:控制终端(? 表示没有)。
  • TIME:累计 CPU 时间。
  • CMD / COMMAND:正在运行的命令。

终止 (terminate) 进程通常是必需的。

  • Ctrl + C:向前台进程发送中断信号 (SIGINT),通常会使其终止。
  • kill PID:向指定 PID 的进程发送终止信号 (SIGTERM, 默认信号 15)。这是一个礼貌的终止请求,允许进程进行清理。
  • kill -9 PID 或 kill -SIGKILL PID:发送 kill 信号 (SIGKILL, 信号 9)。这会强制立即终止,应作为最后的手段使用,因为进程没有机会保存数据或进行清理。
  • pkill process_name:向所有匹配给定名称的进程发送信号(默认 SIGTERM)。
  • killall process_name:类似于 pkill,但在不同系统上的具体行为可能略有差异。通常对匹配精确的进程名称更严格。

示例:查找并终止一个 sleep 进程。

# Start a sleep process in the background
$ sleep 300 &
[1] 13579
# Find its PID (assuming we didn't note it)
$ ps aux | grep 'sleep 300'
user 13579 0.0 0.0 1234 567 pts/0 S 10:15 0:00 sleep 300
user 13581 0.0 0.0 6789 1234 pts/0 S+ 10:15 0:00 grep sleep 300
# Send the default termination signal (SIGTERM)
$ kill 13579
# Check if it's gone (wait a moment)
$ ps aux | grep 'sleep 300'
# (Should only show the grep command itself now)
# If kill didn't work, force kill
# kill -9 13579
# Alternatively, using pkill:
$ pkill sleep
[1]+ Terminated sleep 300

通常,您只能杀死您自己的进程,除非您是 root 用户。

Shell 提供作业控制 (Job Control) 功能来管理当前会话中的后台进程和停止的进程。

  • jobs:列出从当前 Shell 启动的作业(后台或停止的进程),显示它们的作业 ID (job ID)(例如,[1], [2]) 和状态。
  • fg %job_id:将后台或停止的作业带到前台。示例:fg %1。
  • bg %job_id:在后台恢复停止的作业。示例:bg %2。
  • Ctrl + Z:暂停(停止)当前前台进程,并将其放到后台。然后您可以使用 bg 在后台恢复它,或使用 fg 在前台恢复它。
# Start two jobs
$ sleep 100 &
[1] 14001
$ sleep 200 &
[2] 14002
# List jobs
$ jobs
[1]- Running sleep 100 &
[2]+ Running sleep 200 &
# Bring job 1 to the foreground
$ fg %1
sleep 100
# (Now sleep 100 is in the foreground. Press Ctrl+Z)
^Z
[1]+ Stopped sleep 100
# List jobs again
$ jobs
[1]+ Stopped sleep 100
[2]- Running sleep 200 &
# Resume job 1 in the background
$ bg %1
[1]+ sleep 100 &
# List jobs again
$ jobs
[1]- Running sleep 100 &
[2]+ Running sleep 200 &
  • 孤儿进程 (Orphan Process):其父进程已终止的进程。孤儿进程通常由 init 进程 (PID 1) 或其现代等效进程 (systemd) 领养。
  • 僵尸进程 (Zombie Process)(或 defunct process):一个已完成执行但仍在进程表中保留条目的进程。这发生在父进程尚未读取其子进程的退出状态 (exit status) 时。僵尸进程仅消耗极少的资源(只有进程表条目),但大量僵尸进程可能表明父进程存在问题。

僵尸进程通常在 ps 输出中显示为 Z 状态。您不能直接杀死僵尸进程;您需要终止其父进程,或者等待父进程正确处理子进程的退出(回收,reap)。

守护进程 (Daemon) 是在后台运行、与任何终端分离并执行系统任务或提供服务的进程。示例包括 Web 服务器 (httpd, nginx)、数据库服务器 (mysqld) 和 SSH 服务器 (sshd)。

它们通常在启动时启动并持续运行。在使用 systemd 的现代 Linux 系统上,这些进程通常作为“服务”通过 systemctl 命令进行管理(例如,systemctl status sshd, systemctl start nginx)。传统上,它们可能通过 /etc/init.d/ 中的 init 脚本进行管理。

top 命令提供了一个动态的、实时运行中进程视图,默认按 CPU 使用率排序。它显示系统摘要信息(平均负载,CPU 状态,内存使用率)和进程列表。

$ top

top 是交互式的;按 h 获取帮助,按 q 退出,按 M 按内存排序,按 P 按 CPU 排序。

htop 是 top 的一个流行且增强的替代品,提供更用户友好的界面,支持颜色、滚动、更简单的排序和进程终止功能。如果未安装,您通常可以通过系统的包管理器 (package manager) 安装它(例如,sudo apt install htop 或 sudo yum install htop)。

$ htop