【问题标题】:Can the thread ID of a multithreaded process be the same as the process ID of another running process?多线程进程的线程ID可以和另一个正在运行的进程的进程ID相同吗?
【发布时间】:2013-01-02 16:35:42
【问题描述】:

我正在尝试找到一种方法来唯一标识多进程环境中的线程。我有一个服务器来跟踪连接到它的不同进程,其中一些是多线程的,而另一些不是。为了从多线程连接中识别线程,我使用线程 ID 作为唯一标识符(在任何给定时间最多连接 1 个多线程进程)。我的问题是:这些线程之一的线程 ID 是否可能与系统上运行的另一个进程的进程 ID 相同?

提前感谢您的帮助!

【问题讨论】:

    标签: linux multithreading process linux-kernel pthreads


    【解决方案1】:

    TID(由sys_gettid() 系统调用返回)在系统上的所有线程中都是唯一的1,对于单线程进程,PID 和 TID 是相等的。这意味着 TID 永远不会与来自另一个进程的 PID 冲突。


    1。需要注意的是,如果使用 PID 命名空间,则 TID 和 PID 仅在同一 PID 命名空间内是唯一的。

    【讨论】:

    • 好的,这是很好的信息。目前我正在使用pthread_self() 函数,但这只能保证过程中的唯一性。我认为sys_gettid() 是要走的路,谢谢!
    • @mgcleveland:不过请注意,这是特定于 Linux 的。
    • 这里写的是gettid()而不是sys_gettid()linux.die.net/man/2/gettid
    • @AlexisWilke 阅读了您链接的手册页上的“注释”部分。
    • @andy:SYS_gettid(系统范围内唯一)返回的 Linux 线程 ID 与 pthread_t 类型的 POSIX 线程 ID(仅保证进程范围内唯一)。
    【解决方案2】:

    根据man page of pthreads,线程 ID 在创建进程中是唯一的,因此是的,另一个线程或进程可能具有相同的 ID。但是,如果它在进程中是唯一的,并且进程 ID 在系统中是唯一的,那么也许您可以将两者的组合用作唯一标识符。

    进程中的每个线程都有一个唯一的线程标识符 (存储在 pthread_t 类型中)。该标识符返回给 pthread_create(3) 的调用者,线程可以获取自己的线程 使用 pthread_self(3) 的标识符。 线程 ID 只能保证 在进程中是唯一的。

    【讨论】:

    • 感谢您的回答。我熟悉那个手册页条目,但是它并没有明确指定进程中的线程 ID 是否可以与系统上的进程 ID 集相交。有你提到的混合方法,但如果可能的话,我试图将值保留为一种 uint65_t 数据类型。
    • @mgcleveland 如果不能保证它是系统范围内的唯一,那么没有什么能阻止它作为 PID 被重用,这就是重点。
    • 是的,这就是我正在研究的假设。我们目前有描述的实现,但可能必须将其修改为类似于您建议的内容。感谢您的意见!
    【解决方案3】:

    虽然 pthread ID 可能不是唯一的,但在线程映射到任务的实现中,任务 ID(如 /proc/PID/task 中所示)实际上在系统范围内是唯一的,并且具有类似于实际 PID。

    【讨论】:

    • 虽然使用gettid() 可能比读取/proc/... 文件更干净。
    • @AlexisWilke gettid(2) 是内核系统调用,而不是 C 库函数或包装器。可能需要使用迂回方式来称呼它——这就是为什么它经常用另一个名称来说明这一点。几年前我写这个答案时,我指的是 /proc 中提到的 id 以消除它与非常不同的不透明标识符(即 pthread id)之间的 confusion ,而不是真正提出如何 在代码中获取它。
    • 在这种情况下,您可以读取/proc/self 软链接(请参阅readlink(2)),因为该标识符是任务标识符(与gettid() 返回的相同。)
    • 不,这是不正确的。手册页指定 /proc/self 对应于 process 并且仅匹配 first 线程的 ID。但是在 Linux 3.17 之后存在 /proc/thread-self。
    【解决方案4】:

    好吧,我刚才遇到了同样的问题,这是我的验证程序。

    #include <pthread.h>
    #include <stdio.h>
    
    int main() {
        printf("%lu\n", pthread_self());
    }
    

    clang -pthread test.c && strace ./a.out
    

    部分输出如下。

    ...
    arch_prctl(ARCH_SET_FS, 0x7f53259be740) = 0
    ...
    write(1, "139995089987392\n", 16139995089987392
    )       = 16
    ...
    

    那么我们知道 0x7f53259be740 等于 139995089987392 并且arch_prctl 的第二个参数应该在进程地址空间内(man arch_prctl) .也就是说,线程ID实际上是一个虚拟地址。所以如果你在多进程环境中使用pthread_self()来识别线程,虽然几率很小,但可能会发生冲突。

    【讨论】:

    • 根据文档,pthread_self() 标识符在一个进程中是唯一的,但在不同进程的线程之间可能不是唯一的。
    【解决方案5】:
    pthread_equal(id1,id2)
    

    它将比较两个线程的ID,如果它们相同则返回0,如果它们不同则返回非零数。

    【讨论】:

    • 根据文档,pthread_self() 标识符在一个进程中是唯一的,但在不同进程的线程之间可能不是唯一的。
    猜你喜欢
    • 2011-12-05
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多