经典面试题:进程、线程、协程开销问题,为什么进程切换的开销比线程的大?

上下文切换的过程?

上下文切换是操作系统在将CPU从一个进程切换到另一个进程时所执行的过程。它涉及保存当前执行进程的状态并加载下一个将要执行的进程的状态。下面是上下文切换的详细过程:

  1. 保存当前进程的上下文
  • 当操作系统决定切换到另一个进程时,首先需要保存当前正在执行的进程的执行状态。
  • 这包括将当前进程的寄存器状态(如通用寄存器、程序计数器PC、栈指针等)保存到进程控制块(PCB)中。
  • 操作系统还可能会保存其他与进程相关的状态信息,如页表、内存映射、打开的文件等。
  1. 选择新进程
  • 操作系统根据调度算法从就绪队列中选择下一个要执行的进程。
  • 这个选择可能基于各种因素,如优先级、时间片大小、进程状态等。
  1. 加载新进程的上下文
  • 一旦新进程被选择,操作系统需要加载该进程的执行状态,以便CPU可以开始执行该进程。
  • 这包括从该进程的PCB中恢复寄存器状态,如通用寄存器、程序计数器PC、栈指针等。
  • 操作系统还可能恢复其他与进程相关的状态信息,如页表、内存映射、打开的文件等。
  1. 更新调度信息
  • 在进行上下文切换后,操作系统可能需要更新调度信息,如更新就绪队列、时间片计数等。
  • 这确保了系统可以继续有效地调度进程,并避免出现死锁或其他资源争用问题。
  1. 切换到新进程执行
  • 一旦新进程的上下文被加载到CPU中,CPU开始执行新进程的代码。
  • 新进程从其上次中断或被抢占的位置继续执行。

进程、线程、协程切换的开销?

  1. 进程切换的开销
  • 进程切换涉及到从一个进程切换到另一个进程,因此需要保存和恢复大量的上下文信息,包括寄存器状态、内存映射、文件描述符等。
  • 进程切换的开销通常较大,因为它需要切换整个进程的上下文,可能涉及到内存的切换和页面交换等操作。
  • 由于进程之间是相互隔离的,切换进程需要操作系统进行较多的工作,包括内存管理、权限检查等,因此进程切换的开销相对较大。
  1. 线程切换的开销
  • 线程是在同一个进程内部运行的,因此线程切换的开销相对较小。
  • 线程切换只需要保存和恢复线程的寄存器状态和堆栈信息等少量上下文信息。
  • 由于线程共享进程的地址空间和其他资源,线程切换无需进行内存管理或权限检查等操作,因此开销较进程切换要小。
  1. 协程切换的开销
  • 协程是轻量级的用户态线程,其切换开销比进程和线程都要小。
  • 协程切换只需要保存和恢复协程的栈帧信息,以及一些额外的状态信息,如指令指针等。
  • 由于协程是在用户态管理的,无需涉及操作系统的内核调度和内存管理,因此协程切换的开销最小。

为什么进程切换的开销比线程的大?

  • 进程是系统资源的基本单位,它们之间是相互隔离的,切换进程需要操作系统进行大量的内存管理和权限检查等工作,因此开销较大。
  • 各个进程之间可能拥有独立的内存空间,切换进程需要进行内存页的切换和可能的页面交换,把虚拟地址转换为物理地址需要查页表,查页表是很慢的过程,转换检测缓冲区 TLB 可以提高页表查询速度就是一个缓存,页表切换后 TLB 就会失效,命中率就会变低,切换过程就会慢,线程则不需要切换地址空间所以开销比较小。

为什么线程切换的开销比协程的大?

