快速回答这个问题,可以使用以下方法获取正在运行给定PID的进程使用的线程数:
% ps -h -o nlwp <pid>
这将仅返回进程使用的线程总数。选项-h
删除头文件,选项-o nlwp
格式化ps
的输出,以便仅输出轻量级进程数量(NLWP)或线程。例如,当只运行单个进程puma
并且使用pgrep
获得其PID时,您会得到:
% ps -h -o nlwp $(pgrep puma)
4
进程、线程和轻量级进程有什么区别?
这个问题已经在各个地方得到了回答
[见这里,这里和优秀的geekstuff文章]。简而言之:
进程本质上是程序的任何运行实例。
线程是进程的执行流。包含多个执行流的进程称为多线程进程,并在其线程(内存、打开文件、io等)之间共享资源。Linux内核不知道线程
是什么,只知道进程。过去,多线程处理在用户级别上处理而不是内核级别上处理。这使得内核难以进行适当的进程管理。
引入轻量级进程(LWP)。这基本上是解决线程问题的答案。每个线程在内核级别被认为是一个LWP。进程和LWP之间的主要区别在于LWP共享资源。换句话说,轻量级进程是内核术语,用户称之为线程。
ps
可以显示有关线程或LWP的信息吗?
ps
命令或进程状态命令提供有关当前运行进程及其相应LWP或线程的信息。为此,它利用/proc
目录,这是一个虚拟文件系统,被认为是内核的控制和信息中心。[见这里和这里]。
默认情况下,ps
不会给您任何关于LWP的信息,但是在命令中添加选项-L
和-m
通常可以解决问题。
man ps :: THREAD DISPLAY
H Show threads as if they were processes.
-L Show threads, possibly with LWP and NLWP columns.
m Show threads after processes.
-m Show threads after processes.
-T Show threads, possibly with SPID column.
针对进程 puma
,其进程ID为 pgrep puma
% ps -fL $(pgrep puma)
UID PID PPID LWP C NLWP STIME TTY STAT TIME CMD
kvantour 2160 2876 2160 0 4 15:22 pts/39 Sl+ 0:00 ./puma
kvantour 2160 2876 2161 99 4 15:22 pts/39 Rl+ 0:14 ./puma
kvantour 2160 2876 2162 99 4 15:22 pts/39 Rl+ 0:14 ./puma
kvantour 2160 2876 2163 99 4 15:22 pts/39 Rl+ 0:14 ./puma
然而,加上
-m
选项会清晰地给出更好的概述。当多个进程使用相同的名称运行时,这尤其方便。
% ps -fmL $(pgrep puma)
UID PID PPID LWP C NLWP STIME TTY STAT TIME CMD
kvantour 2160 2876 - 0 4 15:22 pts/39 - 0:44 ./puma
kvantour - - 2160 0 - 15:22 - Sl+ 0:00 -
kvantour - - 2161 99 - 15:22 - Rl+ 0:14 -
kvantour - - 2162 99 - 15:22 - Rl+ 0:14 -
kvantour - - 2163 99 - 15:22 - Rl+ 0:14 -
在这个例子中,您可以看到进程
puma
的PID为2160,运行了4个线程(NLWP),ID为2160-2163。在
STAT
下面,您可以看到两个不同的值
Sl+
和'Rl+'。这里的
l
是
multi-threaded
的指示器。
S
和
R
分别代表
可中断休眠(等待事件完成)和
运行。因此,我们可以看到4个线程中有3个正在以99%的CPU运行,另一个线程正在睡眠。
您还可以直接使用格式说明符
-o
或
-O
来获取信息。同时您也可以看到总累计CPU时间为44秒,而单个线程只运行了14秒。
man ps :: STANDARD FORMAT SPECIFIERS
lwp lightweight process (thread) ID of the dispatchable
entity (alias spid, tid). See tid for additional
information. Show threads as if they were processes.
nlwp number of lwps (threads) in the process. (alias thcount).
所以您可以使用任何一个lwp
、spid
或tid
和nlwp
或thcount
。
如果您只想获取名为puma
的进程的线程数,您可以使用:
% ps -o nlwp $(pgrep puma)
NLWP
4
或者如果您不喜欢标题。
% ps -h -o nlwp $(pgrep puma)
4
您可以使用以下方法获取更多信息:
% ps -O nlwp $(pgrep puma)
PID NLWP S TTY TIME COMMAND
19304 4 T pts/39 00:00:00 ./puma
最后,您可以将标志与
ps aux
组合以列出线程。
% ps aux -L
USER PID LWP %CPU NLWP %MEM VSZ RSS TTY STAT START TIME COMMAND
...
kvantour 1618 1618 0.0 4 0.0 33260 1436 pts/39 Sl+ 15:17 0:00 ./puma
kvantour 1618 1619 99.8 4 0.0 33260 1436 pts/39 Rl+ 15:17 0:14 ./puma
kvantour 1618 1620 99.8 4 0.0 33260 1436 pts/39 Rl+ 15:17 0:14 ./puma
kvantour 1618 1621 99.8 4 0.0 33260 1436 pts/39 Rl+ 15:17 0:14 ./puma
...
top是否可以显示有关线程或LWP的信息?
top
有一个选项可以通过在交互模式下按下H
或使用top -H
启动来显示线程。问题是它将线程列为进程(类似于ps -fH
)。
% top
top - 09:42:10 up 17 days, 3 min, 1 user, load average: 3.35, 3.33, 2.75
Tasks: 353 total, 3 running, 347 sleeping, 3 stopped, 0 zombie
%Cpu(s): 75.5 us, 0.6 sy, 0.5 ni, 22.6 id, 0.0 wa, 0.0 hi, 0.8 si, 0.0 st
KiB Mem : 16310772 total, 8082152 free, 3662436 used, 4566184 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 11363832 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
868 kvantour 20 0 33268 1436 1308 S 299.7 0.0 46:16.22 puma
1163 root 20 0 920488 282524 258436 S 2.0 1.7 124:48.32 Xorg
...
在这里您可以看到,puma
累计运行时间为46:16.22,CPU利用率约为300%。不过,并没有指示这是一个多线程进程。唯一的指示是CPU使用率,但是如果3个线程“睡眠”,这个值可能低于100%。此外,状态标志显示S
,表示第一个线程正在休眠。按下H
键会给出更多信息。
% top -H
top - 09:48:30 up 17 days, 10 min, 1 user, load average: 3.18, 3.44, 3.02
Threads: 918 total, 5 running, 910 sleeping, 3 stopped, 0 zombie
%Cpu(s): 75.6 us, 0.2 sy, 0.1 ni, 23.9 id, 0.0 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 16310772 total, 8062296 free, 3696164 used, 4552312 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 11345440 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
870 kvantour 20 0 33268 1436 1308 R 99.9 0.0 21:45.35 puma
869 kvantour 20 0 33268 1436 1308 R 99.7 0.0 21:45.43 puma
872 kvantour 20 0 33268 1436 1308 R 99.7 0.0 21:45.31 puma
1163 root 20 0 920552 282288 258200 R 2.0 1.7 124:52.05 Xorg
...
现在我们只看到了3个线程。由于其中一个线程正在“睡眠”,因此它在按CPU使用率排序时排在最下面。
top
为了查看所有线程,最好让其显示特定的
pid
(针对单个进程):
% top -H -p $(pgrep puma)
top - 09:52:48 up 17 days, 14 min, 1 user, load average: 3.31, 3.38, 3.10
Threads: 4 total, 3 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 75.5 us, 0.1 sy, 0.2 ni, 23.6 id, 0.0 wa, 0.0 hi, 0.7 si, 0.0 st
KiB Mem : 16310772 total, 8041048 free, 3706460 used, 4563264 buff/cache
KiB Swap: 4194300 total, 4194300 free, 0 used. 11325008 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
869 kvantour 20 0 33268 1436 1308 R 99.9 0.0 26:03.37 puma
870 kvantour 20 0 33268 1436 1308 R 99.9 0.0 26:03.30 puma
872 kvantour 20 0 33268 1436 1308 R 99.9 0.0 26:03.22 puma
868 kvantour 20 0 33268 1436 1308 S 0.0 0.0 0:00.00 puma
当你有多个进程运行时,你可能会想要按下"f"键并切换"PGRP"。这将显示进程的组PID。(在ps中的PID与top中的PID是LWP)。
如何在不使用"ps"或"top"的情况下获取线程计数?
文件"/proc/$PID/status"包含一行声明进程PID为"$PID"的线程数。
% grep Threads /proc/19304/status
Threads: 4
总体评论
- 有可能您无法找到另一个用户的进程,因此无法获取该进程正在使用的线程数。这可能是由于 /proc/ 的挂载选项(hidepid=2)引起的。
使用的示例程序:
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char c = 0;
#pragma omp parallel shared(c) {
int i = 0;
if (omp_get_thread_num() == 0) {
printf("Read character from input : ");
c = getchar();
} else {
while (c == 0) i++;
printf("Total sum is on thread %d : %d\n", omp_get_thread_num(), i);
}
}
}
使用gcc -o puma --openmp
编译