进程基本概念与常见调度 - 进程与线程(二)

操作系统最核心概念是进程,进程是一个应用程序运行时刻的实例(从进程的结构看);进程是应用程序运行时所需资源的容器(从进程的功能看);甚至进程是一堆数据结构(从操作系统对进程实现的角度来说)。进程,而它又非常依赖于内存管理、中断、硬件体系结构。文章主要解决如下几个问题:

  • 为什么要引入进程的概念以及如何解决问题
  • 进程的概念,进程和程序的联系和区别
  • 进程控制块
  • 进程的状态模型

1. 为什么要引入进程

早期的计算机一次只能执行一个任务,采用批处理的方法,由监督系统完成作业的切换,使得作业一个接一个的被处理,如下图所示

在这里插入图片描述

首先,由监督器将磁带上的第一个程序装入内存,并把运行的控制权交给作业。当该作业批处理完成时,又把控制权交还给监督程序,再由监督程序把磁带上的第二个作业调入内存,计算机系统就这样自动地一个任务有一个任务的进行处理,直到将磁带上的所有作业全部完成。对于该批处理系统内存中仅有一道程序运行,即每次监督器只能从磁带上调入一道程序进入内存中运行,当该程序完成或发生异常时,才换入其他后续程序进入内存运行,这就是早期的批处理系统。但是随着计算机的发展趋势,这种已经不能满足越来越复杂的场景需求。

计算机程序种类越来越多(文本编辑、科学计算、web服务…),外部设备种类越来越多(磁盘、显示、网络),造成程序等待。就会出现以下的情况

在这里插入图片描述
我们以实际的例子,来说明这种情况下的弊端

在这里插入图片描述
对于上面的程序A和程序B,如果在单道程序设计中,需要80个时间周期才能执行完,而采用多道程序设计,A程序等待的时候,B程序可以调度执行,相同的操作只需要45个时间周期就能完成,其效率如下所示

单道程序多道程序
CPU利用率40/80=50% 40/45=89%
DEV1利用率15/80=18.75%  15/45=33%
DEV2利用率25/80=31.25%25/45=56%

所以,对于这种批处理系统, 每次上机时, 我和其他程序都排好队, 一个接一个的进入内存运行。但是这种效率低下,为了创建和谐社会,促进效率和公平, 充分发挥每一个人的能力,所以就引入了多道程序设计的概念。主要是为了提高CPU利用率,人们设计了在一台计算机实现能将多个程序同时加载、并发执行,从而引入进程的概念。每个加载到内存中的程序都称为进程,操作系统管理者多个进程并发执行。进程会认为自己独立占用CPU资源

2. 进程的概念

2.1 进程的定义

进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。其如下图所示

在这里插入图片描述

由上图可以知道,进程包含了正在运行的一个程序的所有的状态的信息,其主要包括以下

  • 代码
  • 数据
  • 状态寄存器,例如CPU的状态,栈指针,PC指针等
  • 通用寄存器
  • 进程占用系统资源,打开文件,已分配的内存信息等

2.2 进程的特点

  • 动态性 - 可以动态创建、结束进程
  • 并发性 - 进程可以被独立调度并占用处理器运行
  • 独立性 - 不同进程的工作不相互影响
  • 制约性 - 因访问共享数据/资源或进程间同步而产生制约

在这里插入图片描述

2.3 进程与程序的联系

  • 程序 = 文件 (静态的可执行文件)
  • 进程 = 执行中的程序 = 程序 + 执行状态

进程是操作系统处于执行状态程序的抽象。同一程序的多次执行过程对应为不同的进程,如命令ls的多次执行对应多个进程,进程执行是需要资源。内存:保护代码和数据,CPU:执行指令

2.4 进程与程序的区别

进程是动态的,程序是静态的
程序是有序代码的集合
进程是程序的执行,进程有核心态和用户态
进程是暂时的,程序是永久的
进程是一个状态变化的过程
程序可长久保存
进程与程序的组成不同
进程的组成包括程序、数据和进程控制块

3. 进程实现 - 控制块(PCB)

进程是操作系统中调度的一个实体,需要对进程所拥有的资源进行抽象,这个抽象的形式就是进程控制块(PCB),主要是用来管理控制进程运行所用的信息集合。其包含进程三类核心信息:进程管理信息、存储管理信息和文件管理信息。

