操作系统学习笔记6 | 进程调度

操作系统是一个复杂系统,将来还会面对很多复杂系统,希望通过对操作系统的学习,形成对复杂系统的研究和开发能力。

本部分还介绍了一个实际的调度算法,理解操作系统调度的考虑因素和实现方法。

参考资料:

1. 操作系统树

操作系统是一个复杂系统,Linux 的作者 Linus 在论坛上画了一棵树(Linux Kernel Source Tree)来描述整个 Linux 系统。

虽然名字是操作系统树,但我没有找到跟老师课件里一样的树,我觉得下面这个图还不错。不过这些结构都是在变化的,理解其结构含义即可。

操作系统学习笔记6 | 进程调度

要开发操作系统的某个模块,心中就必须要有整个源码树的图案。设计操作系统就更需要对整体有一个把握。

实现操作系统这个复杂系统不是一个一个模块堆砌而成的,而是基于简单功能不断丰富复杂得到的; 是从小树长大的过程

2. Linux 0.01 对于进程切换的实验

在 Linux 0.11 之前,Linus 最早写的是 Linux 0.01,效果就是在屏幕上交替地打出AB,这就是操作系统树最开始的那棵小树。

如何交替地打出AB呢?

  • 创建两个进程,分别循环打出A和B
    *
main(){
    if(!fork()){while(1)printf("A");}
    if(!fork()){while(1)printf("B");}
    wait();
}
  • fork 的实现:
main(){
    mov __NR_fork, %eax
    int 0x80
100:mov %eax, res
    cmpl res,0
    jne 208
200:printf("A")
    jmp 200
208: ...

304:wait()
}

简单解释一下:
操作系统学习笔记5中已经讲过,eax中存放的是返回值,如果值为1则是父进程(208位置的程序),值为0则为子进程(200位置的程序),子进程 输出 A
– int 0x80 -> sys_fork -> copy_process
+ int 指令进入内核,形成内核栈和用户栈的图像;system_call 处理中断指令,在 sys_call_table中找到 sys_fork;

操作系统学习笔记6 | 进程调度操作系统学习笔记6 | 进程调度
+ copy_process 就是在内核中根据父进程创建子进程的过程,能够实现如下的结构(右边),那么当子进程执行时,屏幕上就出现A 。操作系统学习笔记6 | 进程调度
+ 子进程创建完毕,父进程返回

希望这一点能够想明白,上面都是父进程,父进程调用了fork来创建子进程,但是 子进程还没有执行。 system_call中,从call sys_call_table返回后,会判断当前进程/线程是否阻塞,如果阻塞,就要调用reschedule,选择下一个进程并进行进程切换。
reschedule 放在中断返回后。 之前还提到过,除了判断当前进程的阻塞情况,还需要判断时间片是否用完,下面的代码中没有写。 当我们的调度算法选择到 A 这个子进程,执行后屏幕开始输出A。

操作系统学习笔记6 | 进程调度
– 类似地,用同样的过程创建 B 子进程的PCB和栈,并返回。与A进程不同的地方在于 eip 指向打印 B 的语句地址。 现在整个内核栈和用户栈的情况如下,子进程A和子进程B的 PCB 就形成了一个 就绪队列,等待主进程AB从执行态切出:操作系统学习笔记6 | 进程调度
– 父进程执行 wait(),进行等待,而等待的底层功能代码就是 将自己的状态变为阻塞,操作系统就会调用 schedule ,将其从CPU中切出,换上 两个子进程其中之一。操作系统学习笔记6 | 进程调度
– schedule 负责调度下一个进程,在这个实验中就是选择两个子进程之一,比如我们选择第一个fork 出的 A进程,接下来 switch_to。操作系统学习笔记6 | 进程调度
– switch_to 的操作就是将当前CPU的现场信息保存到AB的TSS中,将A的TSS中的信息恢复到CPU现场操作系统学习笔记6 | 进程调度
– A 进程开始执行,开始不断地打印 A操作系统学习笔记6 | 进程调度
– 现在屏幕上只能打印A,怎么才能交替打印AB呢? A进程本身不会引发阻塞,不会主动释放CPU控制权,如何切换为B进程? 思考:现在是在用户态打印A,如何在用户态打印B呢?应当进入内核把进程切换过来,如何找到B进程?需要调度schedule,schedule是内核代码,所以需要 中断进入内核。 (时钟中断)
– 时钟中断 实现 :
+ current是当前进程的PCB
+ current->counter是当前进程的剩余时间片
+ 每次时钟中断(设定),都让当前进程的 current->counter--
counter 就代表这个进程能够使用的时钟数。 其实这一点类似单片机的定时器中断。操作系统学习笔记6 | 进程调度
– 如果减到了0(如下图所示那次的时钟中断),那么就调用 schedule(),从而switch_to 到B进程打印B操作系统学习笔记6 | 进程调度 B 的 TSS 信息 载入 CPU,发生切换五段论(切换如下图)。发现其中的eip=300,就会跳转到 地址为 300 的用户态程序去执行,也就是打印出B;如上图。操作系统学习笔记6 | 进程调度
接下来不断的时钟中断,当进程B的剩余时间片为0时,就再切换为进程A,eip 指向200 打印 A
根据调度算法的不同,当然有可能还是B本身 以此类推,不断循环,那么屏幕上就交替的输出A和B

