目录
Linux线程切换:
Linux线程切换的实现涉及到操作系统的调度和线程上下文的切换。
线程上下文包括程序计数器(PC)和寄存器值,以及线程的堆栈和堆栈指针等。
操作系统通过调度器决定哪个线程将获得CPU时间片来执行。
当一个线程被操作系统调度器选中时,线程上下文会从CPU寄存器和内存中保存。然后,操作系统会将另一个线程的上下文加载到CPU中,这个新的线程开始执行,之前的线程则被暂停。
在 Linux 中,有两种类型的线程:用户线程和内核线程。用户线程是应用程序中的线程,内核线程则是由操作系统创建和管理的线程。用户线程的调度是由用户空间的调度器完成的,而内核线程的调度则是由内核空间的调度器完成的。
Linux线程切换的实现有两种情况:
- 如果前后两个线程属于不同进程,那么线程切换就跟进程切换一样,需要保存和恢复所有的资源和寄存器。
- 如果前后两个线程属于同一个进程,那么线程切换只需要保存和恢复线程的私有数据和寄存器,因为虚拟内存等资源是共享的。
线程切换的实现主要涉及到以下几个步骤:
- 保存当前线程的上下文:当一个线程被抢占时,它的上下文将被保存到内存中。这个过程包括将程序计数器(PC)和寄存器中的值保存到线程的内存区域中。
- 选择下一个线程:操作系统的调度器从就绪队列中选择下一个将要执行的线程,并将其上下文从内存中读取到CPU寄存器中。
- 恢复下一个线程的上下文:调度器将下一个线程的上下文从内存中读取到CPU寄存器中,并开始执行新的线程。
- 执行新线程:CPU开始执行新的线程,直到发生抢占或线程完成。如果线程完成,操作系统将释放线程的资源,如果发生抢占,重复步骤1-3。
Linux采用一对一的线程模型,用户线程切换与内核线程切换之间的差别非常小。同时,如果忽略用户主动放弃用户线程的执行权(yield)带来的开销,则只需要考虑内核线程切换的开销。
总的来说,Linux线程切换的实现是一个复杂的过程,涉及到多个组件和操作系统的核心机制。不过,操作系统的调度器和线程库已经对这个过程进行了封装和优化,使得开发者可以方便地使用线程来编写高效的并发程序。
Linux进程切换:
进程切换就是上下文切换。
进程切换和线程切换的区别
这里说的是相同进程下的线程。
最主要的一个区别在于进程切换涉及虚拟地址空间的切换而线程不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
虚拟地址空间切换耗时的原因
现在我们已经知道了进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个cache就是TLB。由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。