用户级线程的好处

时间:2016-01-02 18:38:17

标签: multithreading operating-system multitasking

我正在研究用户级线程和内核级线程之间的差异,我基本上理解这一点 我不清楚的是完全实现用户级线程的重点。

如果内核不知道单个进程中存在多个线程,那么我可以体验到哪些好处? 我已经阅读了几篇文章,声明只有当这样的线程不执行阻塞操作(这会导致整个进程被阻塞)时,建议用户级别的线程实现。

这就是说,所有线程的顺序执行和它们的“并行”执行之间的区别是什么,考虑到它们无法利用多个处理器和独立调度?

回答之前提出的问题(类似于我的问题)就像是:

  

现代操作系统实际上没有将n个用户级线程映射到1   内核级线程。

但由于某些原因,互联网上的许多人都声称用户级线程可以从不利用多个处理器。

你能帮我理解这个吗?

2 个答案:

答案 0 :(得分:11)

我强烈推荐Modern Operating Systems 4th Edition Andrew S. Tanenbaum(主演debate about Linux等节目;同时参演:Linus Torvalds)。耗费了大量的钱,但如果你真的想知道的话,它绝对值得。对于渴望学生和绝望的爱好者来说,这很棒。

您的问题已解答

  

[...]我不清楚的是实现用户级线程的重点   一点都不。

阅读我的帖子。我敢说这是全面的。

  

如果内核不知道a中存在多个线程   单一过程,那么我可以体验哪些好处?

阅读"缺点"下方。

  

我已经阅读了一些声明用户级别的文章   只有当这样的线程不这样做时,才建议实现线程   执行阻塞操作(这将导致整个过程   块)。

阅读小节"不与系统调用协调"在"缺点。"

所有引用都来自我在本答案的顶部,第2.2.4章,以及#34;在用户空间中实现线程所推荐的那本书。"

优点

在没有线程的系统上启用线程

第一个优点是用户级线程是一种在没有线程的情况下使用系统上的线程的方法。

  

第一个也是最明显的优势是   用户级线程包可以在不支持线程的操作系统上实现。所有操作系统都习惯了   属于这一类,即使现在有些人仍然这样做。

无需内核交互

另一个好处是切换线程时的开销很小,而不是切换到内核模式,做东西,切换回来等。较轻的线程切换在书中描述如下:

  

当线程执行某些可能导致其被阻止的事情时   本地,例如,等待其进程中的另一个线程   完成一些工作,它调用运行时系统程序。这个   过程检查线程是否必须进入阻塞状态。   如果,那么它存储线程的寄存器(即它自己的)[...]和   使用新线程的已保存值重新加载机器寄存器。一旦堆叠   指针和程序计数器已​​经切换,新线程来了   再次自动生活。如果机器碰巧有   用于存储所有寄存器的指令和用于加载它们的另一个寄存器   所有,整个线程切换可以在少数几个完成 -   structions。 像这样进行线程切换至少是一个顺序   幅度 - 可能比捕获到内核更快 - 并且是一个   支持用户级线程包的强烈论据。

这种效率也很好,因为它使我们免受令人难以置信的沉重的上下文切换和所有这些问题。

单独调整的调度算法

此外,由于没有中央调度算法,每个过程都可以有自己的调度算法,并且在各种选择方面更灵活。此外,"私人"调度算法对于从线程获取的信息更加灵活。 可以手动和按流程调整信息的数量,因此它非常精细。这是因为,再次,没有中央调度算法需要满足每个人的需求处理;它必须非常通用,并且必须在每种情况下都能提供足够的性能。用户级线程允许非常专业的调度算法 这只受到缺点的限制"没有自动切换到调度程序。"

  

他们[用户级线程]允许每个进程拥有自己的进程   自定义调度算法。对于某些应用程序,例如,   那些有垃圾收集器线程的人,不必担心   线程在不方便的时刻停止是一个加号。他们也   更好地扩展,因为内核线程总是需要一些表空间   并且在内核中堆栈空间,如果有的话,这可能是个问题   非常多的线程。

缺点

与系统调用无协调

用户级调度算法不知道某个线程是否已调用阻塞read系统调用。 OTOH是一种内核级调度算法,因为可以通过系统调用通知它;两者都属于内核代码库。

  

