【操作系统】进程、线程调度

357 阅读7分钟

进程

可执行文件的一次执行为一个进程。

并发

Why?

一个CPU处理器核需要运行多个程序任务,为了更加公平的运行这些任务,通过并发的方式组织这些任务的执行。

How?

  • 并发:一段时间内多个程序同时执行
  • 并行:多个核同一时刻分别运行着不同的任务

进程的状态

Why?

操作系统对进程进行调度,过程中进程对应了不同的状态

What?

五态模型

  • 创建:进程正在被创建
  • 运行:占用CPU
  • 就绪:准备就绪,等待CPU执行
  • 阻塞:等待某一事件(输入输出、IO网络)暂停运行,让出CPU
  • 结束:运行完毕,正在删除进程

进程的状态变迁:

  • 创建状态:一个新进程被创建时的第一个状态;
  • 创建状态 -> 就绪状态:进程创建完成并初始化后,一切就绪准备运行时;
  • 就绪态 -> 运行状态:被操作系统的进程调度器选中,分配给 CPU 正式运行该进程;
  • 运行状态 -> 结束状态:当进程已经运行完成或出错时,会被操作系统作结束状态处理;
  • 运行状态 -> 就绪状态:运行中时间片用完;
  • 运行状态 -> 阻塞状态:进程请求某个事件且必须等待;
  • 阻塞状态 -> 就绪状态:进程要等待的事件完成;

七态模型

增加挂起状态:内存数据移动到磁盘,被暂时挂了起来

  • 阻塞挂起状态:进程在外存(硬盘)并等待某个事件的出现;
  • 就绪挂起状态:进程在外存(硬盘),但只要进入内存,即刻立刻运行;

进程控制块 PCB

Why?

进程的数据、状态等需要用一个结构存储,就是PCB。

What?

PCB是进程的描述符,标识了进程的存在

包含的信息:

  • 进程描述信息:

    • 进程标识符:进程的唯一标识符;
    • 用户标识符:进程归属的用户,用户标识符主要为共享和保护服务;
  • 进程控制和管理信息:

    • 进程当前状态,如 new、ready、running、waiting 或 blocked 等;
    • 进程优先级:进程抢占 CPU 时的优先级;
  • 资源分配清单:

    • 有关内存地址空间或虚拟地址空间的信息,所打开文件的列表和所使用的 I/O 设备信息。
  • CPU 相关信息:

    • CPU 中各个寄存器的值,以便进程重新执行时,能从断点处继续执行。

PCB组装形式:

  • 链表:链表把具有相同状态的进程链在一起,组成各种队列。
  • 索引:将同一状态的进程组织在一个索引表中,索引表项指向相应的 PCB。

进程的上下文切换:

几十纳秒到几微秒之间

CPU由一个进程切换到另一个进程运行。CPU上下文由寄存器和程序计数器组成。

  • CPU 寄存器:存储了运行程序的信息
  • 程序计数器:存储了运行到哪一步了
  • 进程上下文切换:PCB保存前一个任务的上下文,从PCB加载当前任务的上下文

线程

Why?

  • 通常一个程序有很多部分组成,多进程开销太大、数据共享不方便

How?

  • 线程:是进程当中的一条执行流程。

    • 一个进程可以开很多线程,线程间可以并发执行,共享相同的地址空间、文件等资源
    • 优点:创建删除快、占用空间小;同一个进程内的线程上下文切换开销小,数据交换效率高
    • 缺点:进程崩,所有线程都崩。

进程VS线程

  • 进程是资源(包括内存、打开的文件等)分配的单位,线程是 CPU 调度的单位;
  • 进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈;
  • 线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系;
  • 线程能减少并发执行的时间和空间开销;

线程上下文切换

  • 不同进程的线程:与进程切换一致
  • 同进程的线程:只需要切换线程的私有数据、寄存器等不共享的数据

线程的实现

