我有一个与Linux中线程实现相关的查询。
Linux没有明确的线程支持。在用户空间中,我们可能使用线程库(如NPTL)来创建线程。现在,如果我们使用NPTL,它支持1:1映射。
内核将使用clone()
函数来实现线程。
假设我创建了4个线程。那就意味着:
task_struct
。 task_struct
内,将根据克隆(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
的参数提供共享资源。现在我有以下查询:
答案 0 :(得分:232)
四个线程将具有相同的PID但仅在从上方查看时。 你(作为用户)调用PID不是内核(从中查看)下面)调用PID。
在内核中,每个线程都有自己的ID,称为PID(尽管将它称为TID或线程ID可能更有意义)并且它们也有一个TGID(线程) group 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) 以令人印象深刻的图形技能敬畏: - )
答案 1 :(得分:2)
使用PID和TGID(线程组ID)标识线程。他们还知道哪个线程是谁的父级,所以基本上一个进程与它启动的任何线程共享其PID。线程ID通常由线程库本身管理(例如pthread等)。如果4个线程启动,它们应具有相同的PID。内核本身将处理线程调度,但是这个库将是管理线程的(无论它们是否可以运行,取决于你使用线程连接和等待方法)。
注意:这是我对内核2.6.36的回忆。我在当前内核版本中的工作是在I / O层中,所以我不知道从那时起它是否已经发生了变化。
答案 2 :(得分:-5)
Linux为fork()
系统调用提供了复制进程的传统功能。 Linux还提供了使用clone()
系统调用创建线程的能力。但是,linux不区分进程和线程。