抢占式、单片式、多任务操作系统上的上下文切换涉及两种路径之一,一种是通过某些系统服务调用(睡眠、互斥获取、等待事件、阻塞 I/O)隐式让步给调度程序,另一种是通过中断和调度程序决定交换正在运行的任务。
当调度程序交换任务时,会发生一些重量级的事情:
- 所有操作都作为操作系统内核的一部分发生,以高级别的特权运行。检查(或应该检查)每个操作,以确保调度程序做出的决定不会授予任务任何额外的权限(想想本地 root 漏洞利用)
- 交换用户模式进程地址空间。这导致内存管理器在页表布局中闲逛,并将新的目录库加载到控制寄存器中。
- 这也意味着保存在 CPU 缓存中的数据可能会被删除和清除。如果您的任务刚刚访问了一堆常用的东西,然后上下文切换并“丢失”它(在下次访问时,它[可能]必须再次从主内存中获取),这将很糟糕
- 根据您进入内核的方式,您需要从内核中捕获 OUT。例如,如果您进行系统调用,CPU 将通过一组非常精确的步骤转换到内核中运行的代码,然后在退出时展开这些步骤。这些步骤比对程序中的另一个模块进行函数调用更复杂,因此它们需要更多时间。
据我了解,绿色线程任务非常简单。用户模式调度程序指示协程运行,直到协程屈服。上面的一些区别:
- None of the dispatching of coroutines happens in kernel mode, indeed dispatching green threads generally does not need to involve any operating system services, or any blocking operating system services. So all of this can happen without any context switches or any user/kernel translation.
- A green thread isn't preemptively scheduled, or even preempted at all by the green thread manager, they are scheduled co-operatively. This is good and bad, but with well written routines, generally good. Each task does precisely what it needs to do and then traps back to the dispatcher, but without any context swap overhead.
- 绿色线程共享它们的地址空间(据我所知)。在上下文切换时不会发生地址空间的交换。堆栈(据我所知)已交换,但这些堆栈由调度程序管理,并且交换堆栈也是对寄存器的简单写入。交换堆栈也是一种非特权操作。
简而言之,用户模式下的上下文切换涉及一些库调用和写入堆栈指针寄存器。内核模式下的上下文切换涉及中断、用户/内核转换和系统级行为,如地址空间状态更改和缓存刷新。