到这里,Linux 0.01 —— 简单的操作系统模型就跃然纸上了,也把前面各讲串到了一起。后续的复杂操作系统,也就是在这个模型的基础上继续增添模块和丰富完善。

3. CPU 调度策略

前文以及前面几讲反复提到了 schedule 调度算法,下面挑选其中的一种来了解一下操作系统在这方面需要考虑哪些问题,以及如何实现算法的。

操作系统的调度算法有很多,至今都还有很多人在做这方面的研究,且不同的情境下对OS的要求也不同,实时环境就要求实时性强等等。

3.1 调度的直观理解

这部分承接操作系统学习笔记4

举个例子来解释一下调度这件事:

  • 如下图,PID:1的进程阻塞了,接下来要从PID:2和PID:3的进程中挑一个,挑哪个?
  • PID:2的进程是刚刚read调用的,PID:3的进程时刚刚时间片用完了的,挑哪个比较好?操作系统学习笔记6 | 进程调度

这就 涉及 选择哪个进程的问题。CPU调度/进程调度的直观想法就是两种:

  • FIFO,先来先得,比如银行、食堂排队
  • Priority,提高某些任务的优先级,但需要考虑如何划定优先级。

3.2 调度算法的考虑

我们的调度算法衡量的标准就是 进程的满意程度,量化一点的标准就是 时间:

  • 尽快结束任务(对于每个进程来说):从任务进入到任务结束时间(周转时间)短;比如编译一个巨型程序。
  • 用户操作尽快响应:响应时间短,即从用户操作到操作系统响应时间短;比如图形化界面的显示。
  • 系统内耗时间短:吞吐量,即单位时间完成的任务量;比如执行多项任务的服务器。

调度算法如何在这些标准中间做到合理分配呢? 折中、综合

  • 吞吐量和响应时间之间是有矛盾的: 每个进程的响应时间少-> 进程间的切换次数多-> 系统内耗大 -> 吞吐量小;
  • 前台任务和后台任务的关注点不同: 前台任务关注响应时间,后台任务关注周转时间;
  • IO约束型任务和CPU约束型任务特点不同:
  • IO约束型任务:仅需要较短CPU执行时间,主要等待I/O反应;
  • CPU约束型任务:需要较长CPU执行时间;
  • 应当IO 约束型任务优先,因为IO任务执行较短时间就会释放CPU控制权,这时放上CPU约束型任务,就相当于前后两者同时进行工作。
  • 因此,前台任务(很像IO型)或许应当优先于后台任务(很像CPU型);这也考虑了用户体验。

折中和综合会让OS变得复杂,但实际上系统又要尽量简洁。下一部分会介绍一个 实际的schedule 函数,既考虑了折中,又十分简洁。

3.3 基本的调度算法

3.3.1 FCFS && SJF

FCFS,先来先服务,First Come First Served:

  • 第一种:平均周转时间 40.2
  • 第二种:平均周转时间 35
  • 数学原理 排序不等式

