Linux: 在运行时检测一个进程是否有多个线程

7
我想询问最近的glibc的linux系统。
有没有一种方法可以检测进程是由一个线程还是多个线程组成的?
线程可以通过pthread或裸clone()创建,因此我需要一些通用的方法。
更新:我想从当前进程本身检测线程。

在你自己的程序内部还是外部? - Duck
我必须问一下:为什么你不已经知道呢?是一个库或类在幕后打开它们吗? - Duck
1
鸭子,这段代码将被放置在.so库中,可以链接到各种程序中,包括基于pthread或clone的线程。 - osgx
4
如果你的库依赖于了解这个,那它就不够健壮。现在可能只有一个线程,但很快会启动另一个线程。你打算多久检查一次? - MarkR
5个回答

12

检查目录/proc/YOUR_PID/task/是否只包含一个子目录。如果该进程中有多个线程,则会有多个子目录。

硬链接计数可用于计算子目录数。此函数返回当前线程数:

#include <sys/stat.h>

int n_threads(void)
{
    struct stat task_stat;

    if (stat("/proc/self/task", &task_stat))
        return -1;

    return task_stat.st_nlink - 2;
}

1
@osgx:你可以使用一个系统调用来完成它 - 只需 stat("/proc/self/task") 并检查是否 st_nlink > 3 - caf
caf,谢谢,但是procfs是否维护目录的inode链接计数?你有检查过这个方法吗? - osgx
@osgx: 指的是stat()在第二个线程开始之前或者第二个线程结束之后发生的竞争问题。 - caf
@caf,stat是在线程本身中完成的。在两个线程中,在_create之后。 stat CLI实用程序显示相同的内容(从第二个线程printf并等待一段时间 - 多个stat运行显示nlink = 3;然后执行ls / proc / pid / task,所有统计数据都将显示nlink = 4)。有趣的是,在第二个线程退出(和pthread_join)之后 - 如果我在2个线程运行时使用ls,则程序中的stat(2)仍然显示nlink = 4。 - osgx
@osgx:内核版本是多少?可能在某个时候内核行为发生了变化。 - caf
显示剩余4条评论

0

我想你可以运行'ps'命令(通过popen()或类似方式),并解析其输出,看看你的进程ID(由getpid()返回)在输出中出现了多少次。可能有更好的方法,但这是我首先想到的。


不要使用任何子进程启动:)。这样太慢了,我需要一种快速的方式,比如1个系统调用或某些标志读取等。 - osgx

0

/proc是在Linux中执行此操作的标准方式。像'ps'这样的工具是通过/proc工作的。在Linux 2.6中,您可以在/ proc / self / stat中找到线程数,但这不向后兼容。


0

Victor的回答肯定是最快的,但您可能要考虑改用ps库。

在Ubuntu下的名称是libprocps3-dev,因此您可以使用以下命令进行安装:

sudo apt-get install libprocps3-dev

头文件位于/usr/include/proc下。

请注意,该库通过读取/proc工作。因此,它与直接读取感兴趣的文件相同,只是它会在幕后了解各个版本之间的差异并为您处理。

有关详细信息,请参见http://procps.sourceforge.net/index.html


procps需要进行多少次系统调用才能回答“进程由1个线程组成还是多个线程组成”的问题? - osgx
1
在主要的回答中,我看到很多人问到兼容性问题。procps肯定比较慢,但在新版本和旧版本的Linux上应该可以透明地运行。这取决于你是需要速度还是长期的兼容性。 - Alexis Wilke

0
一个有点不同的方式,还没有被提到过,但绝对是最无麻烦的:
int ret = unshare(CLONE_THREAD); // CLONE_SIGHAND and/or CLONE_VM also works
if (ret && errno == EINVAL) {
    // we are multi-threaded
}

对于单线程程序,这是一个无操作(no-op)。这不允许您查看创建的线程数量,但这并不是被要求的。

来源:unshare man page

此外,如果调用者是单线程的(即它没有与另一个进程或线程共享其地址空间),则可以在标志中指定 CLONE_THREAD、CLONE_SIGHAND 和 CLONE_VM。在这种情况下,这些标志没有任何效果。[...] 如果进程是多线程的,则使用这些标志会导致错误。

编辑:根据您的评论,似乎这可能是您要寻找的内容。这是一个单一的系统调用,不会启动任何其他进程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接