如果线程共享相同的PID,则如何识别它们?


97

我有一个与Linux中线程实现有关的查询。

Linux没有显式线程支持。在用户空间中,我们可能使用线程库(例如NPTL)来创建线程。现在,如果我们使用NPTL,则它支持1:1映射。

内核将使用该clone()函数来实现线程。

假设我创建了4个线程。那么就意味着:

  • 将有4个task_struct
  • 在内部task_struct,将根据克隆参数提供共享资源(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)

现在,我有以下查询:

  1. 4个线程的PID是否相同?如果有人可以详细说明,则如何共享PID。
  2. 如何识别不同的线程;有一些TID(线程ID)概念吗?

Answers:


272

这四个线程将具有相同的PID,但仅当从上方查看时才如此。什么,你(作为一个用户)调用PID是不是有什么内核(从下面看)调用PID。

内核中,每个线程都有自己的ID,称为PID(尽管将其称为TID或线程ID可能更有意义),并且它们还具有TGID(线程组ID),它是线程的PID这开始了整个过程。

简而言之,当创建一个新进程时,它将显示为一个线程,其中PID和TGID都是相同(新)编号。

当一个线程启动另一个线程时,该启动的线程将获得其自己的PID(因此调度程序可以独立调度它),但是它从原始线程继承了TGID。

这样,内核可以愉快地调度线程,而与线程所属的进程无关,而将进程(线程组ID)报告给您。

以下线程层次结构可能会有所帮助(a)

                      USER VIEW
 <-- PID 43 --> <----------------- PID 42 ----------------->
                     +---------+
                     | process |
                    _| pid=42  |_
                  _/ | tgid=42 | \_ (new thread) _
       _ (fork) _/   +---------+                  \
      /                                        +---------+
+---------+                                    | process |
| process |                                    | pid=44  |
| pid=43  |                                    | tgid=42 |
| tgid=43 |                                    +---------+
+---------+
 <-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
                     KERNEL VIEW

您可以看到,启动一个新进程(左侧)会为您提供一个新的PID 一个新的TGID(两者都设置为相同的值),而启动一个新线程(右侧)会为您提供一个新的PID,同时保持相同的值TGID作为启动它的线程。


(a) 惊叹于我令人印象深刻的图形技巧:-)


20
仅供参考,getpid()返回tgid:,asmlinkage long sys_getpid(void) { return current->tgid;}www.makelinux.com/中
Duke

6
@Duke-哇,这就是为什么我找不到gettgid(2)函数。并且getpid()不会返回TID(线程的“ PID”),并且有输入的地方gettid(2)。通过这种方式,我可以知道是否在主线程中。
Tomasz Gandor 2014年

2
这引出了另一个有趣的观点:因此,如果线程和进程在内核中(除tgid之外)均等地进行处理,那么只要多线程进程具有相同的线程,则多线程进程最终将比单线程进程获得更多的CPU时间。优先级,并且不会由于任何原因(例如等待互斥体)而暂停任何线程。
阿空加瓜

1
@ Aconcagua,CFS(Linux中完全公平的调度程序)通常以这种方式工作,但也允许使用组调度程序扩展来使公平性在某些任务组而不是单个任务之间运行。除了粗略地看了一眼,我从来没有真正研究过它。
paxdiablo

“”的getpgrp'获得组ID
彭城

2

使用PID和TGID(线程组ID)标识线程。他们还知道哪个线程是父进程的父进程,因此从本质上来说,进程与它启动的任何线程共享其PID。线程ID通常由线程库本身管理(例如pthread等)。如果启动了4个线程,则它们应具有相同的PID。内核本身将处理线程调度等,但是该库将用于管理线程(它们是否可以运行,取决于您对线程连接和等待方法的使用)。

注意:这来自我对内核2.6.36的回忆。我在当前内核版本中的工作在I / O层中,因此我不知道从那以后是否已更改。


-6

Linux为fork()系统调用提供了复制进程的传统功能。Linux还提供了使用clone()系统调用创建线程的功能。但是,Linux不能区分进程和线程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.