Cai*_*tri 61 theory multithreading operating-system process
我一直在查看基于这个主题的一些注释,虽然我对一般的线程有所了解,但我并不确定用户级和内核级线程之间的差异.
我知道进程基本上由多个线程或单个线程组成,但是这两个先前提到的类型的线程是什么?
据我所知,内核支持的线程可以访问内核以进行系统调用和用户级线程无法使用的其他用途.
那么,用户级线程是否只是程序员创建的线程,然后利用内核支持的线程执行由于其状态而无法正常执行的操作?
Bra*_*ncy 80
编辑:问题有点混乱,所以我用两种不同的方式回答它.
为清楚起见,我通常说"操作系统级线程"或"本机线程"而不是"内核级线程"(我在下面的原始答案中将其与"内核线程"混淆.)操作系统级线程由以下内容创建和管理:操作系统.大多数语言都支持它们.(C,最近的Java等)它们非常难以使用,因为您100%负责预防问题.在某些语言中,即使是原生数据结构(例如Hashes或Dictionaries)也会在没有额外锁定代码的情况下中断.
与OS线程相反的是由您的语言管理的绿色线程.这些线程根据语言(C中的协同程序,Go中的goroutines,Ruby中的光纤等)给出了各种名称.这些线程只存在于您的语言中,而不存在于您的操作系统中 因为语言选择了上下文切换(即在语句的末尾),所以它会阻止TONS的微妙竞争条件(例如看到部分复制的结构,或者需要锁定大多数数据结构).程序员看到"阻塞"调用(即data = file.read()),但语言将其转换为对操作系统的异步调用.然后,该语言允许其他绿色线程在等待结果时运行.
对于程序员来说,绿色线程更简单,但它们的性能各不相同:如果你有很多线程,绿色线程可以更好地用于CPU和RAM.另一方面,大多数绿色线程语言无法利用多个核心.(你甚至不能再购买单核电脑或手机了!).一个坏的库可以通过阻止OS调用来暂停整个语言.
两个世界中最好的是每个CPU有一个OS线程,并且许多绿色线程神奇地移动到OS线程上.像Go和Erlang这样的语言可以做到这一点.
系统调用和用户级线程无法使用的其他用途
这只是一半.是的,如果你自己调用操作系统(即做一些阻塞的操作),你很容易引起问题.但是语言通常有替换,所以你甚至都没注意到.这些替换确实调用了内核,与您的想法略有不同.
编辑:这是我的原始答案,但它是关于用户空间线程与仅内核线程,(事后看来)可能不是问题.
用户线程和内核线程完全相同.(您可以通过查看/ proc /看到内核线程也在那里.)
用户线程是执行用户空间代码的线程.但它可以随时调用内核空间.它仍然被认为是一个"用户"线程,即使它正在以更高的安全级别执行内核代码.
内核线程是仅运行内核代码并且与用户空间进程无关的线程.这些就像"UNIX守护进程",除了它们是仅内核的守护进程.所以你可以说内核是一个多线程程序.例如,有一个用于交换的内核线程.这会强制所有交换问题"序列化"为单个流.
如果用户线程需要某些东西,它将调用内核,这会将该线程标记为休眠.之后,交换线程找到数据,因此它将用户线程标记为可运行.后来,"用户线程"从内核返回到用户空间,好像什么都没发生一样.
实际上,所有线程都是从内核空间开始的,因为clone()操作发生在内核空间中.(在你可以'返回'到用户空间的新进程之前,还有很多内核会计要做.)
Yus*_*san 17
在我们进行比较之前,让我们先了解一下线程是什么.线程是独立进程域内的轻量级进程.它们是必需的,因为流程繁重,消耗大量资源,更重要的是,
两个独立的进程无法共享内存空间.
假设你打开一个文本编辑器.它是一个独立的进程,在内存中执行,具有单独的可寻址位置.在此过程中您将需要许多资源,例如插入图形,拼写检查等.为每个功能创建单独的进程并在内存中独立维护它们是不可行的.要避免这种情况,
可以在单个进程中创建多个线程,这可以共享在进程内独立存在的公共内存空间.
现在,回到你的问题,一次一个.
我不确定用户级和内核级线程之间的区别.
线程基于其执行域大致分为用户级线程和内核级线程.还有 一种或多种用户线程映射到一个或多个内核线程的情况.
- 用户级线程
用户级线程主要位于应用程序级别,应用程序创建这些线程以维持其在主内存中的执行.除非需要,否则这些线程与内核线程隔离.
这些更容易创建,因为它们不必引用许多寄存器,并且上下文切换比内核级线程快得多.
用户级线程,主要是在应用程序级别引起更改,内核级别线程继续按自己的进度执行.
- 内核级线程
这些线程大多独立于正在进行的进程,并由操作系统执行.
操作系统需要这些线程来执行内存管理,进程管理等任务.
由于这些线程维护,执行和报告操作系统所需的进程; 内核级线程的创建和管理成本更高,这些线程的上下文切换速度很慢.
大多数内核级线程不能被用户级线程抢占.
MS DOS written for Intel 8088 didn't have dual mode of operation. Thus, a user level process had the ability to corrupt the entire operating system.
Run Code Online (Sandbox Code Playgroud)
- 通过内核线程映射的用户级线程
这可能是最有趣的部分.许多用户级线程映射到内核级线程,后者又与内核进行通信.
一些突出的映射是:
一对一
当一个用户级线程仅映射到一个内核线程时.
优点:每个用户线程映射到一个内核线程.即使其中一个用户线程发出阻塞系统调用,其他进程也不会受到影响.
缺点:每个用户线程都需要一个内核线程进行交互,而内核线程的创建和管理成本很高.
多对一
当许多用户线程映射到一个内核线程时.
优点:不需要多个内核线程,因为类似的用户线程可以映射到一个内核线程.
缺点:即使其中一个用户线程发出阻塞系统调用,也会阻止映射到该内核线程的所有其他用户线程.
此外,由于内核一次只处理一个内核线程,因此无法实现良好的并发性.
多对多
当许多用户线程映射到相同或更少数量的内核线程时.程序员决定有多少用户线程将映射到多少内核线程.某些用户线程可能只映射到一个内核线程.
优点:实现了很高的并发性.程序员可以决定一些可能发出阻塞系统调用的潜在危险线程,并将它们与一对一映射放在一起.
缺点:内核线程的数量,如果不谨慎决定可以减慢系统速度.
问题的另一部分:
内核支持的线程可以访问内核以进行系统调用和用户级线程无法使用的其他用途.
那么,用户级线程是否只是程序员创建的线程,然后利用内核支持的线程执行由于其状态而无法正常执行的操作?
部分正确.由于内核线程负责执行OS的进程,因此几乎所有内核线程都可以访问系统调用和其他关键中断.用户线程无法访问其中一些关键功能.例如,文本编辑器永远不能拍摄能够改变过程物理地址的线程.但是如果需要,用户线程可以映射到内核线程并发出一些它不能作为独立实体执行的系统调用.然后,内核线程将此系统调用映射到内核,并在认为合适时执行操作.