操作系统用PCB来描述进程的基本情况以及运行变化的过程。PCB是进程存在的唯一标志,每个进程都在操作系统中一个对应的PCB,对于进程控制块需要描述以下信息:

  • 进程的运行状态:包括就绪、运行、等待阻塞、僵尸等状态
  • 程序计数器:记录当前进程运行到哪条指令
  • CPU寄存器:主要用于保存当前运行的上下文,记录CPU所有必须保存下来的寄存器信息,以便当前进程调度出去之后还能调度回来并接着运行
  • CPU调度信息:包括进程优先级、调度队列和调度等相关信息
  • 内存管理信息:进程使用的内存信息,如进程的页表等
  • 统计信息:包含进程运行时间等相关统计信息
  • 文件相关信息:包括进程打开的文件等

因此,进程描述符是用于描述进程运行状态以及控制进程运行所需要的全部信息,是操作系统用来感知进程存在的一个非常重要的数据结构。任何一个操作系统的实现都需要一个数据结构来描述进程描述符,所以linux内核采用一个名为task_struct的结构体,该内容后面详细学习。

进程主要是通过中断或者系统调用进入内核,上下文保存在对应的PCB中,被调度时,从PCB取出上下文并恢复进程。对于进程的上下文切换,如下图所示:

在这里插入图片描述

4. 进程的状态与转换(经典5态模型)

一个进程的生命周期可以划分为一组状态,这些状态刻画了整个进程。进程状态即体现一个进程的生命状态。进程的整个生命周期如下:

在这里插入图片描述

4.1 进程创建

在linux系统中,许多进程在诞生之初都与其父进程共同用一个存储空间。但是子进程又可以建立自己的存储空间,并与父进程“分道扬镳”,成为与父进程一样真正意义上的进程。

linux系统运行的第一个进程是在初始化阶段“捏造出来的”。而此后的线程或进程都是由一个已存在的进程像细胞分裂一样通过系统调用复制出来的,称为“fork()”或者“clone()”引起进程创建的情况

  • 系统初始化创建,例如第一个进程
  • 用户请求创建一个新进程
  • 正常运行的进程执行创建进程的系统调用

4.2 进程执行

进程的创建解决了从无到有的过程,而当进程创建后,就处于就绪状态,进程具备运行条件,等待系统分配处理器以便运行。

而进程的执行是内核选择一个就绪的进程,让它占用处理器并执行,主要是从就绪状态切换到运行态的过程,但是这里面涉及到如何选择哪个就绪队列,采用何种算法,这个后面会单独学习

4.3 进程等待

指进程不具备运行条件,正在等待某个事件的完成,此时进程进入等待(阻塞)的状态,其有如下情况

  • 请求并等待系统服务,无法马上完成
  • 启动某些操作,无法马上完成
  • 需要的数据没有到达

只有进程自身才知道何时需要等待某种事情的发生,该过程只能发生在运行态到等待态的。Linux等待过程中分为深度睡眠和浅睡眠,深度睡眠是无法响应信号的,只能等待资源满足了将其唤醒。出现深度睡眠情景是不需要相应信号,比方说磁盘代码读取。在代码读取过程中,不能再读其他的代码资源,否则会造成嵌套睡眠。一般情况下都是使用浅睡眠,深度睡眠实例比较少。

4.4 进程抢占

无论进程当前运行在内核态还是用户态,都可以发生抢占,被抢占的进程仍然运行在TASK_RUNNING状态。进程抢占可能发生在两种情况下:

  • 更高优先级的任务进入TASK_RUNNING状态
  • 当前进程的时间片到期

4.5 进程唤醒

  • 被阻塞进程需要的资源可以满足
  • 被阻塞进程等待的事件到达
  • 进程只能被别的进程或操作系统唤醒

4.6 进程结束

  • 正常退出(自愿的)
  • 错误退出(自愿的)
  • 致命错误退出(强制性的)
  • 被其他进程所杀(强制性的)

我们来看看sleep系统调用对应的进程状态的变化情况,如下图

在这里插入图片描述

首先,创建sleep进程,进程处于就绪状态,等待操作系统调度
当操作系统从就绪态开始执行该进程,就处于运行态
运行态去等待time硬件时间到,系统马上就切换到等待态,并切换到另外的进程运行
当硬件时间到后,该进程马上就回到就绪,等待操作系统运行
当再次运行完毕后,该进程就退出
我们来实现看看进程切换的完成状态图,如下图示

在这里插入图片描述

4.8. 进程挂起模型

每次执行中的进程必须完全载入内存中,因此所以队列中的所有进程必须驻留在内存中。内存中保存多个进程,当一个进程正在等待,处理器可以转移到另外一个进程,但是CPU比I/O要快很多,以至于内存中所有进程都在等待I/O的情况就显得很常见。那么我们该如何处理这种问题呢?

