linux - 内核如何将线程与进程分离

标签 linux multithreading linux-kernel

假设我有一个像 Firefox 这样的浏览器进程,它的 pid = 123。Firefox 有 5 个打开的选项卡,每个选项卡都在一个单独的线程中运行,所以它总共有 5 个线程。

  • 所以想深入了解一下,内核如何将进程分离到线程中执行struct task_struct或在 thread_info 中。
  • 点赞struct task_struct是任务列表的任务描述符。struct task_struct 在哪里?包含对这五个线程的引用或链接。
  • struct thread_struct像 Firefox 这样的进程包含对所有 5 个线程的引用



    每个线程都被视为 Linux 内核中的一个进程。
  • 最佳答案

    与 Windows 不同,Linux 在内核中没有“线程”的实现。内核为我们提供了有时称为“轻量级进程”的东西,它是“进程”和“线程”概念的概括,可用于实现其中任何一个。

    当您阅读内核代码并看到诸如 thread_struct 之类的内容时,可能会感到困惑。一方面,pid (进程 ID)另一方面。实际上,两者都是一回事。不要被术语混淆。

    每个轻量级进程都有完全不同的thread_infotask_struct (嵌入 thread_struct )。您似乎认为 task_struct一个轻量级进程的指针应该指向 task_struct同一(用户空间)“进程”中的其他(用户空间)“线程”。不是这种情况。在内核内部,每个“线程”都是一个单独的进程,调度程序分别处理每个线程。

    Linux 有一个名为 clone 的系统调用。它用于创建新的轻量级流程。当您调用 clone ,您必须提供各种标志来指示新进程和现有进程之间将共享什么。他们可以共享他们的地址空间,也可以各自拥有不同的地址空间。他们可以共享打开的文件,也可以各自拥有自己的打开文件列表。他们可以共享自己的信号处理程序,也可以各自拥有自己的信号处理程序。它们可以在同一个“线程组”中,也可以在不同的线程组中。等等...

    尽管“线程”和“进程”在 Linux 中是同一个东西,但是您可以使用 clone 来实现我们通常认为的“进程”。创建 的进程不要分享它们的地址空间、打开的文件、信号处理程序等。

    您还可以使用 clone 来实现我们通常认为的“线程”。创建 的进程分享它们的地址空间、打开的文件、信号处理程序等。

    如果您查看 task_struct 的定义,你会发现它有指向其他结构的指针,例如 mm_struct (地址空间),files_struct (打开文件),sighand_struct (信号处理程序)等等。当你clone一个新的“进程”,所有这些结构都将被复制。当你clone一个新的“线程”,这些结构将在新旧 task_struct 之间共享s——它们都指向同一个mm_struct , 相同 files_struct , 等等。无论哪种方式,您只是为 clone 提供不同的标志。告诉它要复制什么,要分享什么。

    我刚刚在上面提到了“线程组”,所以您可能对此感到疑惑。简而言之,“进程”中的每个“线程”都有自己的 PID,但它们都共享相同的 TGID(线程组 ID)。 TGID 都等于第一个程序线程的 PID。用户空间“PID”,如 ps 中所示,或在 /proc ,实际上是内核中的“TGID”。当然,clone有一个标志来确定一个新的轻量级进程是否会有一个新的 TGID(因此将它放在一个新的“线程组”中)。

    UNIX 进程也有“父”和“子”。 Linux中有指针task_struct它实现了父子关系。而且,正如您可能已经猜到的那样,clone有一个标志来确定一个新的轻量级进程的父进程将是什么。它可以是调用 clone 的进程。 , 或调用 clone 的进程的父进程.你能弄清楚创建“进程”时使用哪个,创建“线程”时使用哪个?

    查看 clone 的联机帮助页;这将是非常有教育意义的。也可以试试 strace在使用 pthread 的程序上查看 clone正在使用。

    (很多都是凭内存写的;其他人可以根据需要随时进行更正)

    关于linux - 内核如何将线程与进程分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30839834/

    相关文章:

    linux - 使用交叉编译器时缺少 libmpfr.so.6

    c - 使用内核模块中的 sysctl 接口(interface)

    c++ - libSoX 是线程安全的吗?

    python - cython.并行 : variable assignment without thread-locality

    linux - 如何使用Linux软件看门狗?

    c++ - 也许 QThread 内 QTLineEdit 的范围会导致程序崩溃?

    linux - 为什么wget引发错误403:禁止的错误?

    java - 在android中创建线程不起作用

    linux-kernel - 我可以在不创建平台设备的情况下查询设备树项吗?

    linux - 从内核模块向用户空间发送实时信号失败