multithreading 用户级线程和内核支持的线程之间的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15983872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between user-level and kernel-supported threads?
提问by Cail Demetri
I've been looking through a few notes based on this topic, and although I have an understanding of threads in general, I'm not really to sure about the differences between user-level and kernel-level threads.
我一直在查看基于此主题的一些注释,虽然我对线程有一般的了解,但我并不确定用户级线程和内核级线程之间的区别。
I know that processes are basically made up of multiple threads or a single thread, but are these thread of the two prior mentioned types?
我知道进程基本上由多个线程或单个线程组成,但是这些线程是前面提到的两种类型吗?
From what I understand, kernel-supported threads have access to the kernel for system calls and other uses not available to user-level threads.
据我所知,内核支持的线程可以访问内核以进行系统调用和用户级线程无法使用的其他用途。
So, are user-level threads simply threads created by the programmer when then utilise kernel-supported threads to perform operations that couldn't be normally performed due to its state?
那么,用户级线程是否只是程序员在利用内核支持的线程执行由于其状态而无法正常执行的操作时创建的线程?
回答by BraveNewCurrency
Edit: The question was a little confusing, so I'm answering it two different ways.
编辑:这个问题有点令人困惑,所以我用两种不同的方式回答它。
OS-level threads vs Green Threads
操作系统级线程与绿色线程
For clarity, I usually say "OS-level threads" or "native threads" instead of "Kernel-level threads" (which I confused with "kernel threads" in my original answer below.) OS-level threads are created and managed by the OS. Most languages have support for them. (C, recent Java, etc) They are extremely hard to use because you are 100% responsible for preventing problems. In some languages, even the native data structures (such as Hashes or Dictionaries) will break without extra locking code.
为清楚起见,我通常说“操作系统级线程”或“本机线程”而不是“内核级线程”(我在下面的原始答案中将其与“内核线程”混淆。)操作系统级线程由创建和管理操作系统。大多数语言都支持它们。(C、最新的 Java 等)它们极难使用,因为您 100% 负责预防问题。在某些语言中,即使是本机数据结构(例如哈希或字典)也会在没有额外锁定代码的情况下中断。
The opposite of an OS-thread is a green threadthat is managed by your language. These threads are given various names depending on the language (coroutines in C, goroutines in Go, fibers in Ruby, etc). These threads only exist inside your language and not in your OS. Because the language chooses context switches (i.e. at the end of a statement), it prevents TONS of subtle race conditions (such as seeing a partially-copied structure, or needing to lock most data structures). The programmer sees "blocking" calls (i.e. data = file.read()
), but the language translates it into async calls to the OS. The language then allows othergreen threads to run while waiting for the result.
与操作系统线程相反的是由您的语言管理的绿色线程。这些线程根据语言被赋予不同的名称(C 中的协程、Go 中的 goroutine、Ruby 中的纤程等)。这些线程仅存在于您的语言中,而不存在于您的操作系统中。因为语言选择上下文切换(即在语句的末尾),它防止了微妙的竞争条件(例如看到部分复制的结构,或需要锁定大多数数据结构)。程序员看到“阻塞”调用(即data = file.read()
),但语言将其转换为对操作系统的异步调用。然后该语言允许其他绿色线程在等待结果时运行。
Green threads are much simpler for the programmer, but their performance varies: If you have a LOT of threads, green threads can be better for both CPU and RAM. On the other hand, most green thread languages can't take advantage of multiple cores. (You can't even buy a single-core computer or phone anymore!). And a bad library can halt the entire language by doing a blocking OS call.
对于程序员来说,绿色线程要简单得多,但它们的性能各不相同:如果您有很多线程,绿色线程对 CPU 和 RAM 都更好。另一方面,大多数绿色线程语言无法利用多核。(您甚至不能再购买单核计算机或手机了!)。一个糟糕的库可以通过阻塞操作系统调用来停止整个语言。
The best of both worlds is to have one OS thread per CPU, and many green threads that are magically moved around onto OS threads. Languages like Go and Erlang can do this.
两全其美的是每个 CPU 有一个操作系统线程,以及许多神奇地移动到操作系统线程上的绿色线程。像 Go 和 Erlang 这样的语言可以做到这一点。
system calls and other uses not available to user-level threads
用户级线程不可用的系统调用和其他用途
This is only half true. Yes, you can easily cause problems if you call the OS yourself (i.e. do something that's blocking.) But the language usually has replacements, so you don't even notice. These replacements do call the kernel, just slightly differently than you think.
这只是对了一半。是的,如果你自己调用操作系统(即做一些阻塞的事情),你很容易引起问题。但是语言通常有替代品,所以你甚至不会注意到。这些替代品确实调用了内核,只是与您想象的略有不同。
Kernel threads vs User Threads
内核线程与用户线程
Edit: This is my original answer, but it is about User space threads vs Kernel-only threads, which (in hindsight) probably wasn't the question.
编辑:这是我的原始答案,但它是关于用户空间线程与仅内核线程的,这(事后看来)可能不是问题。
User threads and Kernel threads are exactly the same. (You can see by looking in /proc/ and see that the kernel threads are there too.)
用户线程和内核线程完全一样。(您可以通过查看 /proc/ 看到内核线程也在那里。)
A User thread is one that executes user-space code. But it can call into kernel space at any time. It's still considered a "User" thread, even though it's executing kernel code at elevated security levels.
用户线程是执行用户空间代码的线程。但它可以随时调用内核空间。它仍然被认为是一个“用户”线程,即使它正在以更高的安全级别执行内核代码。
A Kernel thread is one that only runs kernel code and isn't associated with a user-space process. These are like "UNIX daemons", except they are kernel-only daemons. So you could say that the kernel is a multi-threaded program. For example, there is a kernel thread for swap. This forces all swap issues to get "serialized" into a single stream.
内核线程是只运行内核代码并且不与用户空间进程关联的线程。这些类似于“UNIX 守护进程”,只不过它们是仅内核守护进程。所以你可以说内核是一个多线程程序。例如,有一个用于交换的内核线程。这会强制所有交换问题“序列化”到单个流中。
If a user thread needs something, it will call into the kernel, which marks that thread as sleeping. Later, the swap thread finds the data, so it marks the user thread as runnable. Later still, the "user thread" returns from the kernel back to userland as if nothing happened.
如果用户线程需要某些东西,它将调用内核,从而将该线程标记为休眠。稍后,交换线程找到数据,因此它将用户线程标记为可运行。稍后,“用户线程”从内核返回到用户态,就好像什么都没发生一样。
In fact, allthreads start off in kernel space, because the clone() operation happens in kernel space. (And there's lots of kernel accounting to do before you can 'return' to a new process in user space.)
事实上,所有线程都是从内核空间开始的,因为 clone() 操作发生在内核空间。(在您可以“返回”到用户空间中的新进程之前,还有很多内核会计要做。)
回答by Yusuf Hassan
Before we go into comparison, let us first understand what a thread is. Threads are lightweight processes within the domain of independent processes. They are required because processes are heavy, consume a lot of resources and more importantly,
在进行比较之前,让我们先了解什么是线程。线程是独立进程域内的轻量级进程。它们是必需的,因为流程繁重,消耗大量资源,更重要的是,
two separate processes cannot share a memory space.
两个独立的进程不能共享内存空间。
Let's say you open a text editor. It's an independent process executing in the memory with a separate addressable location. You'll need many resources within this process, such as insert graphics, spell-checks etc. It's not feasible to create separate processes for each of these functionalities and maintain them independently in memory. To avoid this,
假设您打开了一个文本编辑器。它是一个在内存中执行的独立进程,具有单独的可寻址位置。在此过程中您将需要许多资源,例如插入图形、拼写检查等。为这些功能中的每一个创建单独的过程并在内存中独立维护它们是不可行的。为了避免这种情况,
multiple threads can be created within a single process, which can share a common memory space, existing independently within a process.
可以在单个进程中创建多个线程,这些线程可以共享一个公共内存空间,独立存在于一个进程中。
Now, coming back to your questions, one at a time.
现在,回到你的问题,一次一个。
I'm not really to sure about the differences between user-level and kernel-level threads.
我不太确定用户级线程和内核级线程之间的区别。
Threads are broadly classified as user level threadsand kernel level threadsbased on their domain of execution. There are also cases when one or many user thread maps to one or many kernel threads.
线程根据其执行域大致分为用户级线程和内核级线程。也有 一个或多个用户线程映射到一个或多个内核线程的情况。
- User Level Threads
- 用户级线程
User level threads are mostly at the application level where an application creates these threads to sustain its execution in the main memory. Unless required, these thread work in isolation with kernel threads.
用户级线程主要位于应用程序级,应用程序创建这些线程以维持其在主内存中的执行。除非需要,这些线程与内核线程隔离工作。
These are easier to create since they do not have to refer many registers and context switching is much faster than a kernel level thread.
这些更容易创建,因为它们不必引用许多寄存器,并且上下文切换比内核级线程快得多。
User level thread, mostly can cause changes at the application level and the kernel level thread continues to execute at its own pace.
用户级线程,大多会引起应用程序级的变化,内核级线程继续按照自己的节奏执行。
- Kernel Level Threads
- 内核级线程
These threads are mostly independent of the ongoing processes and are executed by the operating system.
这些线程大多独立于正在进行的进程并由操作系统执行。
These threads are required by the Operating System for tasks like memory management, process management etc.
操作系统需要这些线程来执行诸如内存管理、进程管理等任务。
Since these threads maintain, execute and report the processes required by the operating system; kernel level threads are more expensive to create and manage and context switching of these threads are slow.
由于这些线程维护、执行和报告操作系统所需的进程;内核级线程的创建和管理成本更高,并且这些线程的上下文切换速度很慢。
Most of the kernel level threads can not be preempted by the user level threads.
大多数内核级线程不能被用户级线程抢占。
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.
- User Level Threads mapped over Kernel Threads
- 用户级线程映射到内核线程
This is perhaps the most interesting part. Many user level threads map over to kernel level thread, which in-turn communicate with the kernel.
这可能是最有趣的部分。许多用户级线程映射到内核级线程,内核级线程又与内核通信。
Some of the prominent mappings are:
一些突出的映射是:
One to One
一对一
When one user level thread maps to only one kernel thread.
当一个用户级线程仅映射到一个内核线程时。
advantages: each user thread maps to one kernel thread. Even if one of the user thread issues a blocking system call, the other processes remain unaffected.
优点:每个用户线程对应一个内核线程。即使其中一个用户线程发出阻塞系统调用,其他进程也不受影响。
disadvantages: every user thread requires one kernel thread to interact and kernel threads are expensive to create and manage.
缺点:每个用户线程都需要一个内核线程来交互,并且内核线程的创建和管理成本很高。
Many to One
多对一
When many user threads map to one kernel thread.
当许多用户线程映射到一个内核线程时。
advantages: multiple kernel threads are not required since similar user threads can be mapped to one kernel thread.
优点:不需要多个内核线程,因为类似的用户线程可以映射到一个内核线程。
disadvantage: even if one of the user thread issues a blocking system call, all the other user threads mapped to that kernel thread are blocked.
缺点:即使其中一个用户线程发出阻塞系统调用,映射到该内核线程的所有其他用户线程也会被阻塞。
Also, a good level of concurrency cannot be achieved since the kernel will process only one kernel thread at a time.
此外,由于内核一次仅处理一个内核线程,因此无法实现良好的并发水平。
Many to Many
多对多
When many user threads map to equal or lesser number of kernel threads. The programmer decides how many user threads will map to how many kernel threads. Some of the user threads might map to just one kernel thread.
当许多用户线程映射到相等或更少数量的内核线程时。程序员决定将多少用户线程映射到多少内核线程。一些用户线程可能只映射到一个内核线程。
advantages: a great level of concurrency is achieved. Programmer can decide some potentially dangerous threads which might issue a blocking system call and place them with the one-to-one mapping.
优点:实现了高水平的并发性。程序员可以决定一些可能会发出阻塞系统调用的潜在危险线程,并将它们与一对一映射放置在一起。
disadvantage: the number of kernel threads, if not decided cautiously can slow down the system.
缺点:内核线程的数量,如果不慎重决定会减慢系统速度。
The other part of your question:
你问题的另一部分:
kernel-supported threads have access to the kernel for system calls and other uses not available to user-level threads.
So, are user-level threads simply threads created by the programmer when then utilise kernel-supported threads to perform operations that couldn't be normally performed due to its state?
内核支持的线程可以访问内核以进行系统调用和用户级线程不可用的其他用途。
那么,用户级线程是否只是程序员在利用内核支持的线程执行由于其状态而无法正常执行的操作时创建的线程?
Partially correct. Almost all the kernel thread have access to system calls and other critical interrupts since kernel threads are responsible for executing the processes of the OS. User thread will not have access to some of these critical features. e.g. a text editor can never shoot a thread which has the ability to change the physical address of the process. But if needed, a user thread can map to kernel thread and issue some of the system calls which it couldn't do as an independent entity. The kernel thread would then map this system call to the kernel and would execute actions, if deemed fit.
部分正确。由于内核线程负责执行操作系统的进程,因此几乎所有内核线程都可以访问系统调用和其他关键中断。用户线程将无法访问其中一些关键功能。例如,文本编辑器永远无法拍摄能够更改进程物理地址的线程。但是如果需要,用户线程可以映射到内核线程并发出一些它不能作为独立实体执行的系统调用。然后内核线程将这个系统调用映射到内核,并在认为合适的情况下执行操作。
回答by Nathan Day
Some development environments or languages will add there own threads like feature, that is written to take advantage of some knowledge of the environment, for example a GUI environment could implement some thread functionality which switch between user threads on each event loop.
一些开发环境或语言会在那里添加自己的线程,比如特性,这是为了利用环境的一些知识而编写的,例如 GUI 环境可以实现一些线程功能,在每个事件循环的用户线程之间切换。
A game library could have some thread like behaviour for characters. Sometimes the user thread like behaviour can be implemented in a different way, for example I work with cocoa a lot, and it has a timer mechanism which executes your code every x number of seconds, use fraction of a seconds and it like a thread. Ruby has a yield feature which is like cooperative threads. The advantage of user threads is they can switch at more predictable times. With kernel thread every time a thread starts up again, it needs to load any data it was working on, this can take time, with user threads you can switch when you have finished working on some data, so it doesn't need to be reloaded.
一个游戏库可以有一些类似于角色行为的线程。有时像用户线程的行为可以用不同的方式实现,例如我经常使用可可,它有一个计时器机制,它每 x 秒执行一次代码,使用几分之一秒,它就像一个线程。Ruby 有一个类似于协作线程的 yield 特性。用户线程的优点是它们可以在更可预测的时间切换。每次线程再次启动时,内核线程都需要加载它正在处理的任何数据,这可能需要时间,对于用户线程,您可以在处理完某些数据后进行切换,因此不需要重新加载。
I haven't come across user threads that look the same as kernel threads, only thread like mechanisms like the timer, though I have read about them in older text books so I wonder if they were something that was more popular in the past but with the rise of true multithreaded OS's (modern Windows and Mac OS X) and more powerful hardware I wonder if they have gone out of favour.
我还没有遇到过看起来与内核线程相同的用户线程,只有类似定时器这样的机制的线程,尽管我在较旧的教科书中读到过它们,所以我想知道它们是否在过去更受欢迎,但与真正的多线程操作系统(现代 Windows 和 Mac OS X)和更强大的硬件的兴起,我想知道它们是否已经失宠。
回答by Jia
Quote from here :
从这里引用:
To make concurrency cheaper, the execution aspect of process is separated out into threads. As such, the OS now manages threads and processes. All thread operations are implemented in the kernel and the OS schedules all threads in the system. OS managed threads are called kernel-level threads or light weight processes. NT: Threads Solaris: Lightweight processes(LWP).
为了使并发更便宜,进程的执行方面被分离到线程中。因此,操作系统现在管理线程和进程。所有线程操作都在内核中实现,操作系统调度系统中的所有线程。操作系统管理的线程称为内核级线程或轻量级进程。NT:线程 Solaris:轻量级进程 (LWP)。
In this method, the kernel knows about and manages the threads. No runtime system is needed in this case. Instead of thread table in each process, the kernel has a thread table that keeps track of all threads in the system. In addition, the kernel also maintains the traditional process table to keep track of processes. Operating Systems kernel provides system call to create and manage threads.
在这种方法中,内核知道并管理线程。在这种情况下不需要运行时系统。内核有一个线程表来跟踪系统中的所有线程,而不是每个进程中的线程表。此外,内核还维护了传统的进程表来跟踪进程。操作系统内核提供系统调用来创建和管理线程。
Advantages:
好处:
Because kernel has full knowledge of all threads, Scheduler may decide to give more time to a process having large number of threads than process having small number of threads. Kernel-level threads are especially good for applications that frequently block.
由于内核完全了解所有线程,因此调度程序可能会决定为具有大量线程的进程提供比具有少量线程的进程更多的时间。内核级线程特别适合经常阻塞的应用程序。
Disadvantages:
缺点:
The kernel-level threads are slow and inefficient. For instance, threads operations are hundreds of times slower than that of user-level threads. Since kernel must manage and schedule threads as well as processes. It require a full thread control block (TCB) for each thread to maintain information about threads. As a result there is significant overhead and increased in kernel complexity.
内核级线程速度慢且效率低下。例如,线程操作比用户级线程慢数百倍。由于内核必须管理和调度线程以及进程。每个线程都需要一个完整的线程控制块 (TCB) 来维护有关线程的信息。因此,存在显着的开销并增加了内核复杂性。
User-Level Threads
用户级线程
Kernel-Level threads make concurrency much cheaper than process because, much less state to allocate and initialize. However, for fine-grained concurrency, kernel-level threads still suffer from too much overhead. Thread operations still require system calls. Ideally, we require thread operations to be as fast as a procedure call. Kernel-Level threads have to be general to support the needs of all programmers, languages, runtimes, etc. For such fine grained concurrency we need still "cheaper" threads. To make threads cheap and fast, they need to be implemented at user level. User-Level threads are managed entirely by the run-time system (user-level library).The kernel knows nothing about user-level threads and manages them as if they were single-threaded processes.User-Level threads are small and fast, each thread is represented by a PC,register,stack, and small thread control block. Creating a new thread, switiching between threads, and synchronizing threads are done via procedure call. i.e no kernel involvement. User-Level threads are hundred times faster than Kernel-Level threads.
内核级线程使并发比进程便宜得多,因为要分配和初始化的状态要少得多。然而,对于细粒度的并发,内核级线程仍然会承受过多的开销。线程操作仍然需要系统调用。理想情况下,我们要求线程操作与过程调用一样快。内核级线程必须是通用的,以支持所有程序员、语言、运行时等的需求。对于这种细粒度的并发,我们仍然需要“更便宜”的线程。为了使线程既便宜又快速,它们需要在用户级别实现。用户级线程完全由运行时系统(用户级库)管理。内核对用户级线程一无所知,像单线程进程一样管理它们。用户级线程小而快,每个线程由一个 PC 表示,寄存器、堆栈和小线程控制块。创建新线程、切换线程和同步线程都是通过过程调用完成的。即没有内核参与。用户级线程比内核级线程快一百倍。
Advantages:
好处:
The most obvious advantage of this technique is that a user-level threads package can be implemented on an Operating System that does not support threads. User-level threads does not require modification to operating systems. Simple Representation: Each thread is represented simply by a PC, registers, stack and a small control block, all stored in the user process address space. Simple Management: This simply means that creating a thread, switching between threads and synchronization between threads can all be done without intervention of the kernel. Fast and Efficient: Thread switching is not much more expensive than a procedure call.
这种技术最明显的优点是可以在不支持线程的操作系统上实现用户级线程包。用户级线程不需要修改操作系统。简单表示:每个线程由PC、寄存器、堆栈和一个小的控制块简单表示,所有这些都存储在用户进程地址空间中。简单管理:这只是意味着创建线程、线程之间的切换和线程之间的同步都可以在没有内核干预的情况下完成。快速高效:线程切换并不比过程调用昂贵多少。
Disadvantages:
缺点:
User-Level threads are not a perfect solution as with everything else, they are a trade off. Since, User-Level threads are invisible to the OS they are not well integrated with the OS. As a result, Os can make poor decisions like scheduling a process with idle threads, blocking a process whose thread initiated an I/O even though the process has other threads that can run and unscheduling a process with a thread holding a lock. Solving this requires communication between between kernel and user-level thread manager. There is a lack of coordination between threads and operating system kernel. Therefore, process as whole gets one time slice irrespect of whether process has one thread or 1000 threads within. It is up to each thread to relinquish control to other threads. User-level threads requires non-blocking systems call i.e., a multithreaded kernel. Otherwise, entire process will blocked in the kernel, even if there are runable threads left in the processes. For example, if one thread causes a page fault, the process blocks.
用户级线程不是一个完美的解决方案,就像其他所有东西一样,它们是一种权衡。由于用户级线程对操作系统不可见,因此它们没有与操作系统很好地集成。因此,操作系统可能会做出糟糕的决定,例如使用空闲线程调度进程、阻塞其线程发起 I/O 的进程,即使该进程有其他可以运行的线程,以及使用持有锁的线程取消调度进程。解决这个问题需要内核和用户级线程管理器之间的通信。线程和操作系统内核之间缺乏协调。因此,无论进程内有 1 个线程还是 1000 个线程,整个进程都会获得一个时间片。由每个线程将控制权交给其他线程。用户级线程需要非阻塞系统调用,即,一个多线程内核。否则,整个进程都会在内核中被阻塞,即使进程中还有可运行的线程。例如,如果一个线程导致页面错误,进程就会阻塞。
回答by Razib Palash
User Threads
用户线程
- The library provides support for thread creation, scheduling and management with no support from the kernel.
- The kernel unaware of user-level threads creation and scheduling are done in user space without kernel intervention.
- User-level threads are generally fast to create and manage they have drawbacks however.
- If the kernel is single-threaded, then any user-level thread performing a blocking system call will cause the entire process to block, even if other threads are available to run within the application.
- User-thread libraries include POSIX Pthreads, Mach C-threads, and Solaris 2 UI-threads.
- 该库支持线程创建、调度和管理,无需内核支持。
- 内核不知道用户级线程的创建和调度是在用户空间完成的,无需内核干预。
- 用户级线程通常可以快速创建和管理,但它们也有缺点。
- 如果内核是单线程的,那么任何执行阻塞系统调用的用户级线程都会导致整个进程阻塞,即使其他线程可以在应用程序中运行。
- 用户线程库包括 POSIX Pthreads、Mach C 线程和 Solaris 2 UI 线程。
Kernel threads
内核线程
- The kernel performs thread creation, scheduling, and management in kernel space.
- kernel threads are generally slower to create and manage than are user threads.
- the kernel is managing the threads, if a thread performs a blocking system call.
- A multiprocessor environment, the kernel can schedule threads on different processors. 5.including Windows NT, Windows 2000, Solaris 2, BeOS, and Tru64 UNIX (formerlyDigital UN1X)-support kernel threads.
- 内核在内核空间中执行线程创建、调度和管理。
- 内核线程的创建和管理通常比用户线程慢。
- 如果线程执行阻塞系统调用,则内核正在管理线程。
- 在多处理器环境中,内核可以在不同的处理器上调度线程。5.包括Windows NT、Windows 2000、Solaris 2、BeOS和Tru64 UNIX(原Digital UN1X)——支持内核线程。