该问题产生的直接原因是内存问题,那么最直接的方法是扩充内存适应更多的进程。另外一种方式,是虚拟内存技术的方式,采用交换,把内存中某个进程的一部分或者全部移到磁盘中。当内存中没有处于就绪状态的进程时,操作系统就把阻塞的进程换到磁盘中的“挂起队列”中。

在这里插入图片描述
不同于进程阻塞。挂起时没有占用该内存空间,而是映像在磁盘上,主要是减小进程占用内存。类似虚存中,有的程序段被放到了硬盘上。

  • 等待挂起状态:该状态是由等待状态切换,进程在外出中并等待某事件的出现
  • 就绪挂起状态:进程在外存中,但只要进入内存,即可运行

7. 小结

本章主要是学习了操作系统为何要引入进程这个概念,为了提高CPU利用率。多批道处理系统一次性载入多个作业到内存中让程序并发执行,但这会造成一系列的问题,引入进程这些问题得以解决,同时也学习了进程的相关的概念。但是随着人们需求越来越多,对于并发的要求越来越高,单纯的进程已经不能满足于日常的需求,此时就导致线程的概念的产生。

进程常见调度

进程调度的概念比较简单,我们假设在一个单核处理器的系统中,同一时刻只有一个进程可以拥有处理器资源,那么其他的进程只能在就绪队列中等待,等到处理器空闲之后才有计划获得处理器资源来运行。在这种场景下,操作系统就需要从众多的就绪进程中选择一个最合适的进程来运行,这个就是调度器需要做的事情。linux内核管理过程中是按照线程完成调度工作,与线程所属进程基本上没有什么关系。

1. 调度简介

在计算机开始的初期调度算法非常简单,多道程序按照顺序方式进行执行,管理过程只需要做好基本的输入和输出管理即可。但是,现代社会计算机CPU速度非常快,输入输出已经限制了程序的运行。当前运行的进程基本上划分为I/O请求信和CPU密集型,随着时代的发展,实际计算机越来越偏向于I/O请求型计算机发展,CPU密集型逐渐用外部基本的IC替代其复杂的计算工作。

1.1. 调度情况

通常来说,操作系统是应用程序和可用资源直接的媒体,CPU是一个重要的资源,调度器可以临时分配一个任务在CPU上执行。为了使各个进程间可以公平共享CPU时间,而同时又要考虑不同的任务优先级,所以就需要一个调度器,来保证以下功能有效的分配CPU时间片,根据用户的目标来提供一个很好的用户体验。当面对一些互相冲突的目标的时候,提供一个最优化的调度算法,例如既要为关键实时任务最小响应时间,又要最大限度的提高CPU的总体利用率。知道了进程的分类,那就可以知道哪些场景需要调度来协调,如IO消耗性的,例如磁盘,打印机,网络等场景。调度在不同场景下的目标有。

我们以生活中为例,来看看调度器对我们实际生活的影响,以我们手机上的一个场景为例。如我们手机上运行一个机器学习的程序,大约CPU需要运行30分钟,我们也需要播放音乐。如果没有调度器:

在这里插入图片描述

对于手机上运行的学习进程和播放进程,学习进程属于批处理进程,而播放音乐属于实时进程,如果整体播放延时比较大就会出现卡顿的情况,用户体验就会很差。如果没有调度器,对于用户就需要30分钟才能播放音乐,那么它可能等不到30分就会抛弃这个手机。

如果有调度器:调度器让生活更美好

在这里插入图片描述

调度器“任性化”将程序切片执行,对于用户就可以边听音乐边等待他的程序运行完,能够完美的实现二者的兼容。

1.2. 调度行为与何时调度

如果站在CPU的角度来看进程,有些进程一直占用处理器,有些进程只需要一部分处理器资源即可。所以进程按照这个特性可以分为两类

  1. CPU消耗型:CPU消耗型的进程会把大部分的时间用在运行代码上,并且会一直占用CPU。一个常见的例子就是while循环的运行,如运行大量计算的程序等。
  2. IO消耗性:IO消耗性的进程会把大部分的时间用在提交I/O请求或等待I/O请求,所以这类的进程通常只需要很少的处理器计算资源即可,如需要键盘的输入进程或等待网路I/O的进程。

存在调度的基本情况类型如下:

  1. 在创建子进程以后,父进程与子进程执行顺序需要调度
  2. 一个进程退出时需要确定调度
  3. 当一个进程阻塞在I/O和信号量上时,需要调度其他进程进入执行
  4. 当I/O中断发生时,必须做出调度决策

1.3. 调度算法分类

