进程在 Linux 中可以说是一个非常重要的概念,上到系统内核,下到一个很小的脚本,甚至是 ls 命令,都是进程的缩影。可能很多人对进程的概念还不是很清楚,以及具体怎么做,怎么管理等等。今天我们就分两个部分,详细的讲一下 Linux 的进程概念。
什么是进程
教科书级别的解释是:进程是程序的执行实例,是系统资源分配和独立运行的基本单位。
不要管那么多。说得不恰当一些,进程就是某个人现在正在做的事情,严格的说是任务。只不过放到系统层面而言,我们把它抽象化了。
比如说,出去买菜,这就是一个进程。买菜回来做饭,这也是一个进程。
进程的几个状态
运行:很简单,一个进程正在运行或者在运行队列中。比如说:正在买菜。
睡眠:一个进程正在等待某个事件完成(例如等待 I/O,有点像数据库里面的死锁),但可以被终止,又叫中断睡眠(浅度睡眠)。比如说:买菜的路上接到家里人的电话。
磁盘休眠:又叫不可中断睡眠(深度睡眠),说明一个进程必须等待某个事件完成才能继续,并且此时不可以被终止。比如说:买菜在等摊主找零,必须等找完才能离开。
停止:一个进程被暂停,但稍后可以被恢复继续。比如说:买菜的路上先去买了一杯棒打鲜橙或者杨枝甘露。
僵尸:大多出现在子进程内,指的是子进程结束(停止)后,父进程因某些原因未能读取子进程信息的状态。比如说:A 委托 B 去买东西,B 买完之后通知 A,A 恰好在忙,没来得及理会。
死亡:持续时间极短,只是一个返回状态,用于告知系统一个进程已经完成使命,随后系统会立即释放该进程占有的资源。比如说:B 买完了东西回来,A 拿到东西后让 B 去忙自己的事情。
孤儿:和僵尸状态相对,指的是子进程仍然在运行时,父进程因某些原因突然结束或异常终止的状态。此时子进程会被
systemd进程(系统启动时最先运行的进程,编号为 1,直至系统关机。某些老的系统内是init)“收养”,直至结束。比如说:A 和 B 买菜时,A 让 B 去某个摊位买梭子蟹,B 在买鱼的时候,A 突然接到电话说要立即去开会,就立即赶到公司,B 回来时,找不到 A.
管理进程
Linux 系统提供了多个命令方便我们检查和管理进程。
top, htop 和 btop
这三个程序都能直观地(动态)显示当前系统的资源状况和进程。
其中 top 是系统自带,而 htop 和 btop(别称 btop++)需要自己安装。当然,在某些系统内,htop 也是预装的。
以 btop 为例,安装的命令如下:
# Debian/Ubuntu
sudo apt install btop
# Fedora
sudo dnf install btop
# For RHEL/CentOS/AlmaLinux 8+/RockyLinux:
# You need to install "epel-release" first.
# Arch Linux
sudo pacman -S btop
# openSUSE
sudo zypper in btop
# A manual installation for other distributions is mandatory直接输入对应的程序名称(例如 btop)即可查看当前系统进程状态:

虽然上面用的是更加先进的 btop,但我们还是有必要科普一下 top 每一行的含义。
在下面一个 top 界面中:

第一行的参数如下表:
第二行的参数如下表:
第三行的参数如下表:
第四行的参数如下表:
第五行的参数如下表:
第六行(空行不算)的参数如下表:
下面就是一些进程的详细信息,这里就不多讲了。
一些使用技巧如下:
top -d 1
# refresh by 1 second
top -d 1 -p 10126
# look at information of process 10126
top -d 1 -p 10126,1
# look at processes 10126 and 1查看一个进程
Linux 内有一个命令 ps(不是 P 图的那个!它的全称是 process management,进程状态)可以静态查看进程。这样获取到的进程信息是固定的某一瞬间,有点像抓拍到的照片。
我们先运行这个命令:
ps aux结果如下:

输出的内容非常多,这里只是截取的一部分。
我们先来看看字段名称:
USER:指的是创建进程的用户,也就是哪个用户(你还记得几种?)创建了这个进程。
PID:指的是进程的 ID. 系统会从 1 开始(对应的是
systemd)将每一个进程编号。这个字段非常重要,因为后面当我们需要杀死进程时就需要进程的 PID.%CPU:指的是该进程占用 CPU 的比率。
%MEM:指的是该进程占用内存的比率。
VSZ:指的是该进程占用虚拟内存(或者交换空间)的量。
RSS:指的是该进程占用实际内存的量(不是 RSS 订阅!)。
TTY:指的是该进程运行的终端(后面会讲)。“?”表示该进程由系统启动。
STAT:指的是进程的状态。主要分为 R, S, T, Z, X(运行,睡眠,停止,僵尸,死亡)五种。
START:指的是该进程启动的时间。
TIME:指的是该进程占用 CPU 的总时间。
COMMAND:指的是该进程的名称。
一个比较常用的方法是,将该命令和管道(后面会讲)结合使用。例如,要查找名称为 sleep 114 的进程(假设没有其他进程创建了这个进程):
ps aux | grep sleep在使用 ps 命令时,我们也可以指定参数,以期获得不同排序指标下的进程状态。
例如,按照 CPU 占用率排序(默认是升序,如果要降序在 %cpu 前加“-”;有没有“=”连接 --sort 和 %cpu 其实都可以):

另一个常用的命令是 ps -ef ,它能以完整格式(从 Full Format 直译的,我也不清楚是什么)列出所有的进程:

这个命令还会列出父进程的 PID(0 就是不存在),这样可以方便我们查看进程可能的依赖关系。
ps 命令也支持自定义字段:

自定义字段名必须参照原格式,中间用逗号分隔,并且不允许有空格。
杀死进程
kill 命令可以用来杀死(强制终止)某个进程,也可以向某个进程发送其他的一些信号。
下面是这个命令支持的一部分信号(可以通过 kill -l 查阅):
相应的,该命令的格式如下:
kill -[SignalNo] [SID]例如:
kill -9 14871
# KILL the process with PID of 14871
kill -15 14888
# Terminate the process with PID of 14888进程优先级
Linux 系统内存在 2 种优先级,分别是 PR 值和 nice 值。下面我们来重点说说 nice 值。
进程的优先级(nice)是一个位于区间 [-20, 20) 的整数数值,其中在区间映射的 x 轴上,数值越靠左(越靠近 -20),该进程的优先级越高,反之越低。这和数学上的负数意义还是不一样的!
至于另一种 PR 值,则是将 nice 值映射到更大的优先级队列,即将 -20 映射到 0,+19 映射为 39. PR 值也允许负值,且下不兜底。
那么,为什么必须要有优先级呢?像人一样,在每一个时间点上每一个 CPU 只能处理一个进程,因此 CPU 必须通过明白各个进程的轻重缓急,优先决定哪些进程要先处理,再结合时间片技术,进而同时运行多个程序。
查阅进程的优先级
下面的命令可以查看进程的 nice 级别:
ps aux --sort=-nice | head -5结果如下:

更改优先级
我们可以通过 nice 和 renice 命令调整进程的优先级。
默认情况下,一个进程启动时,会继承父进程的优先级。要手动指定之,我们应该在该进程的前面使用 nice 命令:
nice -n -5 sleep 3600 &这个命令会创建一个 nice 值为 -5,名为 sleep 3600 的进程。后面的 & 表示创建该进程后,任其自然(不影响后续命令的执行,不会表现出等待 I/O),且仅返回其 PID.

如果在上面不小心输错了优先级怎么办?此时,renice 就作为“后悔药”来解决这一问题了。它的基本用法如下:
renice [newNiceValue] [PID] 例如:

结果是这样的:

更高级的用法可以参阅这里:
总结
进程是计算机中正在运行的程序的实例,它具有创建、执行和结束的生命周期,并包含代码、数据和系统资源;进程在其生命周期中会经历多个状态,主要包括就绪、运行、阻塞和终止等,这些状态反映了进程在CPU和内存中的活动情况。在管理进程方面,用户可以使用命令行工具如 top、htop 和 btop 来实时监控系统进程和资源使用情况,通过命令如 ps 查看特定进程的详细信息,并在需要时使用 kill 或 pkill 命令终止失控进程;此外,进程优先级(如 nice 值)允许用户调整进程的CPU调度顺序,可以通过 top 或 ps 命令查看优先级,并使用 renice 或 nice 命令动态更改它以优化系统性能。总之,理解进程及其管理对于维护系统稳定和高效运行至关重要。