注意理解下图条状时刻的意思:

  • 五个任务同时到达
  • 下图标的时刻是任务被处理的时刻T
  • 所以计算任务的执行总时间要计算 T时刻到0时刻 的时间之和

操作系统学习笔记6 | 进程调度

基于排序不等式,引入第二个算法 SJF,短作业优先,这样 周转时间理论上是最小的,证明如下,p1被用到的次数最多,而其时间最短:

操作系统学习笔记6 | 进程调度

但是现实中基于有物理意义的排序,这样并不绝对最优。来看看响应时间:

  • 如果P2是前文 3.2 所说的 前台任务,需要响应时间极短,但是在上述情境下,P2要等待很长时间。
  • 基于缩小响应时间的考虑,提出下一种算法:

3.3.2 RR

RR,轮转时间片,Round Robin。

Robin 是一只鸟。

为了保证每个程序的响应时间,设置时间片(比如下图为10),每个进程时间片用完就切出。这样限制了最长响应时间不会太长(在限制进程个数的情况下)。

当然 P3 是因为 只需要3时长,提前切出。

操作系统学习笔记6 | 进程调度

但是还存在问题,即 响应时间和周转时间同时存在,上述调度算法没办法让多种类型的任务都满意

3.3.3 综合的直观想法

  • 不同类型的任务放在不同的队列中;
  • 例如分为前台任务队列和后台任务队列,前台RR,后台SJF,只有前台任务没有时才调度后台任务

操作系统学习笔记6 | 进程调度

但这种想法还是太简单,因为前台任务在不断产生,可能会引起后台任务的饥饿。所以:

3.3.4 优先级调度

轮转调度为核心,前后台都用时间片管理,在此基础上增加 优先级调度

SJF 也是一种以时间为优先级的调度、前台任务优先级高于后台任务

操作系统学习笔记6 | 进程调度

3.4 一些其他问题

上述分析其实基于很多隐含的假设,而这些假设都是问题:

  • 如何知道哪些任务是前台任务、哪些任务是后台任务?
  • 调度算法应当有一点学习机制,能够辨认任务并进行调整;
  • 有些任务横跨前后台,不纯粹是前、后台任务,比如gcc也需要交互、word也会执行批处理程序等等…

  • 算法要辨认前后台任务,还需要随着任务的实际情况变化而变化。

    这里我心动了,实在是小模型人工智能的味道。

  • SJF 中,还需要判断任务的时间长短…

操作系统学习笔记6 | 进程调度

4. 一个实际的调度函数

本来想单列,但发现课程这一讲比较短。

实际的 schedule 是多种基本算法的融合,综合考虑各种情况,也会针对当前设备和操作系统的应用场景,同时也要求算法本身尽可能的简单。

这里探讨的调度函数面向普通的PC机情境,即既有前台任务、也有后台任务;既要考虑响应时间、也要考虑周转时间……

4.1 kernel/sched.c

下面看一个实际的调度函数—— Linux0.11的调度函数,既考虑多种因素,也尽量简洁:

下图中的代码是节选,理解其主要工作原理即可。

  • 首先遍历所有的任务 i=NR_TASKS; while(i--)
  • 如果 state = TASK_RUNNING,说明是就绪态,并且通过循环赋值比较,找到就绪队列中counter 最大的任务

    这里代码是有一些问题的:

  • 源代码中在while(–i)中会有–p的过程 : if(!*--p) continue
  • 应为 *(p) -> state 再者,这里的counter 有两个含义:
  • 进程的剩余时间片
  • 进程的优先级 是的,这两个衡量标准用一个变量统一起来了,这体现了算法的简洁。
  • 如果就绪任务中最大的 counter==0,说明所有任务的时间片都用完了,就需要重置所有任务的counter,然后再重新遍历 重置的方法:
(*p)->counter=((*p)->counter>>1)+(*p)->priority;

这样重置后会让 阻塞态的counter 较大,如果阻塞态转为就绪态,其counter较大,就会被优先执行,并且其时间片也较大。
* 特殊情况:如果没有就绪任务,则遍历结束时c==-1,也会break,那这个时候next应该就是初始值task[NR_TASKS],这个任务是进程0.