不同环境或者领域需要实现目标不同,需要不同的调度算法方向也是不一样的。具体可以划分成三种类型,分别是交互式、批处理、实时。其特征如下:

  1. 交互式进程: 与人机交互的进程,例如鼠标、键盘、触摸屏等相关的应用,这类进程的特点是系统响应时间越短越好,否则用户就会抱怨系统卡顿。一般个人PC和掌上设备属于这种类型。
  2. 批处理进程: 此类进程默默运行,可能会占用比较多的系统资源,对响应时间没有确定的要求。网络处理器和数据流水处理都属于这种类型。
  3. 实时进程: 有些应用对整体时延有严格的要求,如VR设备,从头部转动到画面显示的间隔时间有明确的要求,否则人的体验不是太好;同时例如工业控制系统,不符合时延可能会导致严重的事故。工厂中RTOS系统属于这种类型。

1.4. 调度器目标

针对不同的目标环境,设计调度算法的侧重点也是不一样的。当然,多有系统都会有如下几项的公共特点:

  • 公平 - 给每个进程公平的CPU份额
  • 策略强制执行 - 保证规定的策略被执行
  • 平衡 - 保存系统的所有部分都忙碌
  • 低功耗 - 对于目前的移动设备,如何设计一个更优的调度算法,来保证系统的低功耗也需要重点

对于批量处理系统

  • 吞吐量 - 每小时最大的作业数。最大系统利用率(高吞吐量),对于一些批处理系统中需要考虑
  • 周转时间 - 从提交到中止的最小时间

对于交互式系统

  • 响应时间 - 快速响应请求。此类进程经常与用户进行交互, 因此需要花费很多时间等待键盘和鼠标操作. 当接受了用户的输入后, 进程必须很快被唤醒, 否则用户会感觉系统反应迟钝,主要用于一些交互式系统需要重点考虑
  • 均衡性 - 满足用户的期望

实时系统

  • 满足截至时间 - 避免丢失数据。这些进程由很强的调度需要, 这样的进程绝不会被低优先级的进程阻塞. 并且他们的响应时间要尽可能的短
  • 可预测性 - 在多媒体系统中避免品质降低

确定如何从就绪队列中选择下一个执行的进程进入调度,需要解决以下问题。如何挑选就绪队列中的哪一个进程,通过什么样的调度准则来选择。调度算法的要求,希望得到**“更快”**服务,那么如何定义什么是更快呢?根据调度器的目标,其可以重点关注:

高吞吐量:传输文件时的高带宽
低响应延时:玩游戏时的低延迟
调度器的响应目标考虑:

减小响应时间:及时处理用户的输入请求,尽快将输出反馈给用户
减小平均响应的时间波动:在交互系统中,可预测性比高差异低平均更重要
低延迟调度改善了用户的交互体验:如果移动鼠标时,屏幕中的光标没动,那么客户会如何做呢?会不会重启
处理器调度吞吐 量目标考虑

增加吞吐量:减小开销,主要是上下文切换的开销,系统资源的高利用(CPU /IO设备)
减小等待时间:减小每个进程的等待时间
处理器公平的定义:

2. 交互式系统中的调度

3.1 先来先服务算法(First Come First Served, FCFS)

每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行。

依据进程进入就绪队列的先后顺序排列,进程进入等待或者结束状态时,就绪队列中的下一个进程占用CPU,3个进程,计算时间分别为12,3,3,FCFS算法的周转时间,根据任务到达的顺序不同,周转时间不同

在这里插入图片描述

结合大家学习中,遇到的实际例子,我们来学习下整个过程,例如该过程中,调度器是我们生活中遇到的学霸,而此时有3个同学想学霸请教问题,其思路如下

在这里插入图片描述

该问题对于C同学来说,有一个很大的问题是,我的问题很简单,却需要等那么长的时间,所以对于该算法的特征如下:

优点缺点
简单 1. 平均等待时间波动较大,短进程可能排到长进程后面
2. IO资源和CPU资源的利用率较低,对于上面的例子,如果该同学需要查阅相关文档,那么学霸就需要一直等待,浪费学霸的资源

3.2 短进程优先算法(SPN)

它会优先选择运行时间最短的进程来运行,这有助于提高系统的吞吐量。

选择就绪队列中执行时间最短进程占用CPU进入运行状态,就绪队列按预期的执行时间来排序

在这里插入图片描述

进程的平均周转时间为:

在这里插入图片描述

还是基于刚才学霸解决问题的实例来看看这个算法的执行顺序,首先A同学先执行,当执行到2后,同学B和C都来寻求学霸解决问题,但是此时A占用了学霸,所以当A解决完问题后,发现同学C问题简单,所以就优先解决C的问题

