Linux 内核线程真的是内核进程吗?

Linux 内核线程真的是内核进程吗?

我在很多地方读到 Linux 为 Java VM 中的每个用户线程创建一个内核线程。 (我看到术语“内核线程”有两种不同的使用方式:

  1. 为执行核心操作系统工作而创建的线程以及
  2. 操作系统识别并安排执行用户工作的线程。

我说的是后一种类型。)

由于 Linux 进程支持父进程和子进程之间的共享内存空间,内核线程与内核进程是否相同,或者它确实是不同的实体?

答案1

文档可能非常混乱,所以这里是“真实的“Linux 型号:

  • 在 Linux 内核中,可以运行(和调度)的东西称为“进程”,
  • 每个进程都有一个系统唯一的进程ID(PID)和一个线程组ID(TGID),
  • “正常”进程的 PID=TGID 并且没有其他进程共享此 TGID 值,
  • “线程”进程是指其 TGID 值与其他进程共享的进程,
  • 共享相同 TGID 的多个进程至少也共享相同的内存空间和信号处理程序(有时更多),
  • 如果“线程”进程的 PID=TGID,则可以称为“主线程”,
  • 从任何进程调用getpid()都会返回其 TGID(=“主线程”PID),
  • 从任何进程调用gettid()都会返回其 PID (!),
  • 任何类型的进程都可以通过系统调用创建clone(2)
  • 进程之间共享的内容是通过将特定标志传递给来决定的clone(2)
  • 您可以列出文件夹的数字名称,ls /proc就像/proc/NUMBERTGID 一样,
  • 文件夹的数字名称与/proc/TGID/taskPID/proc/TGID/task/NUMBER一样,
  • 即使您没有看到每个现有的 PID 都带有ls /proc,您仍然可以这样做cd /proc/any_PID

结论:从内核的角度来看,只有进程存在,每个进程都有自己唯一的PID,所谓的线程只是一种不同类型的进程(至少与一个或多个其他进程共享相同的内存空间和信号处理程序) ·s)。

笔记:Linux 中“线程”概念的实现导致了词汇混乱,如果getpid() 它没有按照你的想法做,那是因为它的行为遵循 POSIX 兼容性(线程应该共享一个公共 PID)。

答案2

Linux 上的线程和进程完全没有区别。如果你看克隆(2)您将看到一组标志,用于确定线程之间共享的内容和不共享的内容。

经典进程只是不共享任何内容的线程;你可以在Linux下分享你想要的组件。

其他操作系统实现的情况并非如此,它们存在更实质性的差异。

答案3

线程是Linux下的进程。它们是通过clone系统调用创建的,系统调用返回一个进程 ID,可以通过kill系统调用向该 ID 发送信号,就像进程一样。线程进程在ps输出中可见。该clone调用会传递一些标志,这些标志确定父进程的环境有多少与线程进程共享。

答案4

前面的答案非常好,指出线程是 Linux 内核内部的进程,并且您无论如何都可以克隆()您喜欢的进程状态的任何子集。

但我认为记住这一点是有帮助的:有多少上下文可以共享或必须唯一保存,以及上下文切换可能需要多少个周期,这可能取决于可能有​​多少不同,而不仅仅是不同程度就操作系统而言,还涉及硬件,例如TLB。因此,克隆什么和共享什么很重要。

在应用层面,一个新线程(按照传统的理解,共享内存映像、当前目录、打开的文件句柄等)总是比一个最多只在最初共享这些的新进程便宜。即使进程是通过写时复制来分叉的,一旦写入,您就必须进行复制。这就是为什么在设计应用程序时,创建 10,000 个线程比创建 10,000 个进程更合理。出于安全原因执行新进程的原因是运行不同的可执行文件或防火墙。

相关内容