操作系统知识回顾(2)--进程与线程

在操作系统中,进程和线程是极为重要的概念,这篇文章主要总结了进程、线程的基本概念及进程的调度。

1. 进程

1.1 什么是进程

进程(process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动。在传统 OS 中,进程是系统进行资源分配和调度的基本单位。进程是一个正在运行程序的实例,包括程序代码、程序计数器和寄存器的值以及系统资源(如打开的文件)等。

在某一瞬间,一个 CPU 中只能运行一个进程,它是在各个进程之间来回切换的,每个进程执行的速度也不确定。

进程和程序间的联系和区别如下:

  • 程序是一段静态的代码;进程是一个动态运行的过程;
  • 程序是产生进程的基础;进程是程序功能的体现;
  • 程序的每次执行都构成了不同的进程,通过多次运行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序;

1.2 进程的实现

为了实现进程,操作系统维护了一张进程表(结构数组),每个进程占用一个进程表项(进程控制块 PCB),它是进程存在的唯一标志。该表项包含了进程状态的重要信息,包括进程标识符、状态、优先级、程序计数器、堆栈指针、寄存器等;

对进程的管理就是对通过 PCB 的组织管理来实现的。由于保存了在进程的状态变化时的必要信息,在中断一个正在执行的进程,并在后来恢复时,就好像进程从未中断过。它是支持多进程和提供多处理的关键。

1.3 进程的状态及转换

如下图是进程的三种状态的状态图。一个进程的三种状态是:

  • 运行态:进程正在占用 CPU 执行;
  • 就绪态:进程处于准备运行状态,已经获得除 CPU 外的所有资源;
  • 阻塞态:进程由于等待某种外部事件而暂停运行,即使获得 CPU,也不能运行。

进程之间主要有四种转换关系:

  • 由运行态转换为就绪态:在时间片用完后,不得不让出 CPU
  • 由就绪态转换为运行态:进程被调度,获得处理机资源;
  • 由阻塞态转换为就绪态:进程的 I/O 请求完成;
  • 由运行态转换为阻塞态:进程发出 I/O 请求;

2. 线程

2.1 什么是线程

线程(thread)是进程中的一条执行流程。在引入线程的操作系统中,进程是拥有资源的基本单位;而线程是 CPU 调度和分派的基本单位。

一个进程中可以有多个线程,多个线程可以并发执行,它们之间共享相同的地址空间。但如果一个线程崩溃,可能会导致其所属进程的所有线程崩溃。

2.2 进程和线程的区别

  • 调度性:传统 OS 中,进程是调度和分派的基本单位,但在引入线程后,线程是调度和分派的基本单位;
  • 并发性:在引入线程后,多个进程可以并发执行,一个进程中的多个线程也可以并发执行;
  • 拥有资源:进程是拥有资源的基本单位,而线程本身并不拥有资源;
  • 系统开销:进程切换付出的系统开销明显大于线程;

2.3 线程实现的三种方式

有三种线程的实现方式:

  • 用户线程:用户空间实现,由用户线程库管理;
  • 内核线程:内核中实现,由操作系统管理;
  • 轻量级进程:内核中实现,支持用户线程;

用户线程

用户线程是把整个线程包放在用户空间中,不依赖于操作系统的内核,所以它可以在不支持线程的操作系统上实现。可以用一组用户级的线程函数库来实现线程。

每个进程都需要私有的线程表,用来跟踪记录该进程中线程的状态信息,不过仅记录每个线程的程序计数器、堆栈指针、寄存器和状态等,该线程表由运行时系统管理。而且用户线程的切换由线程库函数来完成,不需要用户态、核心态切换,所以线程调度速度特别快。另外,也允许每个进程都拥有自定义的线程调度算法。

但如果一个线程发起系统调用而阻塞,尽管其他线程可以运行,但整个进程都会阻塞。当一个线程开始运行后,除非它主动较交出 CPU,否则它所在的进程中的其他线程将无法运行。

内核线程

内核线程在操作系统的内核中实现,由内核来完成对线程的创建、终止和管理。

由于线程的创建、终止和切换通过系统调用执行,由内核完成的,其系统开销比较大;

但在一个进程中,如果某个内核线程发起系统调用而被阻塞,并不会影响其他使用内核线程的运行;

轻量级进程

轻量级进程是内核支持的用户线程。一个进程可以有一个或多个轻量级进程,每个轻量级进程由一个单独的内核线程来支持。而轻量级进程内部可以对应多个用户线程。

3. CPU 调度

3.1 调度概念

处理机调度是当有多个进程(线程)竞争 CPU 时,调度程序需要从从就绪队列中挑选下一个占用 CPU 运行的进程。

调度算法是为了解决通过什么样的准则来挑选就绪对列中的哪一个进程来执行。在每次调度时需要决定在下一个 CPU 计算时将哪个进程交给 CPU

3.2 调度算法

先来先服务算法FCFS

根据进程进入就绪态的先后顺序排列。当进程进入阻塞态或结束时,就绪队列中的下一个进程占用 CPU

实现简单,但可能短进程排在长进程后面,导致平均等待时间波动较大。

短进程优先算法SJF

选择就绪队列中执行时间最短的进程占用 CPU 运行。

  • 可抢占系统改进:短剩余时间优先算法,即选择剩余运行时间最短的进程运行。

短进程优先算法有最优的平均周转时间,但连续的短进程可能会使长进程无法获得 CPU 资源,导致饥饿;运行时间不可预估,并不可靠。

最高响应比优先算法HRN

选择就绪队列中响应比最高的进程。它是基于短进程优先算法的改进,它不允许抢占,另外等待时间越长,响应比越高,可以避免长时间地等待。

R = (w+s)/s     // 其中 w 为等待时间,s 为执行时间。
复制代码

时间片轮转算法RR

按时间片分配给进程运行。在轮转中,每个进程分到执行 1/n 的时间,时间片结束时,按先来先服务算法切换到下一个就绪进程,每隔 n-1 个时间片进程会再次执行。

如果时间片过大,进程等待时间过长,极限情况下会退化为先来先服务算法;如果时间片过小,虽然反应迅速,但上下文切换开销较大,会影响系统吞吐量。

多级反馈队列算法

就绪队列被划分为多个独立的子队列,而且每个队列可以有自己的调度策略,在队列之间可以设置优先级,第一个队列优先级最高,其余依次递减。优先级越高的队列分配的时间片越短。

在执行时,进程在不同队列间移动,如果进程在当前优先级的时间片下没有完成,则下降到低一优先级的队列,以此类推。只有当一个队列为空时才会去执行下一个队列中的进程。

这种算法对于 CPU 密集型进程的优先级下降很快,而 I/O 密集型进程停留在高优先级。

猜你喜欢

转载自juejin.im/post/5c3349246fb9a049c84f9f30