监视Linux上的进程线程计数
1. 简介
现代 CPU 由多个内核组成。因此,为了利用多核处理器的强大功能,应用程序通常在多线程进程上运行。有时,我们可能需要有关特定进程使用多少线程的信息。在本文中,我们将向您介绍可用于检查和监控线程计数数据的所有工具和命令。
我们假设线程和进程的概念是已知的。因此,如果您不熟悉或想了解更多关于线程和进程之间的区别,请务必阅读我们的文章Linux 进程与线程 。
2. 检查线程数
在本节中,我们将了解如何获取进程的即时线程计数信息。总而言之,我们有几种选择。
2.1.使用ps命令
命令 ps 显示有关计算机上当前活动进程的信息。组合选项*-e和-f是我们可以用来以格式化方式获取每个进程的信息的标准方法。同样,我们可以附加-L选项让ps*报告附加线程信息:
$ ps -eLf
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 12:00 ? 00:00:01 /sbin/init splash
root 2 0 2 0 1 12:00 ? 00:00:00 [kthreadd]
root 3 2 3 0 1 12:00 ? 00:00:00 [rcu_gp]
root 4 2 4 0 1 12:00 ? 00:00:00 [rcu_par_gp]
root 6 2 6 0 1 12:00 ? 00:00:00 [kworker/0:0H-events_highpri]
root 9 2 9 0 1 12:00 ? 00:00:00 [mm_percpu_wq]
root 10 2 10 0 1 12:00 ? 00:00:00 [rcu_tasks_rude_]
root 11 2 11 0 1 12:00 ? 00:00:00 [rcu_tasks_trace]
root 12 2 12 0 1 12:00 ? 00:00:00 [ksoftirqd/0]
root 13 2 13 0 1 12:00 ? 00:00:00 [rcu_sched]
root 14 2 14 0 1 12:00 ? 00:00:00 [migration/0]
root 15 2 15 0 1 12:00 ? 00:00:00 [idle_inject/0]
root 16 2 16 0 1 12:00 ? 00:00:00 [cpuhp/0]
root 17 2 17 0 1 12:00 ? 00:00:00 [cpuhp/1]
.
.
.
blogdemo 1970 1350 1970 0 5 12:01 ? 00:00:01 /usr/libexec/gnome-terminal-server
blogdemo 1970 1350 1971 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
blogdemo 1970 1350 1972 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
blogdemo 1970 1350 1973 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
blogdemo 1970 1350 1977 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
blogdemo 1978 1970 1978 0 1 12:01 pts/0 00:00:00 bash
blogdemo 1996 1350 1996 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
blogdemo 1996 1350 1997 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
blogdemo 1996 1350 1998 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
blogdemo 1999 1607 1999 0 4 12:02 ? 00:00:00 update-notifier
blogdemo 1999 1607 2002 0 4 12:02 ? 00:00:00 update-notifier
blogdemo 1999 1607 2003 0 4 12:02 ? 00:00:00 update-notifier
blogdemo 1999 1607 2004 0 4 12:02 ? 00:00:00 update-notifier
root 2139 2 2139 0 1 12:07 ? 00:00:00 [kworker/u4:1-events_unbound]
root 2149 2 2149 0 1 12:15 ? 00:00:00 [kworker/1:1-cgroup_destroy]
root 2240 2 2240 0 1 12:32 ? 00:00:00 [kworker/0:1-events]
root 2241 2 2241 0 1 12:32 ? 00:00:00 [kworker/0:3-inet_frag_wq]
root 2247 2 2247 0 1 12:36 ? 00:00:00 [kworker/u4:0-events_unbound]
root 2298 2 2298 0 1 12:43 ? 00:00:00 [kworker/u4:2]
root 2335 2 2335 0 1 12:44 ? 00:00:00 [kworker/1:0-cgroup_destroy]
root 2336 2 2336 0 1 12:44 ? 00:00:00 [kworker/0:0-events]
blogdemo 2346 1978 2346 0 1 12:45 pts/0 00:00:00 ps -eLf
在输出中,NLWP(轻量级进程数)列指示附加到该特定进程的线程数。例如,当我们查看一个 NLWP 值大于 1 的进程时,我们可以看到它之后的相应行数具有相同的 PID 值。
但是,如果我们不想接收每个进程的所有这些杂乱信息并且我们只搜索特定进程的线程数,我们可以使用ps和*-o*选项:
$ ps -o nlwp 1970
NLWP
5
这里nlwp表示我们上面用来获取线程数信息的列,1970是一个进程的PID。正如我们所见,这个进程同时运行了五个线程。如果我们愿意,我们可以使用thcount而不是nlwp来获得相同的结果:
$ ps -o thcount 1970
THCNT
5
2.2. 检查*/proc*目录
以类似的方式,我们可以检查*/proc目录中的线程计数数据。/proc*是一个虚拟文件系统,包含有关进程的各种信息。我们来看看我们能得到哪些信息:
$ ls /proc/1970/task/
1970 1971 1972 1973 1977
正如我们在上面清楚地看到的,PID 为 1970 的进程包含五个线程。事实上,这个结果与我们之前使用命令ps得到的结果相匹配。此外,我们可以验证这些目录名称是否与LWP列下的相应结果完全相同。
查找线程计数信息的另一种方法是检查 方便文件夹下的status文件:
$ cat /proc/1970/status | grep Threads
Threads: 5
3. 监控线程数
到目前为止,我们已经研究了通过使用几种方法来获得即时结果。现在让我们看看我们想要实时监控状态的情况。
3.1. 将之前的命令与watch结合起来
当我们使用 watch工具结合上一节提到的命令时,可以实时监控任意进程的线程状态。我们还可以使用*-n*选项以秒为单位指定更新间隔。让我们看一个例子:
$ watch -n 1 ps -o thcount 1970
Every 1,0s: ps -o thcount 1970 blogdemo: Tue Mar 29 16:35:30 2022
THCNT
5
请注意,上述结果每秒刷新一次。 watch每秒运行命令 ps -o thcount 1970并将输出显示回控制台。
3.2. 使用top工具
*top *是一个内置程序,用于报告 CPU 使用率和内存状态等系统信息。我们可以使用此工具获取每个进程的线程数信息,但默认情况下它是禁用的。因此,我们将不得不手动调整该工具。首先,我们需要进入实用程序:
$ top
然后,在按下 f键后,我们将看到top可以显示的指标列表。让我们用d相应地选择nTH字段, 然后按q返回主界面:
top - 15:53:11 up 3:52, 1 user, load average: 0,14, 0,13, 0,09
Tasks: 198 total, 1 running, 197 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1,7 us, 0,7 sy, 0,0 ni, 97,3 id, 0,0 wa, 0,0 hi, 0,3 si, 0,0 st
MiB Mem : 971,2 total, 90,5 free, 543,3 used, 337,4 buff/cache
MiB Swap: 923,3 total, 718,7 free, 204,6 used. 273,4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND nTH
1622 blogdemo 20 0 4218272 304356 76152 S 2,3 30,6 2:22.32 gnome-shell 12
1416 blogdemo 20 0 286816 58088 24356 S 1,7 5,8 0:39.93 Xorg 2
1970 blogdemo 20 0 818528 43312 30420 S 1,0 4,4 0:16.31 gnome-terminal- 5
1547 blogdemo 20 0 158108 2068 1984 S 0,3 0,2 0:13.21 VBoxClient 4
1 root 20 0 167660 7924 5496 S 0,0 0,8 0:01.38 systemd 1
2 root 20 0 0 0 0 S 0,0 0,0 0:00.00 kthreadd 1
3 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_gp 1
4 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_par_gp 1
6 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 kworker/0:0H-events_highpri 1
9 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 mm_percpu_wq 1
10 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rcu_tasks_rude_ 1
11 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rcu_tasks_trace 1
12 root 20 0 0 0 0 S 0,0 0,0 0:00.21 ksoftirqd/0 1
13 root 20 0 0 0 0 I 0,0 0,0 0:00.53 rcu_sched 1
14 root rt 0 0 0 0 S 0,0 0,0 0:00.03 migration/0 1
15 root -51 0 0 0 0 S 0,0 0,0 0:00.00 idle_inject/0 1
16 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/0 1
17 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/1 1
需要注意的是**,PID 为 1970 的进程有五个线程,正如我们在之前的方法中看到的那样**。
我们还可以使用更现代的版本 htop。这个想法是一样的。但是,请记住,top通常是内置的,而我们可能需要手动安装htop 。