操作系统学习笔记6 | 进程调度

扩展资料:

  • linux0.11《linux内核注释》 作者:赵炯

4.2 时间片设置

作为时间片的衡量,在时钟中断里需要设置 counter 自减,每中断一次就 -1,如果 =0 则进行 reschedule(). 这种设计就是基于RR的考虑。

操作系统学习笔记6 | 进程调度

4.3 优先级设置

作为优先级的衡量,通过上面的调度算法,实现了进程优先级的动态调整。

虽然这个动态调整也只是在时间片=0后按照一个式子统一调整所有的任务优先级。

  • 所有就绪任务的 counter=0,启动所有任务的重置:
  • 就绪任务的 counter=priority;
  • 阻塞任务的 counter=counter/2 + priority;
    • 注意这个机制会让等的时间越长的任务 counter 越大,其转回就绪态优先级就很高。
    • 右移 的设计效率较高。
  • 每个任务默认的priority继承父进程,linux0.11默认是15

counter 作为优先级调度, 照顾了对响应时间要求较高,且占用CPU时间较少的IO进程,那么就蕴含了 3.3 中 SJF 调度的思想。

4.4 响应时间的界 && 总结

  • counter 不断上升,不断的迭代,是一个公比为1/2的等比数列,收敛于2p;也即每个进程最长时间片为2p,还能保证轮转时间片的响应时间。
  • 总结如下图,整个算法十分简洁有效:

操作系统学习笔记6 | 进程调度

4.5 附:源码以及注释

void schedule(void)
{
         int i,next,c;
         struct task_struct ** p;

/* check alarm, wake up any interruptible tasks that have got a signal */
         for(p= &LAST_TASK ; p> &FIRST_TASK ; --p) {
             if (*p) {
                 if ((*p)->alarm &&(*p)->alarm< jiffies) {
                     (*p)->signal|= (1<alarm =0;
                 }
                 if (((*p)->signal& ~(_BLOCKABLE & (*p)->blocked))&&
                     (*p)->state==TASK_INTERRUPTIBLE)
                     (*p)->state=TASK_RUNNING;
             }
         }

/* this is the scheduler proper: */
         while (1) {
                   c = -1;
                   next = 0;
                   i = NR_TASKS;
                   p = &task[NR_TASKS];  // 是从0~NR_TASKS-1吗?那task[NR_TASKS]是什么?
                   while (--i) {  // 遍历所有的任务,从里面找出就绪且counter最大的那一个
                            if (!*--p)
                                     continue;
                            if ((*p)->state ==TASK_RUNNING && (*p)->counter> c)
                                     c = (*p)->counter, next =i;
                   }
                   // 如果c==-1,则break,所有的任务都是非就绪的?可能会出现这种情况吗?
                   // 如果c>0,则break,只要至少有一个counter>0的就绪任务,就会break,且next一定是就绪任务中counter最大的那个
                   if (c) break;
                   // 如果c=0,表示所有就绪任务的时间片都没有了,需要重置
                   for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
                        if (*p)
                            (*p)->counter= ((*p)->counter>> 1) + (*p)->priority;
                   }
         }
         switch_to(next);
}