假设线程在任何键之前从键盘读取   被击中了。 让线程实际进行系统调用   不可接受,因为这将阻止所有线程。其中一个主要   首先拥有线程的目标是允许每个人   使用阻塞调用,但防止一个阻塞的线程影响   其他。 阻止系统调用,很难看出这是怎么回事   目标很容易实现。

他继续说系统调用可能是非阻塞的,但这样会非常不方便,并且对现有操作系统的兼容性会受到严重损害。
Tanenbaum先生还说,可以修改系统调用周围的库包装(例如,在glibc中找到),以预测系统校准何时使用select进行阻止,但他说这是不优雅的。

在此基础上,他说线程经常会阻塞。通常阻塞需要许多系统调用。许多系统调用错误。并且没有阻塞,线程变得不那么有用了:

  

对于基本上完全受CPU限制的应用程序很少   块,有线程的重点是什么?没人会   认真提议计算第一个n素数或下棋   使用线程,因为这样做没有任何好处   方式。

如果不知道线程

,页面错误会阻塞每个进程

操作系统没有线程概念。因此,如果发生页面错误,整个过程将被阻止,从而有效地阻止所有用户级线程。

  

类似于阻止系统调用的问题是   页面错误的问题。 [...]如果程序调用或跳转到   不在内存中的指令,发生页面错误和   操作系统将去获取缺失的指令(和它的   邻居)来自磁盘。 [...]在必要时阻止该过程   正在定位和读入指令。如果线程导致页面   错误,内核,自然也没有意识到线程的存在   尽管如此,阻止整个过程直到磁盘I / O完成   其他线程可能是可以运行的。

我认为这可以推广到所有中断。

无法自动切换到调度程序

由于没有每进程时钟中断,因此线程将永远获取CPU,除非发生某些依赖于操作系统的机制(例如上下文切换)或者它自愿释放CPU。
这可以防止通常的调度算法工作,包括Round-Robin algorithm

  

[...] 如果一个线程开始运行,那个进程中没有其他线程   除非第一个线程自愿放弃CPU,否则它将会运行。   在一个过程中,没有时钟中断   不可能按周期方式安排流程(轮流)。   除非线程以自己的意愿进入运行时系统,否则调度程序永远不会有机会。

他说可能的解决方案是

  

[...]让运行时系统一次请求一个时钟信号(中断)   第二,让它控制,但这也是粗糙和凌乱的   程序

我甚至会继续说下这样一个"请求"需要进行一些系统调用,其缺点已在"没有与系统调用协调中解释。"如果没有系统调用,那么程序将需要免费访问计时器,这是一个安全漏洞,在现代操作系统中是不可接受的。

答案 1 :(得分:2)

  

我不清楚的是完全实现用户级线程的重点。

由于Ada及其对线程的要求(Ada术语中的任务),用户级线程主要成为主流。当时,几乎没有多处理器系统,大多数多处理器属于主/从类。内核线程根本不存在。必须创建用户线程来实现Ada等语言。

  

如果内核不知道单个进程中存在多个线程,那么我可以体验哪些好处?

如果您有内核线程,则单个进程中的多个线程可以同时运行。在用户线程中,线程始终执行交错。

使用线程可以简化某些类型的编程。

  

我已经阅读了一些文章,声明只有当这样的线程不执行阻塞操作(这会导致整个进程被阻塞)时,建议用户级别的线程实现。

在Unix上也是如此,也许并非所有unix实现都是如此。许多操作系统上的用户线程在阻塞I / O时运行良好。

  

这就是说,顺序执行所有线程和" parallel"之间的区别是什么?执行它们,考虑到它们无法利用多处理器和独立调度?

在用户线程中。从来没有并行执行。在内核线程中,如果有多个处理器,则可以并行执行。在单处理器系统上,在单线程上使用内核线程没有太大的优势(反之:注意Unix和用户线程上的阻塞I / O问题)。

  

但由于某种原因,互联网上的许多人都声称用户级线程永远不会利用多个处理器。

在用户线程中,进程管理自己的"线程"通过在自身内交错执行。该进程只能在运行该进程的处理器中运行一个线程。

如果操作系统提供系统服务来安排代码在不同的处理器上运行,则用户线程可以在多个处理器上运行。

我最后说,出于可行的目的,用户线程对内核线程没有任何好处。有些人会声称存在性能优势,但是由于存在这样的优势,它将取决于系统。