在这里插入图片描述

优点缺点
平均周转时间较短1. 不公平,可能出现导致饥饿,连续的短进程流会使得长进程长时间无法获得CPU资源
2. 平均响应时间过长
3. 需要预知未来,需要解决预估下一个CPU计算的持续时间

2.3 时间片轮转算法(RR, Round-Robin)

定义:每个进程被分配一个时间段,称为时间片(*Quantum*),即允许该进程在该时间段中运行。如果时间片用完,进程还在运行,那么将会把此进程从 CPU 释放出来,并把 CPU 分配另外一个进程;如果该进程在时间片结束前阻塞或结束,则 CPU 立即进行切换;
通过时间片,分配处理器资源的基本单元,当时间片结束后,按FCFS算法切换到下一个就绪进程,我们还是以刚才例子为例,此时为

在这里插入图片描述

但是这种算法也需要重点考虑时间片长度,因为切换进程,需要有额外的上下文切换

时间片太长

  • 等待时间过长
  • 极限情况下退化成FCFS

时间片太短

  • 反应迅速,但产生大量的上下文切换
  • 大量上下文切换开销会影响系统的吞吐量

时间片长度选择目标

  • 选择一个合适的时间片长度
  • 经验规律:维持上下文切换开销处于1%以内

3. 调度优先级

对于操作系统中的任务是不同的,例如,系统进程和用户进程、前台进程和后台进程,如果不加以区分,那么系统中关键的任务无法及时处理,后台运算导致视频播放卡顿,所以基于此,重要的任务需要被优先调度,就产生了优先级的概念。

3.4.1 多队列调度算法(MQ)

对于该调度算法,就绪队列被划分成多个独立的子队列,如前台(交互)、后台(批处理),每个队列拥有自己的调度策略,如前台-RR,后台-FCFS,队列间的调度

**固定优先级:**先处理前台,后处理后台,可能导致饥饿
**时间片轮转:**每个队列读的到一个确定的能够调度器进程的总时间,如80%CPU时间用于前台,20%CPU时间用于后台

在这里插入图片描述
还是以学霸解决问题为例,基于此的算法为:

在这里插入图片描述

所以该算法特征为:

维护多个优先级队列
高优先级的任务优先执行
同优先级内使用Round Robin调度

3.4.2 公平共享调度(FSS, Fair Share Scheduling)

公平共享调度控制用户对系统资源的访问

一些用户组比其他用户组更重要
保证不重要的组无法垄断资源
未使用的资源按比例分配
没有达到资源使用率目标的组获得更高的优先级

4 调度算法总结

算法 优点缺点
先来先服务算法简单不公平,平均等待时间较差
短进程优先算法平均周转时间最小

1. 不公平,可能导致饥饿

2. 需要精确预测计算时间

时间片轮转算法公平平均等待时间较差
公平共享调度公平是第一要素
多队列调度算法多种算法的集成 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
进程线程是操作系统中的两个基本概念,它们都是用来执行程序的执行单元,但在一些方面有着明显的区别。 1. 进程(Process): - 进程是程序在执行过程中的一个实例。 - 每个进程都有自己的独立内存空间,包括代码段、数据段和堆栈段。 - 进程之间相互独立,拥有各自的资源,通信需要通过进程间通信(IPC)机制。 - 进程拥有自己的进程控制块(PCB),用于描述进程的状态、资源和调度信息。 2. 线程(Thread): - 线程进程中的一个执行单元。 - 多个线程可以共享同一个进程的内存空间,包括代码段、数据段和堆栈段。 - 线程之间共享进程的资源,如打开的文件、信号处理等。 - 线程线程控制块(TCB)来描述,每个线程有自己的栈和寄存器上下文。 区别: 1. 资源占用:每个进程都有独立的内存空间和系统资源,而线程共享进程的资源。 2. 创建销毁开销:创建或销毁进程线程开销大,因为进程需要分配独立的内存空间和系统资源,而线程只需要创建线程控制块。 3. 切换开销:进程切换的开销较大,需要保存和恢复整个进程的上下文,而线程切换只需要保存和恢复线程的上下文。 4. 通信和同步:进程间通信需要使用进程间通信机制,如管道、消息队列等。线程间通信和同步相对容易,可以使用共享内存、信号量、互斥量等机制。 总结: 进程线程都是用于执行程序的执行单元,但进程是资源分配的基本单位,线程是CPU调度的基本单位。多线程比多进程更轻量级,线程之间的切换开销更小,但进程之间相互独立,安全性更高。在实际应用中,需要根据具体需求选择使用进程还是线程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值