操作系统系列 - 进程、线程与协程一文搞懂

87 阅读6分钟

Screenshot 2023-12-18 at 15.35.55.png

引言

Hello 大家,前段时间重看了《Linux系统性能优化》一书,在此总结一下操作系统、进程、线程与协程相关的基础知识,希望对广大程序员朋友们有点点帮助。

操作系统

我们知道操作系统是管理计算机硬件与软件资源的系统软件,它充当计算机硬件与用户及应用程序之间的中间调度系统。为了更高效地发挥硬件资源的能力,操作系统这个调度系统需要具备多任务处理和并发处理的能力,于是人们就创造了进程、线程和协程等概念。进程提供基本隔离,线程提供内部并发,协程优化并发效率。

下面对三者进行一个具体阐述:

进程

  • 是什么
    • 进程是正在运行的一个程序实体,具有独立的内存空间
      • 程序是什么?
        • 程序是一些保存在磁盘上的指令的有序集合,是静态的
    • 进程是操作系统进行资源分配的最小单元
      • 你可能又会问了,那进程都管理哪些资源呢?
        • 简单来说,进程管理的资源有
          • 内存资源(操作系统采用虚拟内存技术,把进程虚拟地址空间划分成用户空间和内核空间)
          • 进程内存分为:栈区,代码区,数据区,堆区等区域
          • IO资源
          • 信号处理
          • 文件资源
          • 打开的文件描述符
          • ...
  • 解决了什么问题
    • 进程让操作系统的多任务能力得以实现
  • 如何解决的
    • 我们用进程切换的流程来阐述这个问题吧
      1. 通过时钟中断(cpu时间片用完了)、设备中断、进程自己上报等待状态等方式,操作系统判断要切换进程了
      2. 保存现场:
        • 将当前进程的资源状态信息记录到PCB,具体的资源状态处理下边会具体阐述
      3. 操作系统将CPU从用户态切换到内核态
        • 以便操作系统内核安全管理进程上下文切换
      4. 选择下一个进程
        • CPU根据时间片轮转算法从就绪队列中选取下一个可运行进程
      5. 恢复上下文环境
        • 从选定进程的PCB中读取之前保存的状态信息还原到CPU寄存器,内存等处。
      6. 从内核到用户态
        • CPU再从内核模式切换回用户模式,安全地运行用户进程。
    • 进程切换涉及到的资源状态处理:
      1. CPU资源:保存当前进程的CPU状态(程序计数器、寄存器内容等)到PCB
        • 进程控制块(PCB)是操作系统为每个进程都维护的一个数据结构,它包含了该进程的状态信息。每个PCB都存储在内存的操作系统区,而不是用户区或堆区。 操作系统可以高效控制和访问这些PCB。
      2. 内存资源:保存该进程的内存页信息到PCB,如果内存资源不够了,该进程中的部分数据页需要释放内存空间给其他进程使用,操作系统会将其换出到磁盘文件交换区,当再次调度该进程时,会将磁盘交换区的数据页读回内存,还原进程运行环境
        • 进程内存资源还包括其下所有线程的堆栈信息和资源分配情况等
        • "交换区" 指操作系统在磁盘中专门用于进程交换的区域
      3. 文件资源:如果有打开文件,需要将文件状态和位置信息保存到内核维护的全局文件表和PCB中;恢复时还原文件状态
        • 文件表记录用于后续该文件可被多个进程共享访问。
        • 进程控制块记录用于恢复该进程自己之前的文件状态。
      4. 设备资源(磁盘/网卡等):如果占用设备,需要保存当前状态并启用中断;恢复时还原设备状态。
        • 当前进程占用某个设备进行IO操作时(如读磁盘),操作系统会禁止该设备产生中断
        • 当进程切换时,操作系统需要保存设备当前的内部状态(如数据缓冲区中的内容)
        • 同时使能该设备的中断,允许后续操作引起中断
        • 当进程恢复运行后,操作系统需要从状态信息中还原设备内部状态
        • 然后进程可以从中断点继续之前未完成的IO操作,或者处理之前期间积累的中断
      5. 信号量:需要保存和恢复相关信号量的状态。
        • 信号量是一种同步原语,用于进程间的通信和同步。
        • 将当前进程持有的所有信号量的计数状态保存下来,记录在进程控制块中
        • 将这些信号量释放,使其他等待的进程可获取它们
        • 切回原进程时,恢复其持有的信号量的计数状态
      6. 互斥锁:释放当前进程持有的互斥锁,为目标进程获取所需锁
      7. 队列资源:保存相关队列中的消息状态
        • 队列资源指进程间通过消息队列进行通信的消息状态
        • 将当前进程在各个队列中的消息拷贝状态保存到进程控制块
        • 重新开始时,恢复这些队列状态,使进程可以从中继续收发消息
      8. 时间资源:更新进程资源使用时间统计
      9. 其他:比如用户ID/组ID, traba查进度等进程环境信息

线程

  • 是什么
    • 线程是操作系统调度CPU执行的最小单元
    • 同一进程下可以有多个线程,多个线程间共享此进程中的内存空间与资源
      • 所以同一进程下的多个线程互相通信相对简单,加锁访问共享资源即可
      • 但也因为此关联性,当某个线程出问题时,可能会影响整个进程及其他线程
    • 另外,每个线程拥有独立的栈区以及很少的寄存器内容(如程序计数器)
  • 解决了什么问题
    • 提高了操作系统并发处理任务的能力
  • 如何解决的
    • 我们用线程切换的流程来阐述这个问题吧
      1. 保存线程上下文
        • 操作系统将当前线程的CPU寄存器内容(如程序计数器、堆栈指针等)保存到线程控制块TCB中。
      2. 从用户态到内核态
        • 与进程切换一致
      3. 选择下一个线程
        • 与进程切换一致
      4. 上下文切换
        • 与进程切换一致
      5. 切换回用户态
        • 与进程切换一致
    • 与进程切换不同的是,线程切换仅需要保存和恢复线程自己的上下文环境, 比如栈指针等信息,开销更小

协程

  • 是什么
    • 协程是一种运行在用户态的轻量级线程,多个协程可以并发运行在同一个线程上。
  • 解决了什么问题
    • 协程切换不涉及CPU内核态与用户态切换,成本更低
  • 如何解决的
    • 保存当前协程内部栈地址和程序计数器等上下文
    • 恢复上一个协程的上下文环境。
    • 进行上下文环境的快速切换,无需系统内核参与调度。