%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
# Buffer
## 闪念
> sudden idea
## 候选资料
> Read it later
%%
<br><br>
# 进程处理
#### 查询进程 PID—— pgrep
`pgrep [options] pattern` :根据指定 pattern 搜索进程,返回匹配的**进程 PID**
选项:
- `-f|--full`: 使用 `pattern` 指定的**完整命令行**进行搜索,而不仅是进程名。
- `-u|--uid`: 指定 UID,限制搜索范围为特定用户的进程
```shell
pgrep ssh # 查找名为ssh的进程的PID
pgrep -u username # 查找特定用户的进程
pgrep -f /path/to/command # 使用完整的运行命令行进行搜索
```
> [!example] 根据进程名查询其 PID
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-45084ABEB1A6FD50D56B06D523DF3BB2.png|527]]
#### 向进程发送信号——kill、pkill 命令
##### kill 命令
`kill [option] <pid>[...]` : 按 **PID** 向指定进程发送信号(默认为 `SIGTERM(15)` **请求终止**信号)
选项:
- `-l`:查看**信号列表**
- `-<signal>` 以**信号值**标识信号,例如:
- `-9`: 发送`SIGKILL(9)` 信号,强制终止
- `-19`:发送 `SIGSTOP(19)` 信号,强制暂停
- `-18`:发送 `SIGCONT(18)` 信号,恢复被暂停的进程
- `-s <signal>` 以**信号名**标识,例如`SIGKILL` 或 `KILL` 等:
- `-s KILL` | `-s SIGKILL` :发送`SIGKILL(9)` 信号,强制终止
- `-s STOP` | `-s SIGSTOP` :发送 `SIGSTOP(19)` 信号,强制暂停
- `-s CONT` | `-s SIGCONT`:发送 `SIGCONT(18)` 信号,恢复被暂停的进程
```shell
kill <PID> # 默认发送"TERM"信号(值为15), 请求终止.
kill -9 <PID> # 发送"KILL"信号(值为9), 表示"无条件终止"
kill -s KILL <PID> # 与上等价
kill -1 <PID> # 与上等价
kill -s HUP <PID> # 将进程挂起
```
> [!note] `kill -l` 查看信号列表
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-B3F02F913A5A7E1B2C516431B4B08B6D.png|845]]
##### pkill 命令
`$ pkill <p_name>` 按 **进程名** 向指定进程发送信号(默认为 `SIGTERM(15)` 请求终止信号)
选项:
- `-f|--full`: 使用 `pattern` 指定的**完整命令行**进行搜索,而不仅是进程名。
```shell
# 向所有名为python的进程发送 "TERM"信号
pkill python
# "-f"参数表示匹配完整的命令行,而不仅是程序名.
pkill -f <full_command>
# kill掉所有启动命令为 "python3 -u run_train.py"的进程
pkill -f "python3 -u run_train.py"
```
<br><br>
# 后台作业控制
#### 以后台方式运行——&
`command &`:命令后加上`&` 符号,表示在**后台**运行该命令
<br>
#### 查看后台作业信息——jobs
`$ jobs [options]`:查看 **当前 shell 中的后台作业**(仍在运行或已停止的后台作业)
选项:
- `-l`:显示每个后台作业的 **PID**
- `-p`:仅显示每个作业的 PID
- `-n`:仅列出**有状态变化**的作业(例如刚停止或刚恢复)
- `-r`:只列出**正在运行**的作业(Running)
- `-s`:只列出**已停止**的作业
> [!NOTE] jobs 显示说明——默认共三个字段:**后台作业号**、**进程状态**、**进程启动命令**
>
> 作业号标识:
>
> - `+`:**默认作业/当前作业**。使用 fg 或 bg 命令而不带作业号时,**默认即操作该作业**。
> - `-`:**上一个作业**。即 "**默认作业**" 之前的作业,默认作业结束后,**该作业就会变为新的默认作业**。
>
> 进程状态有三种:Running、Stopped、Done
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-65F3A6D2CAFCA1AA58D72FC23F6DE341.png|570]]
> [!info] jobs 会列出以下作业
>
> - 当前 shell 中使用 `&` 启动的后台任务
> - 当前 shell 中被 `Ctrl+Z` 暂停的前台任务(进入后台、状态为 Stopped)
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-20B7D1D10C4557D4E953C8E44422DFA8.png|457]]
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-90DBCDC8718C7FA13F4C8CF4FD2D987C.png|464]]
>
<br>
#### 前后台作业控制——fg、bg
- `fg %[job_id]`:将后台任务 **切回==前台==继续运行**。
- `bg %[job_id]`:让 **被暂停/挂起的后台作业** 在后台 **继续运行**。
> [!example]
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-62B0BBDBE73223C8129C5A55C5F16DC7.png|562]]
<br><br>
### nohup 命令——后台运行并忽略挂起信号
`nohup` 命令 **用于运行另一个命令并==忽略所有发给该命令的挂起信号== `SIGHUP`**。(含义:no hang up)
**==`nohub` 命令== 搭配 ==后台模式 `&`== 来运行另一个进程,可使其在终端注销或关闭后继续运行,不被 `SIGHUP` 信号终止**
```shell
nohub command [args...] &
```
<br>
#### `nohup` 下的运行输出
由于 nohup 命令会**解除终端与进程之间的关联**,因此进程的 STDOUT、STDERR 不再同终端绑定。
**`nohup` 会自动将所运行进程的 STDOUT 和 STDERR 消息==重定向==到名为 `nohup.out` 的文件中。**
(通常在当前工作目录创建,否则会在 `$HOME` 目录创建)
> [!caution] 当使用 nohop 运行另一个进程时,后者的输出会被 **==追加==到已有的 `nohup.out` 文件中**。
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-D76DC12EB35A7986D78AE6250C537414.png|604]]
>
> 当运行位于同一目录中的多个进程时,务必当心,因为**所有的命令输出都会发送到同一个 `nohup.out` 文件中**。
> [!tip] 建议每次使用 `nohup` 时 **==手动指定输出重定向==**,例如:
>
> ```shell
> nohup ./script.sh > output.log 2>&1 &
> # 等价于
> nohup ./script.sh &> output.log &
> ```
>
<br><br>
### screen 工具——会话管理
> Ubuntu 上默认没有安装 screen。
screen 是一个会话管理工具,允许 **在一个单独的 shell 会话** 中管理多个终端窗口,并能在需要时从这些窗口中**分离和重新连接**。
例如,可在远程连接中启动 `screen` 会话,运行程序或任务,然后断开连接,之后再重新连接到同一个会话,而在断开期间,程序继续运行。
screen 功能:
- **会话管理**:在一个 shell 终端中可创建**多个 screen 会话**,每个会话有独立的屏幕空间,**可在不同会话间切换**
- **会话持久性**:可以断开与 `screen` 会话的连接,**会话中运行的程序会继续运行在后台执行**,此后可以重新连接到该会话。
- **窗口管理**:**在一个 `screen` 会话中可以创建多个窗口**,每个窗口也占有独立的屏幕,可以运行不同的命令或程序,提供了多任务处理的能力。
> [!note] `screen` 会话管理
>
>
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-5A14339C8B08A913ECA03FF17E6AB9DE.png|569]]
> [!NOTE] `screen` 窗口管理
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-194E34381B2F720F9C71053568DFB3A8.png]]
>
#### 会话管理相关命令
```shell
# 创建会话
screen
# 创建会话并指定一个会话名
screen -S <screen_name>
# 进入/恢复会话
screen -r <screen_name>
# 列出会话列表, 即显示所有会话
screen -ls
# 删除会话
screen -X -S <screen_name>
```
- `Ctrl+D`:**删除** 当前 screen 会话
- `Ctrl+A + D`:**退出** 当前 screen 会话(当前 screen 会话将在后台继续运行)
> [!NOTE] 检查当前是否位于 screen 会话中
>
> - 查看 `STY` 环境变量:如果环境变量 `$STY` 非空,则意味着可能在一个 screen 会话中
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-0D0B229838745669F557DCD6981491F8.png|402]]
>
> - 查看 `TERM` 环境变量:screen 会话的 `TERM` 变量通常设置为 `screen` 或类似的值。
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-4742F41698597086D92FECEF58F8419D.png|390]]
>
> - 检查当前 shell 的父进程:使用 `ps -p $PPID` 命令
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-5BFB7B59EDCA2009F600539B38C7E4D1.png|371]]
>
<br><br>
# 实时显示进程资源占用情况——top 命令 ⭐
> top 命令用于实时查看**系统资源占用情况**,包括 CPU、内存、进程状态等。
`top` 命令:
- `-p <pid[,pid...]>`:只查看指定进程的信息
- `-u <user>`:只查看指定用户的进程
- `-d <秒>`: 设置**刷新间隔**(默认为 3 秒)
- `-n <次数>`:完成**指定刷新次数**后退出
- `-H`:以 "**线程视图**" 打开(默认是进程视图)
- `-c`:显示**进程启动的完整命令行**(默认只显示程序名)
> [!example] `top -H` 线程视图
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-10D517E738B54D188B93B5A6DC0387A2.png|540]]
>
> `top -H -p <pid>` :查看指定进程中**各个线程**的资源占用情况
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-59C19D6EBA5A1DDD7B93DBAE4DE55CB6.png|591]]
>
> `top -H -p <pid>,<pid>`:查看多个进程的情况:
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-CDF7A20AB91C27738AEEDC2071FD9801.png|517]]
>
<br>
## top 字段说明
示例:
![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-FD219BE2A32045EF00CD7B8803ACDD30.png|670]]
#### (1)顶部系统信息
###### 第一行 top:系统运行状态
| | 字段 1 | 字段 2 | 字段 3 | 字段 4 |
| --- | -------- | ------------------- | ------------- | ---------------------------- |
| 含义 | 当前系统时间 | 系统自启动以来已运行时间 <br> | 当前**登录的用户数量** | **系统负载**(1 分钟、5 分钟、15 分钟平均值) |
| 示例 | 19:21:08 | **up** 1 day, 14:43 | 4 users | load average: 0.09,0.23,0.26 |
> [!info] Load Average 值的含义
>
> load average 值:过去 **1/5/15 分钟内** 处于 **==Runnable 状态==的任务数** 的指数加权移动平均值(**EWMA**)。
>
> - 值范围是 $[0, ∞)$,没有明确上界;
> - Linux 系统 **==每 5 秒==** 记录一次 "**正处于 ==Runnable 状态==的任务数量**”,然后更新**时间窗口内**(1/5/15 分钟)的 EWMA **移动平均值**。
> - 例如过去 1 分钟内,一半时间内**只运行着一个任务**,另一半时间系统完全空闲,则 load average: 0.5。
> - "**任务**" 是指调度单位,可等价理解为 "**线程**"。
> - **只计入 ==Runnable 状态==的任务数**,其它休眠、暂停、僵尸进程都不计入。
>
> 简单来说,其值反映过去 1/5/15 分钟内,**==需要使用 CPU 的平均任务总数==**(也即 **CPU 调度队列的平均长度**,包括正在占用 CPU 的 + 处于就绪状态正等待调度的任务总数)
>
> 以 4 核 CPU 为例,`load average: 8.0` 意味着近 1 分钟内 **平均有 8 个任务在争抢 CPU**,而 CPU 共 4 核,故此时系统已过载。
###### 第二行 Tasks:进程统计
| | totaol | running | sleeping | stopped | zombie |
| --- | ------------- | --------------------- | -------- | ------- | ------ |
| 含义 | 系统中**当前进程总数** | **正在运行的进程总数**(占用 CPU) | 休眠进程总数 | 暂停进程总数 | 僵尸进程总数 |
###### 第三行 %Cpu(s):CPU 使用情况(所有核心的平均值)
| 字段 | 解释 | 含义 |
| --- | -------------- | --------------------------------------------------------------------- |
| us | UserMode | **用户态**占用 CPU 百分比(执行普通程序) |
| sy | SystemMode | **内核态**占用 CPU 百分比(执行系统调用) |
| ni | | **用户进程**中被设置 nice 值的进程占用百分比 |
| id | idlle time | **CPU 空闲时间百分比** |
| wa | wait I/O | CPU 处于 "**空闲状态**" 且系统中**有进程因为等待 I/O 而阻塞**,该状态下 CPU 空闲时间占 CPU 总时间的百分比。 |
| hi | hard interrupt | 处理 **硬件中断** 占用的 CPU时间百分比 |
| si | soft interrupt | 处理 **软件中断** 占用的 CPU时间百分比 |
| st | Steal time | 当前 “**虚拟机**“ 被 “**宿主机**” 偷走 CPU的时间(物理机上运行的系统则恒为 0) |
###### 第四行 Mib Mem:物理内存(RAM)使用情况
| | total | free | used | buff/cache |
| --- | --------- | -------- | ----------- | ----------------------------- |
| 含义 | 总内存容量(MB) | 空闲内存(MB) | 已用内存(不包括缓存) | **buffer 或 page cache 占用**的内存 |
###### 第五行 MiB Swap:交换分区(Swap)使用情况
| | total | free | used | avail Mem |
| --- | ----------- | ----------------- | --------- | ---------------------------- |
| 含义 | 总交换分区大小(MB) | 剩余可用的 swap 空间(MB) | 当前已用 swap | 可用内存(包括可被回收的内存,如 page cache) |
#### (2)进程列表部分
| 字段 | 说明 |
| ------- | ---------------------------------------------------------------------- |
| PR | 进程优先级(Priotity),**值越小,优先级越高** |
| NI | nice 值,**负数表示高优先级**,正数表示低优先级,范围:-20 ~ 19 |
| VIPT | **虚拟内存使用量**(Virtual Memory)——**进程申请的所有内存**,包括未实际使用的、共享库占用的等 |
| RES | **实际占用的物理内存**(Resident Memory)。不包括交换分区,不包括共享库未修改部分 |
| SHR | **共享内存大小**(和其他进程共享的内存,如共享库) |
| S | **进程状态**(`R`=运行中,`S`=可中断休眠,`D`=不可中断休眠,`Z`=僵尸,`T`=暂停或被调试) |
| %CPU | 进程当前 **使用的 CPU 百分比**(相对于一个核心);例如,若值为 300% 说明使用了三个核心 |
| %MEM | 进程当前 **占用的物理内存百分比** |
| TIME+ | **累计占用的 CPU 时间**,格式为 `MM:SS.hh` (`分钟:秒.百分秒`),例如 `0:03.45` 表示占用 3.45 秒 |
| COMMAND | 启动该进程的命令或可执行文件名 |
> [!info] 注:VIPT = RES + SWAP + 映射文件 + 保留的未分配空间
> [!NOTE] PR 和 NI 的关系(进程调度优先级)
>
> Linux 中,调度优先级 **PR = 基础优先级 + NI**。
> 其中,NI 值可通过 `nice` 和 `renice` 命令调整。
<br>
## top 交互界面快捷键
| 按键 | 说明 |
| -------- | ----------------------------------------------------------------------- |
| `q`(小写) | 退出 top 界面 |
| `h` | 交互界面帮助信息 |
| | |
| `H` | 切换 **线程/进程视图** |
| 1 | 显示/隐藏 **每个 CPU 核心**的具体使用率 |
| `d` | **修改刷新时间**(默认 3 秒) |
| `t` | 切换 **CPU 使用率**的显示方式(共三种) |
| `m` | 切换 **内存使用率** 的显示方式 |
| `E`/ `e` | 切换 **顶部栏/任务列表** 中 "**内存使用**" 的 "**单位**"(默认MiB,可切换为 GiB、TiB、PiB、EiB、KiB) |
| `c`(小写) | 显示/隐藏 **进程运行的完整命令行** |
| | |
| `u` | 只显示**指定用户的进程** |
| `L` | 按**字符串**筛选 |
| `=` | **清除所有筛选条件** |
| | |
| `x` | 高亮 **当前排序列** |
| `b` | `x` 列的高亮模式:**加粗** or **背景高亮** |
| | |
| `P` | 按 "**CPU 使用率**" 排序(默认,即 %CPU 字段) |
| `M` | 按 "**内存使用率**" 排序 |
| `T` | 按 "**CPU 时间**" 排序(即 TIME+字段) |
| | |
| `k`(小写) | **向进程发送信号** |
| `r`(小写) | 修改进程的 nice 值 |
> [!NOTE] 交互界面下 `h` 显示的帮助信息:
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-501F47A47FBF5A418E78424DCBC10F64.png|546]]
> [!NOTE] `t` 切换 CPU 使用率显示方式(三种 + 不显示)
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-FAC1277C0C9CDA3A120FED49D8483E12.png|637]]
> [!NOTE] `E` / `e` 切换 **顶部栏/任务列表** 中 "**内存使用**" 的 "**单位**"
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-AD686F8E9CE1A54FD15C375958DB919F.png|502]]
<br><br>
# 查看所有进程信息——ps 命令 ⭐
`ps` :默认显示 **==当前用户==的**、**从==当前终端==中启动的进程**(all "your" process started from the current terminal)
BSD 风格选项:
- `a`:显示 ==**所有用户== 的 ==有控制终端== 的进程**(即前台交互式进程) => All process with terminal. Lift the BSD-style "**only yourself**" restriction.
- `x`:显示 **==当前用户== 的 ==所有进程==**(即包括无控制终端的 **守护进程、后台进程** ) => Lift the BSD-style "**must have a tty**" restriction.
- `u`:显示 **详细信息**(user-orentied format),包括 USER、==%CPU==、==%MEM==、VSZ、RSS、==STAT== 字段
System V 风格选项:
- `-e|-A`: 显示**系统中所有进程**
- `-f`:**全格式**显示(full-format),包含 UID、PPID,且 CMD 列显示**完整命令行**,还包括 **CPU 利用率(C)**、**进程启动时间(STIME)**
- `-l`:**长格式**显示(long-format),包含**进程状态、进程优先级**等信息
- `-o`:**自定义显示字段**,例如 `-o pid,ppid,user,stat,%cpu,%mem,cmd`
- `-p <pid...>`:查看指定进程(可省略`-p`,**==直接跟 `pid`==**,例如 `ps [pid]`)
- `--ppid <ppid>`:按**父进程**筛选
- `-u <user>`:按指定的 "**有效用户**" 进行筛选(effective UID,==EUID==)
- `-U <user>`:按指定的 "**真实用户**" 进程筛选(real UID,==RUID==)
- `-C <command>`:按**进程启动命令**筛选
- `--sort=[-]<col>`:**指定排序的列**(列名前带 `-` 表示**降序排列**)
- `-y`:仅搭配`-l` 使用,不显示 FLAGS 字段,显示 RSS 字段来代替 ADDR 字段。
- `-H`:显示**进程树结构**
- `--forest` 使用 ASCII 字符**绘制进程的层级信息** => 直观追踪父子进程
> [!quote]
>
> By default, `ps` selects all processes **with the same effective user ID (euid=EUID) as the current user** and **associated with the same terminal as the invoker**.
> For example, if you **open a gnome-terminal and give the ps command**, it will list **all your processes started from that terminal**. [^1]
> [!NOTE] 关于 EUID 与 RUID
>
> - **EUID(Effective UID,==有效用户==)**:该进程运行时 **享有其权限的用户**,决定了进程访问权限
> - 例如, `sudo` 启动进程,则**进程的有效用户是 root**。
> - EUID 可以在进程运行期间改变,通过使用 `setuid`、`seteuid` 等系统调用来改变进程的权限。
> - **RUDI(Real UID,==真实用户==)**:启动这个进程的 "**实际用户**",是谁运行的这个程序
> - 例如,执行 `sudo` 前的用户是 yht。
>
> **ps 中各选项下显示的 USER 或 UID,均为 ==EUID==**,若要**查看 RUID**,可使用 `ps -o ruid` 指定显示该字段。
> [!NOTE] `ps` 的命令选项风格
>
> ps 命令的选项有**三种风格**(由于历史原因),输出信息略有不同,
>
> | | 说明 | 示例 |
> | --------------- | --------------------------- | ------------- |
> | **BSD 风格** | 无中划线,例如 `a`、`u`、`x` | `ps aux` |
> | **System V 风格** | 以中划线 `-` 起始,例如 `-e`,`-f`; | `ps -ef` |
> | GNU 长选项 | 双中划线,例如 `--forest`、`--sort` | `ps --forest` |
>
<br>
### 使用示例
```shell
# 查看系统中所有进程
ps aux
ps -el
# 查看指定进程(可多个)
ps [options] [-p|--pid] pid[,pid]
ps u [pid] # 长格式查看指定进程
# 查看当前进程的父进程
ps -p $PPID
# 显示CPU占用率前10的进程
ps aux --sort=-%cpu | head -n 10
```
## 字段说明
> [!note] 不同选项下显示的字段
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-50A9D23AAEF4A4A9F816EEA44951579F.png|606]]
| 所属选项 | 字段 | 含义 |
| ---------------------- | --------- | ----------------------------- |
| `ps` 基本字段 ↓→ | TTY | 控制终端 |
| | TIME | 进程使用的 **CPU 时间总和** |
| | CMD | 进程简略命令行 |
| | | |
| BSD 风格 `u` 选项 ↓→ | USER | **EUID,有效用户 ID** |
| | %CPU、%MEM | CPU、物理内存占用百分比 |
| | VSZ | 虚拟内存使用(KB) |
| | RSS | 实际物理内存使用(KB) |
| | STAT | 进程状态 |
| | START | 进程启动时间 |
| | COMMAND | 进程完整命令行 |
| | | |
| System V 风格 `-f` 选项 ↓→ | UID | **EUID,有效用户 ID** |
| | C | CPU 使用率 |
| | STIME | 进程启动时间 |
| | PPID | 父进程 ID |
| | | |
| System V 风格`-l` ↓→ | F | 进程标志位 |
| | S | 进程状态(仅显示主状态码) |
| | PRI | 动态优先级(越小越优先) |
| | NI | nice 值 |
| | ADDR | 进程在内核中的地址(已废弃或无意义,通常显示为 `-`) |
| | SZ | **虚拟内存页数** |
| | WCHAN | 正在等待的内核函数(如果 S 字段是 S 或 D 休眠时) |
### 关于 `CMD` 和 `COMMAND` 字段的内容差异
![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-进程相关命令.assets/IMG-Linux-进程相关命令-13EC3EBE21A7D551F6B449D983CDF007.png|656]]
`CMD` 和 `COMMAND` 两个字段在不同选项下,具体显示的内容略有不同[^2]:
- `COMMAND` 的内容是 "full command line with arguments";
- `CMD` 的内容有两种可能情况:
- `ps` 显示 "executable name/process accounting name",即 ==`ucmd`==,**可执行文件名**,**不可改**(the "**command**" format specifier)
- `ps -f` 指令显示 "reconstructed / full command line with arguments",即 ==`args`==,**可被修改** (the "**args**" format specifier)
> [!quote]
> 
>
> - `ps` uses the **default format**, which shows the pid, terminal, cumulated CPU time, and the **==executable name==** (`ucmd`).
> - The **executable name is not modifiable,** and reflects exactly **the name of the executable used**.
>
> - `ps -f` uses the full format, which among other fields, shows the **full command with arguments** (`command`, or `args`).
> - The **full command is modifiable**。
>
> `ps` and `ps -f` display different things for CMD: the executable name (`ps`, the "command" format specifier) and the reconstructed command line (`ps -f`, the "args" format specifier). The latter uses the process's ARGV and sees changes to it, while the executable name itself is unchanged.
<br>
### 进程 STAT 状态码
###### 主状态码
| 状态码 | 说明 | 触发场景 |
| --- | --------------------------------------------------------------------- | ----------------------------------- |
| R | 正在运行(Running/Runnable)——可能正占有 CPU,也可能**在调度队列等待调度**。 | |
| S | **可中断休眠**(Interruptible Sleeping) | 调用 `sleep()`、等待 socket I/O、等待信号量时; |
| D | **不可中断休眠**(Uninterruptible Sleeping) | 等待磁盘 I/O |
| T | **暂停**(Stoped)——收到**暂停信号(19 or 20)**而暂停,仅当收到 **SIGCONT(18) 信号**才会恢复执行 | 收到信号 SIGSTOP(19) 或 SIGTSTP(20) |
| t | **被附加调试**而暂停(traced) | 例如被 `gdb -p` 附加调试 |
| Z | 僵尸进程(Zombile) | 子进程结束但父进程未调用 `wait` 或 `waitpid` 回收 |
| X | Dead,已死进程(用户空间极少见,通常是内核回收标记时使用) | |
###### 状态修饰符
<br><br>
# 系统调用相关——strace
`$ strace <ELF_file>` 追踪程序代码中使用的系统调用
%%
# 协程相关
> `coproc` 是 `bash` 中的关键字,而非独立的`Linux` 命令,所以 `man` 手册中查无此命令。
`$ coproc` :**在后台**创建一个 **子 shell** 并**在子 shell 中执行指定命令**,同时与该子 shell **建立一个双向通信的管道**。
当在bash脚本或交互式bash会话中使用`coproc`,**bash 会为子进程的标准输入和标准输出创建管道**,并为这些文件描述符分配一个**数组**名,使你可以在主进程中读取或写入这些文件。
- `coproc` 会将进程名称默认设置为`COPROC`。只有在拥有多个协程时才需要对协程进行命名,因为要和它们进行通信,需要进行区分。
```shell
# 自定义协程的进程名字.
# 左花括号之后, 右花括号之前必须有一个空格。内部命令必须以分号`;`结尾。
coproc My_Job { sleep 10; }
# 示例:
# 使用coproc启动一个简单的bc进程(计算器工具)
coproc CALC { bc; }
# 向bc进程发送一个计算表达式
echo "5 + 5" >&"${CALC[1]}"
# 读取bc进程的输出
read -r result <&"${CALC[0]}"
echo "The result is: $result"
# 关闭文件描述符
exec {CALC[0]}>&-
exec {CALC[1]}>&-
```
> 
%%
<br><br><br>
# 参考资料
# Footnotes
[^1]: [What is the difference between ps and ps -e command in linux](https://stackoverflow.com/questions/29179251/what-is-the-difference-between-ps-and-ps-e-command-in-linux)
[^2]: [Why does the following two commands of ps give different \`CMD\` field? - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/492312/why-does-the-following-two-commands-of-ps-give-different-cmd-field)