# 3.8.进程和守护进程

FreeBSD 是一个多任务操作系统。每个在任意时刻运行的程序都称为一个 *进程（process）*。每个正在运行的命令都会启动至少一个新进程，并且 FreeBSD 还会运行一些系统进程。

每个进程都有一个唯一的编号，称为 *进程 ID（PID）*。类似于文件，每个进程也有一个所有者和所属组，系统会依据所有者和组的权限来判断进程可以访问哪些文件和设备。大多数进程也有一个启动它们的父进程。例如，shell 是一个进程，而在 shell 中启动的任何命令也都是进程，它们的父进程就是该 shell。唯一的例外是一个特殊进程，叫做 [init(8)](https://man.freebsd.org/cgi/man.cgi?query=init\&sektion=8\&format=html)，它总是在系统启动时第一个启动，进程 ID 永远是 `1`。

某些程序并不是设计来持续接受用户输入的，它们会在合适的时机脱离终端。例如，Web 服务器是用来响应网络请求而不是用户输入的。邮件服务器也是这种程序的一个例子。这类程序被称为 *守护进程（daemon）*。daemon 一词来自希腊神话，表示一种既非善也非恶、在幕后默默执行有用任务的存在。这就是为什么 BSD 的吉祥物是那个穿着运动鞋、手持三叉戟、神态轻松的小恶魔。

守护进程的程序通常以 “d” 结尾命名是一种惯例。例如，BIND（Berkeley Internet Name Domain）的实际运行程序是 `named`；Apache Web 服务器程序是 `httpd`；打印服务的后台处理进程是 `lpd`。这只是命名习惯，例如 Sendmail 的主邮件守护进程叫做 `sendmail`，而不是 `maild`。

## 3.8.1. 查看进程

可以使用 [ps(1)](https://man.freebsd.org/cgi/man.cgi?query=ps\&sektion=1\&format=html) 或 [top(1)](https://man.freebsd.org/cgi/man.cgi?query=top\&sektion=1\&format=html) 查看系统中正在运行的进程。要显示当前运行的进程、它们的 PID、所使用的内存，以及启动它们的命令，可以使用 [ps(1)](https://man.freebsd.org/cgi/man.cgi?query=ps\&sektion=1\&format=html)。要以交互方式每隔几秒更新显示所有进程，以便实时观察系统正在执行的任务，可以使用 [top(1)](https://man.freebsd.org/cgi/man.cgi?query=top\&sektion=1\&format=html)。

默认情况下，[ps(1)](https://man.freebsd.org/cgi/man.cgi?query=ps\&sektion=1\&format=html) 只显示当前用户拥有的正在运行的命令。例如：

```sh
% ps
```

输出可能类似如下：

```sh
 PID TT  STAT    TIME COMMAND
8203  0  Ss   0:00.59 /bin/csh
8895  0  R+   0:00.00 ps
```

\[ps(1)] 的输出包含多个列。`PID` 列表示进程的 ID。PID 从 1 开始分配，一直到 99999，然后回绕到起点，但若某个 PID 已在使用，则不会重新分配。`TT` 列显示程序运行的终端设备，`STAT` 显示程序的状态，`TIME` 表示进程在 CPU 上实际运行的时间（而不是启动以来的总时间，因为大多数程序大部分时间都在等待）。最后，`COMMAND` 是启动程序时使用的命令。

可以通过不同的选项改变显示的信息。其中一个最有用的组合是 `auxww`，其中：

* `a` 显示所有用户的进程，
* `u` 显示用户名和内存使用信息，
* `x` 显示守护进程，
* `ww` 则让 ps 显示完整命令行，而不会因过长而截断。

\[Top(1)] 的输出类似如下：

```sh
% top
```

输出示例如下：

```sh
last pid:  9609;  load averages:  0.56,  0.45,  0.36              up 0+00:20:03  10:21:46
107 processes: 2 running, 104 sleeping, 1 zombie
CPU:  6.2% user,  0.1% nice,  8.2% system,  0.4% interrupt, 85.1% idle
Mem: 541M Active, 450M Inact, 1333M Wired, 4064K Cache, 1498M Free
ARC: 992M Total, 377M MFU, 589M MRU, 250K Anon, 5280K Header, 21M Other
Swap: 2048M Total, 2048M Free

  PID USERNAME    THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
  557 root          1 -21  r31   136M 42296K select  0   2:20  9.96% Xorg
 8198 dru           2  52    0   449M 82736K select  3   0:08  5.96% kdeinit4
 8311 dru          27  30    0  1150M   187M uwait   1   1:37  0.98% firefox
  431 root          1  20    0 14268K  1728K select  0   0:06  0.98% moused
 9551 dru           1  21    0 16600K  2660K CPU3    3   0:01  0.98% top
 2357 dru           4  37    0   718M   141M select  0   0:21  0.00% kdeinit4
 8705 dru           4  35    0   480M    98M select  2   0:20  0.00% kdeinit4
 8076 dru           6  20    0   552M   113M uwait   0   0:12  0.00% soffice.bin
 2623 root          1  30   10 12088K  1636K select  3   0:09  0.00% powerd
 2338 dru           1  20    0   440M 84532K select  1   0:06  0.00% kwin
 1427 dru           5  22    0   605M 86412K select  1   0:05  0.00% kdeinit4
```

输出分为两个部分：前五六行是标题区，显示了最近运行的进程 ID、系统负载（衡量系统繁忙程度）、系统运行时间（自上次启动以来），以及当前时间。其余数据包括：运行中进程数量、已用内存和交换空间（swap），以及 CPU 各状态所占百分比。如果加载了 ZFS 文件系统模块，还会显示一行 `ARC`，指示从内存缓存读取的数据量。

标题下面是与 ps 输出类似的各列信息，包括 PID、用户名、CPU 占用时间和启动进程的命令。top 默认还显示进程占用的内存空间，这分为两个列：一列是进程总共申请的内存（SIZE），另一列是当前实际使用的内存（RES）。

[top(1)](https://man.freebsd.org/cgi/man.cgi?query=top\&sektion=1\&format=html) 会每两秒自动刷新一次显示内容，可通过 `-s` 参数指定不同的刷新间隔。

## 3.8.2. 终止进程（Killing Processes）

与任何正在运行的进程或守护进程通信的一种方式是使用 [kill(1)](https://man.freebsd.org/cgi/man.cgi?query=kill\&sektion=1\&format=html) 发送一个 *信号（signal）*。有多种不同的信号；有些具有特定含义，其它的则可在应用程序文档中找到解释。用户只能向自己拥有的进程发送信号，若尝试向他人的进程发送信号将会导致权限拒绝错误。唯一的例外是 `root` 用户，它可以向任何人的进程发送信号。

操作系统本身也可以向进程发送信号。如果某个应用程序设计不良，试图访问其不应访问的内存，FreeBSD 会向该进程发送 “段错误（Segmentation Violation）” 信号（`SIGSEGV`）。如果某个应用程序使用了 [alarm(3)](https://man.freebsd.org/cgi/man.cgi?query=alarm\&sektion=3\&format=html) 系统调用来在一段时间后收到通知，它会收到 “闹钟” 信号（`SIGALRM`）。

可以用两种信号来终止一个进程：`SIGTERM` 和 `SIGKILL`。`SIGTERM` 是一种较为温和的终止方式，因为进程可以接收到信号、关闭任何已打开的日志文件，并尝试完成当前任务后再关闭。在某些情况下，如果进程正处于无法被打断的任务中，它可能会忽略 `SIGTERM`。

`SIGKILL` 是无法被进程忽略的 <注 ①>。向进程发送 `SIGKILL` 通常会立即终止该进程。\[^1]

其它常见的信号包括 `SIGHUP`、`SIGUSR1` 和 `SIGUSR2`。由于这些是通用信号，不同的应用程序会有不同的响应方式。

例如，在修改 web 服务器的配置文件之后，需要让 web 服务器重新读取配置。如果重新启动 `httpd`，可能会造成 web 服务的短暂中断。更好的方式是向该守护进程发送 `SIGHUP` 信号。需注意，不同守护进程的行为可能不同，因此请查阅对应文档以确定 `SIGHUP` 是否能达到预期效果。

> **重要**
>
> 随意终止系统中的某个进程是个坏主意。特别是 [init(8)](https://man.freebsd.org/cgi/man.cgi?query=init\&sektion=8\&format=html)，即 PID 1，是一个特殊进程。运行 `/bin/kill -s KILL 1` 会迅速但不推荐地关闭系统。*在*按下 <kbd>Return</kbd> *之前*，务必再次确认传递给 [kill(1)](https://man.freebsd.org/cgi/man.cgi?query=kill\&sektion=1\&format=html) 的参数。

* <注 ①>：有一些任务是无法被中断的。例如，如果进程试图从网络上另一台计算机的文件中读取数据，而另一台计算机不可用，则该进程被认为是不可中断的。最终，进程会超时，通常在两分钟后。若发生超时，进程将被终止。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://handbook.bsdcn.org/di-3-zhang-freebsd-ji-chu/3.8.-jin-cheng-he-shou-hu-jin-cheng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