Original: https://www.cnblogs.com/Roboduster/p/16629952.html
Author: climerecho
Title: 操作系统学习笔记6 | 进程调度

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/566559/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 地理加权回归

    地理加权回归模型实现:SAM,Arcgis,GEODA软件,R语言 1.Gauss函数法 【选择连续单调递减函数】 带宽b,就是权重与距离之间函数关系的非负衰减参数,带宽越大,权重…

    人工智能 2023年6月18日
    077
  • EasyX 图片透明设置

    屏蔽图/掩码图 :目的就是使位图背景透明。 SRCAND 目标图像 = 目标图像 AND 源图像 SRCPAINT 目标图像 = 目标图像 OR 源图像 原图:黑底彩图 屏蔽图:白…

    人工智能 2023年6月20日
    080
  • YOLOv4网络详解

    0前言 在YOLOv4论文中,作者其实就是把当年所有的常用技术罗列了一遍,然后做了一堆消融实验。 1.YOLOV4的网络改进部分 1、主干特征提取网络:DarkNet53 =&gt…

    人工智能 2023年6月20日
    090
  • 数据分析实习代码总结【进阶】Python

    import pandas as pd import numpy as np file_name0 =[r’&#x4FE1;&#x606F;&#x660E;…

    人工智能 2023年7月7日
    063
  • Unity场景优化工具:Mesh Baker 基础教程(贴图篇)

    目录 前言 一、Mash Baker是什么? 二、使用步骤 1.打开场景 2.将Texture Baker添加到场景中 3.使用Texture Baker生成贴图集 4.烘焙新的模…

    人工智能 2023年7月29日
    060
  • Pytorch创建自己的数据集(一)

    定义自己的数据集 * – 1、Dataset+DataLoader实现自定义数据集读取方法 – + * 1.1、整体框架 * 1.2、例子讲解 * 1.3、…

    人工智能 2023年7月13日
    085
  • 本人备查-学习笔记(一):环境配置

    啊哦~你想找的内容离你而去了哦 内容不存在,可能是由于以下原因造成的: [En] The content does not exist and may be caused by t…

    人工智能 2023年5月25日
    075
  • LDA中文文本挖掘代码分享

    原代码并非我原创,但我在自己的电脑上不断报错,所以加以修改补充后分享给大家,自己运行中需要注意的问题: 1、文本数据保存的时候记得要选择utf-8否则会报错 2、中文停词表自己去网…

    人工智能 2023年7月17日
    061
  • 机器学习(十五)异常检测

    Log 2022.03.10开始第十五章的学习,先开个头,看样子肯定还要花不少时间。咱家这两天成中高风险区了,不出意外的话以后要待在宿舍上网课了。2022.03.11把书本从研究院…

    人工智能 2023年6月24日
    0106
  • 【数据挖掘】频繁模式挖掘及Python实现

    1.理论背景 在美国,著名的沃尔玛超市发现啤酒与尿布总是共同出现在购物车中,于是沃尔玛超市经过分析发现许多美国年轻的父亲下班之后经常要去购买婴儿的尿布,而在购买尿布的同时,他们往往…

    人工智能 2023年6月19日
    079
  • 【NLP】Representation Learning for Natural Language Processing

    主题模型∈生成模型,一篇文章中每个词都是通过 “以一定概率选择某个主题, 并从这个主题中以一定概率选择某个词语”这样一个过程得到的。 LDA即根据给定的一篇…

    人工智能 2023年5月28日
    0140
  • 双目成像原理

    双目成像技术是利用机器视觉,通过两个相机同时同步对图片进行采集,获取左右两相机对一幅图像的对应点成像的像素差获取深度信息,进而获取三维信息,来实现对物体的重建。该技术在现有阶段只能…

    人工智能 2023年6月18日
    071
  • BP神经网络python代码详细解答(来自原文)

    翻译如下** &#xA0; &#xA0; &#xA0; &#xA0; <font color="black" size=&…

    人工智能 2023年6月23日
    0105
  • 软件危机和软件缺陷的特点和区别

    软件危机和软件缺陷的特点和区别 由于软件危机和软件缺陷存在互相促进的可能性,很多情况下较难从事故现场对两者进行一个清晰、明确的划分,从软件开发的5个阶段——需求、设计、编码、测试和…

    人工智能 2023年6月6日
    082
  • 边缘计算如何与物联网结合在一起?

    边缘计算可以使数据处理尽可能接近物联网(IoT)设备,这意味着企业IT在延迟、性能、成本、安全性等方面具有优势。 边缘计算技术如今与其他几项新兴技术齐头并进,尤其是混合云和5G。它…

    人工智能 2023年6月4日
    090
  • 【数字图像处理】实验二 图像增强(MATLAB实现)

    目录 一、实验意义及目的 二、实验内容 三、Matlab 相关函数介绍 四、算法原理 五、参考代码及扩展代码流程图 (1)参考代码流程图 (2)扩展代码流程图 六、参考代码 七、实…

    人工智能 2023年7月30日
    090
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球