协程切换比线程切换开销小的主要原因有以下几点:

  1. 用户空间操作: 协程通常在用户空间内管理,切换时不需要陷入内核态,而线程切换涉及内核态和用户态之间的切换。由于内核态切换通常涉及到上下文的保存和恢复,以及内核数据结构的操作,开销较大。
  2. 轻量级调度: 协程的调度是由用户程序自行控制的,通常采用协作式调度,用户程序在适当的时机主动让出CPU,切换到其他协程。这种调度方式不需要内核的介入,开销较小。
  3. 上下文切换成本低: 协程切换通常只涉及保存和恢复协程的执行上下文,如栈指针、寄存器等,这个过程在用户空间内完成,不涉及内核调度器和内核态的切换,因此开销较小。
  4. 无需同步原语: 在线程切换时,通常需要考虑同步原语(如互斥锁、条件变量)的状态和处理,以确保线程间的数据一致性。而在协程切换时,通常不需要考虑这些同步原语,因为协程之间共享同一个线程的地址空间,不涉及多线程之间的竞争和同步。

协程切换比线程切换开销小的主要原因是协程在用户空间内管理,不涉及内核态和用户态之间的切换,调度方式轻量级,上下文切换成本低,且无需考虑同步原语等因素。这使得协程在高并发、IO密集型等场景下具有较好的性能和效率。

什么是 TLB?

TLB(Translation Lookaside Buffer,译码后备缓冲器)是一种硬件缓存,存储了最近使用的虚拟地址到物理地址的映射关系,用于加速虚拟地址到物理地址的转换过程。在现代计算机体系结构中,TLB通常被用于处理虚拟内存系统中的地址转换。由于TLB的容量有限,如果访问的虚拟地址不在TLB中,就会发生TLB缺失(TLB Miss),此时需要访问MMU进行地址转换,并将新的映射关系加载到TLB中。因此,TLB的命中率直接影响了系统的性能表现。

  1. 加速地址转换: TLB存储了虚拟地址到物理地址的映射关系,当CPU需要访问内存时,先在TLB中查找对应的物理地址,如果命中则直接获取物理地址,避免了访问内存管理单元(MMU)进行地址转换的开销。
  2. 减少内存访问延迟: 由于TLB位于CPU芯片内部,其访问速度远高于访问主存的速度,因此能够大大减少内存访问的延迟,提高程序执行效率。
  3. 提高性能: TLB的存在可以大幅度提高系统的性能,特别是在需要频繁进行地址转换的应用场景下,如多任务操作系统、虚拟化环境等。

为什么每次切换 TLB 都会失效?

TLB(Translation Lookaside Buffer,译码后备缓冲器)每次失效的原因主要有以下几点:

  1. 容量限制: TLB是一个硬件缓存,其容量通常比较有限。当系统中的虚拟地址空间非常大时,TLB无法存储所有的虚拟地址到物理地址的映射关系,因此会发生TLB失效。
  2. 进程切换: 在多任务操作系统中,每个进程都有自己的虚拟地址空间,当发生进程切换时,当前进程的虚拟地址空间会被替换为下一个进程的虚拟地址空间。由于不同进程的虚拟地址空间可能不同,因此TLB中存储的映射关系就会失效。
  3. 页表更新: 虚拟地址到物理地址的映射关系是由操作系统的页表管理的,当页表发生变化时(如页面置换、页表更新等),TLB中存储的映射关系也会失效。
  4. 地址空间切换: 在虚拟化环境中,虚拟机之间的地址空间是相互隔离的,当虚拟机切换时,TLB中存储的映射关系也会失效。
相关推荐
Lee川3 小时前
优雅进化的JavaScript:从ES6+新特性看现代前端开发范式
javascript·面试
Lee川6 小时前
从异步迷雾到优雅流程:JavaScript异步编程与内存管理的现代化之旅
javascript·面试
晴殇i8 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
绝无仅有9 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有9 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
AAA梅狸猫10 小时前
Looper.loop() 循环机制
面试
AAA梅狸猫10 小时前
Handler基本概念
面试
Wect10 小时前
浏览器缓存机制
前端·面试·浏览器
掘金安东尼11 小时前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试
掘金安东尼11 小时前
Next.js 企业级落地
前端·javascript·面试