rap*_*yen 32 multithreading process context-switch
我被要求描述两个不同进程之间的上下文切换(1)所涉及的步骤,以及(2)同一进程中两个不同线程之间的步骤.
这太普遍了,或者你会加入什么来解释这个过程更清楚?
Mar*_*mes 57
由于进程切换总是涉及线程切换,因此以相反的顺序解释它们要容易得多.
单核CPU上的典型线程上下文切换如下所示:
所有上下文切换都由"中断"启动.这可能是运行驱动程序的实际硬件中断(例如,来自网卡,键盘,内存管理或计时器硬件),或者是执行类似硬件中断的调用序列的软件调用(系统调用)进入操作系统 在驱动程序中断的情况下,OS提供了一个驱动程序可以调用而不是执行"正常"直接中断返回的入口点,因此如果需要操作系统设置线程,则允许驱动程序通过OS调度程序退出准备就绪,(例如,它已标示信号量).
非平凡系统必须启动硬件保护级别更改才能进入内核状态,以便可以访问内核代码/数据等.
必须保存中断线程的核心状态.在一个简单的嵌入式系统中,这可能只是将所有寄存器推送到线程堆栈并将堆栈指针保存在其线程控制块(TCB)中.
许多系统在此阶段切换到OS专用堆栈,因此大量的OS内部堆栈要求不会在每个线程的堆栈上造成.
可能需要标记发生中断状态更改的线程堆栈位置以允许嵌套中断.
驱动程序/系统调用运行并且可以通过从内部队列添加/移除TCB来针对不同的线程优先级来改变准备好的线程集合,例如.网卡驱动程序可能已设置事件或发信号通知另一个线程正在等待的信号量,因此该线程将被添加到就绪集,或者正在运行的线程可能已调用sleep(),因此选择将其自身从就绪集中移除.
运行OS调度程序算法以决定接下来运行哪个线程,通常是位于该优先级队列前面的最高优先级就绪线程.如果下一个运行的线程属于与先前运行的线程不同的进程,那么这里需要一些额外的东西(参见后面的内容).
检索来自该线程的TCB的保存堆栈指针并将其加载到硬件堆栈指针中.
将恢复所选线程的核心状态.在我的简单系统上,寄存器将从所选线程的堆栈中弹出.更复杂的系统必须处理返回用户级保护.
执行中断返回,因此将执行转移到所选线程.
在多核CPU的情况下,事情更复杂.调度程序可以决定当前在另一个核心上运行的线程可能需要被停止并由刚刚准备就绪的线程替换.它可以通过使用其处理器间驱动程序硬件中断运行必须停止的线程的核心来实现此目的.除了所有其他东西之外,这个操作的复杂性是避免编写OS内核的一个很好的理由:)
典型的进程上下文切换发生如下:
进程上下文切换由线程上下文切换启动,因此上述所有内容1-9都需要发生.
在上面的步骤5,调度程序决定运行属于与拥有先前运行的线程的进程不同的进程的线程.
内存管理硬件必须加载新进程的地址空间,即任何选择器/段/标志/允许新进程的线程访问其内存的任何内容.
任何FPU硬件的上下文都需要从PCB保存/恢复.
可能存在需要保存/恢复的其他过程专用硬件.
在任何真实的系统中,这些机制都是依赖于体系结构的,上面是对上下文切换的含义的粗略和不完整的指导.进程交换机生成的其他开销并不是交换机的严格组成部分 - 在进程切换后可能会有额外的缓存刷新和页面错误,因为它的某些内存可能已经被分页以支持页面归属拥有之前运行的线程的进程.
Zar*_*trA 14
我希望我能提供更详细/清晰的图片.
首先,OS调度线程而不是进程,因为线程是系统中唯一的可执行单元.进程切换只是一个线程切换,其中线程属于不同的进程.由于这一般,开关程序很常见.
应该调用调度程序.有三个基本的风格:
在所有情况下,为了能够执行线程切换,应该将控制传递给内核.在非自愿开关的情况下,这种控制传递通过中断来执行,在自愿(和半自愿)的情况下,通过系统调用传递控制.
在这两种情况下,进入内核都是CPU辅助的.处理器执行权限检查,记住线程被抢占的点(以便将来能够恢复它),从线程堆栈的用户部分切换到其内核对应部分,并将控件传递给预定义且众所周知的点.内核代码.
一些摘要说明:
(来源:上下文切换)