三种线程的实现方式:

  • 用户线程(User Thread):在用户空间实现的线程,由用户态的线程库来完成线程的管理;

    • 线程控制块(Thread Control Block, TCB)记录它各个线程状态信息(PC、栈指针、寄存器),在线程库里,PCB不可见

    • 用户线程的整个线程管理和调度,操作系统是不直接参与的,而是由用户级线程库函数来完成线程的管理,包括线程的创建、终止、同步和调度等

    • 多个用户线程对应同一个内核线程

    • 缺点:

      • 一个线程发起了系统调用而阻塞,那进程所包含的用户线程都不能执行了。
      • 一个线程开始运行后,除非它主动地交出 CPU 的使用权,否则它所在的进程当中的其他线程无法运行
      • 时间片分配给进程,故与其他进程比,在多线程执行时,每个线程得到的时间片较少,执行会比较慢;
  • 内核线程(Kernel Thread):在内核中实现的线程,是由内核管理的线程;

    • 操作系统管理,TCB 放在操作系统里的,这样线程的创建、终止和管理都是由操作系统负责。

    • 优点:

      • 在一个进程当中,如果某个内核线程发起系统调用而被阻塞,并不会影响其他内核线程的运行;
      • 分配给线程,多线程的进程获得更多的 CPU 运行时间;
    • 缺点:系统

  • 轻量级进程(Light Weight Process):在内核中来支持用户线程;

    • 一个进程可有一个或多个 LWP,每个 LWP 是跟内核线程一对一映射的

    • LWP与用户线程有一对一、多对一、多对多关系

      • 1 : 1 模式:并行度高、开销大

      • N : 1 模式:用户线程数量没限制,且上下文切换发生用户空间,切换的效率较高;一个用户线程如果阻塞了,则整个进程都将会阻塞,另外在多核 CPU 中,是没办法充分利用 CPU 的。

      • M : N 模式:综合了前两种优点,大部分的线程上下文发生在用户空间,且多个线程又可以充分利用多核 CPU 的资源。

      • 组合模式:结合上面三种

调度⭐

Why?

多进程都想在CPU上执行,需要设计一个公平的执行调度算法。

How?

调度时机:就绪 -> 运行、运行 -> 阻塞、运行 -> 结束。

调度原则

  • CPU 利用率高:当CPU空闲(IO、网络阻塞)就调度,使CPU一直忙着
  • 系统吞吐量高:(CPU 在单位时间内完成的进程数量)防止长任务一直占用CPU
  • 周转时间短:进程运行和阻塞时间总和要短
  • 等待时间短:绪队列的时间要短
  • 响应时间短:用户提交请求到系统第一次产生响应所花费的时间

调度算法

  • 非抢占式调度:一个进程运行到结束才切换。非常不公平。

    • 先来先服务(First Come First Severd, FCFS)

    • 最短作业优先(Shortest Job First, SJF)

    • 高响应比优先 (Highest Response Ratio Next, HRRN):响应比=(等待时间+要求服务时间)/要求服务时间

      • 在SJF的基础上,弥补了长作业等待时间长的问题
  • 抢占式调度:固定时间就进行调度,防止一个进程占用太长时间。

    • 时间片轮转(Round Robin, RR):到固定时间(20ms~50ms)或阻塞就进行轮转切换

      • 缺点:时间短频繁切换效率低,时间长响应低
    • 最高优先级(Highest Priority First,HPF):RR基础上,从就绪队列中选择最高优先级的进程进行运行。也有非抢占版本。

    • 多级反馈队列(Multilevel Feedback Queue):兼顾了长短作业,同时有较好的响应时间

      • 多级:多个队列,每个队列优先级从高到低,同时优先级越高时间片越短。

      • 反馈:有新的进程加入优先级高的队列时,立刻停止当前正在运行的进程,转而去运行优先级高的队列;

      • 新进程放入一级队列,按照FCFS服务,时间片用完方下一级,以此类推。

      • 缺点:饥饿问题(“太多”交互型工作,就会不断占用CPU),用户会用一些手段欺骗调度程序,让它给予进程远超公平的资源。