假设我有一个像Firefox这样的浏览器进程,它的pid = 123。Firefox有5个打开的选项卡,每个选项卡运行在一个单独的线程中,因此总共有5个线程。
struct task_struct或thread_info中执行。struct task_struct类似,它是任务列表的任务描述符。struct task_struct在哪里包含对这五个线程的引用或链接。struct thread_struct是否包含对所有5个线程的引用?
或
每个线程都被视为Linux内核中的一个进程。发布于 2015-06-18 07:02:52
与Windows不同,Linux在内核中没有“线程”的实现。内核为我们提供了有时被称为“轻量级进程”的东西,它是“进程”和“线程”概念的概括,可以用来实现任何一个。
当您一方面阅读内核代码并看到诸如thread_struct和pid (进程ID)之类的东西时,可能会感到困惑。在现实中,两者是一体的和相同的。不要被术语弄糊涂了。
每个轻量级流程都有一个完全不同的thread_info和task_struct (带有嵌入式thread_struct)。您似乎认为,一个轻量级进程的task_struct应该具有指向相同(用户空间)“进程”中其他(用户空间)“线程”的task_struct的指针。事实并非如此。在内核中,每个“线程”是一个单独的进程,调度器分别处理每个进程。
Linux有一个名为clone的系统调用,用于创建新的轻量级进程。当您调用clone时,您必须提供各种标志,这些标志指示新进程和现有进程之间将共享什么。他们可以共享他们的地址空间,或者他们可以有不同的地址空间。他们可以共享他们打开的文件,也可以每个人都有自己的打开文件列表。它们可以共享它们的信号处理程序,也可以每个人都有自己的信号处理程序。它们可以在同一个“线程组”中,也可以在不同的线程组中。等等..。
尽管“线程”和“进程”在Linux中是相同的,但是您可以通过使用clone创建不共享的进程--它们的地址空间、打开的文件、信号处理程序等等--来实现我们通常认为的“进程”。
您还可以通过使用clone创建确实共享地址空间、打开文件、信号处理程序等的进程来实现我们通常认为的“线程”。
如果查看task_struct的定义,您会发现它有指向其他结构的指针,如mm_struct (地址空间)、files_struct (打开文件)、sighand_struct (信号处理程序)等等。当您clone一个新的“进程”时,所有这些结构都将被复制。当您clone一个新的“线程”时,这些结构将在新的和旧的task_structs之间共享--它们都指向相同的mm_struct、相同的files_struct等等。无论哪种方式,您只是向clone提供不同的标志来告诉它要复制什么和共享什么。
我刚才提到了上面的“线程组”,所以您可能会对此感到好奇。简而言之,“进程”中的每个“线程”都有自己的PID,但它们都共享相同的TGID (线程组ID)。TGID都等于第一个程序线程的PID。与ps或/proc中显示的in一样,Userspace“PID”实际上是内核中的“TGID”。当然,clone有一个标志来确定一个新的轻量级进程是否会有一个新的TGID (从而将它放入一个新的“线程组”中)。
UNIX进程也有“父进程”和“子进程”。Linux task_struct中有实现父-子关系的指针。而且,正如您可能已经猜到的,clone有一个标志来确定新轻量级过程的父进程是什么。它可以是调用clone的进程,也可以是调用clone的进程的父进程。您能确定在创建“进程”时使用哪一个,在创建“线程”时使用哪个?
请看clone的手册,它将非常有教育意义。另外,在一个程序上尝试使用strace来查看正在使用的clone。
(其中很多都是从记忆中写出来的,其他人应该可以随时在必要时进行修改)
https://stackoverflow.com/questions/30839834
复制相似问题