min*_*ino 27 concurrency multithreading operating-system
所以这里有两个问题.首先,(是的,我已经对此进行了搜索,但需要澄清),用户线程和内核线程之间有什么区别?简单地说,一个是由用户程序生成的,另一个是由操作系统生成的,后者可以访问特权指令吗?它们在概念上是相同的还是线程本身存在实际差异?
其次,我的问题的真正问题是:我正在使用的书中说"用户线程与内核线程之间必须存在关系",继续列出这种关系的不同模型.但该书未能清楚地解释为什么必须始终将用户线程映射到特定的内核线程.为什么是这样?
tem*_*def 30
甲内核线程是由操作系统维护的线程对象.它是一个能够由处理器调度和执行的实际线程.通常,系统线程是具有权限设置,优先级等的重量级对象.内核线程调度程序负责调度内核线程.
用户程序也可以制作自己的线程调度程序.他们可以创建自己的"线程"并模拟上下文切换以在它们之间切换.但是,这些线程不是内核线程.每个用户线程实际上不能单独运行,并且用户线程运行的唯一方法是实际上告诉内核线程执行用户线程中包含的代码.也就是说,用户线程比内核线程具有更大的优势.它们可以更轻量级,因为它们不一定需要有自己的优先级,可以由单个进程管理(可能有更好的信息,关于什么线程需要运行时),并且不会创建大量的用于安全性和锁定的内核对象.
用户线程必须与内核线程相关联的原因是用户线程本身只是用户程序中的一堆数据.内核线程是系统中的真正线程,因此对于用户线程来说,用户程序必须让其调度程序获取用户线程,然后在内核线程上运行它.用户线程和内核线程之间的映射不必是一对一的(1:1); 您可以让多个用户线程共享同一个内核线程(一次只运行其中一个用户线程),并且您可以拥有一个用户线程,该线程在1:n映射中跨不同内核线程进行轮换.
我认为一个真实世界的例子会消除混淆,所以让我们看看在 Linux 中是如何完成的。
首先Linux不区分进程和线程,可以调度的实体在Linux中称为任务,用task_struct. 因此,每当您执行fork()系统调用时,task_struct都会创建一个 new来保存与新任务关联的数据(或指针)。
task_struct对象。因为调度程序只知道这些可以分配给不同 CPU(逻辑或物理)的实体。换句话说,如果您希望 Linux 调度程序调度您的进程,您必须创建一个task_struct.
用户线程是在内核之外由某些执行环境(从现在开始是 EE)例如 JVM支持和管理的东西。这些 EE 将为您提供一些创建新线程的功能。
假设您使用 EE 创建了一些线程。最终它们必须由 CPU 执行,从上面的解释我们知道线程必须有一个task_struct才能分配给某个 CPU。这就是映射必须存在的原因。您的 EE 有责任创建task_structs.
如果您的 EE 使用多对一模型,那么它只会task_struct为所有线程创建一个模型,并将所有这些线程调度到该模型上task_struct。把它想象成有一个 CPU ( task_struct) 和许多进程(在 EE 中创建的线程),您的操作系统 (EE) 将在单个 CPU 上多路复用这些进程。
如果它使用一对一的模型,那么task_struct在 EE 中创建的每个线程都会有一个。因此,当您在 EE 中创建新线程时,task_struct会在内核中创建相应的线程。
Windows 做不同的事情(进程和线程是不同的)但总体思路保持不变,即内核线程是 CPU 调度程序考虑分配的实体,因此用户线程必须映射到相应的内核线程(如果您希望 CPU 执行它们)。
| 归档时间: |
|
| 查看次数: |
5029 次 |
| 最近记录: |