1.问题描述

在前面的文章中,学习了译链接的过程和ELF可执行文件格式,对Linux内核装载和启动一个可执行程序,本次内容围绕对进程调度的时机和进程切换进行,分析进程的调度时机,调度策略和算法,并跟踪schedule,pick_next_task和context_switch等函数。

2.解决过程

2.1 进程调度的时机

中断:进程调度的时机与中断相关,是程序执行过程中的强制性转移,转移到操作系统内核相应的处理程序。中断在本质上都是软件或者硬件发生了某种情形而通知处理器的行为,处理器进而停止正在运行的指令流,对这些通知作出相应反应,即转去执行预定义的中断处理程序。

2.1.1 硬中断

就是CPU的两根引脚(可屏蔽中断和不可屏蔽中断)。CPU在执行每条指令后检测这两根引脚的电平,如果是高电平,说明有中断请求,CPU就会中断当前程序的执行去处理中断。

2.1.2 软中断/异常

包括除零错误、系统调用、调试断点等在CPU执行指令过程中发生的各种特殊情况统称异常。异常会导致程序无法继续执行,而跳转到CPU预设的处理函数。

2.1.3 schedule函数

Linux内核通过schedule函数实现进程调度,schedule函数在运行队列中找到一个进程,把CPU分配给它,调用schedule函数的时候就是进程调度的时机。

schedule函数调用的两种方法:主动调用和松散调用。

2.1.4 上下文

CPU所处的3种情况:

(1)运行于用户空间,执行用户进程上下文。

(2)运行于内核空间,处于进程上下文。

(3)运行于内核空间,处于中断上下文。

内核线程以进程上下文的形式运行在内核空间中,本质上还是进程,但它有调用内核代码的权限,如主动调用schedule()函数让出CPU。

2.1.5 调度时机

(1)用户进程通过特定的系统调用主动让出CPU。

(2)中断处理程序在内核返回用户态时进程调度。

(3)内核线程主动调用schedule函数让出CPU。

(4)中断处理程序主动调用schedule函数让出CPU。

2.2 调度策略与算法

调度算法就是从就绪队列中选一个进程。

调度策略:确定算法目标时追求资源利用率最高,还是追求相应最即时。

调度算法:调度策略的具体实现。

2.2.1 进程分类

根据处理对象,进程可分为I/O消耗型进程,服务器的服务进程和处理器消耗型进程;根据处理方式,也可分为交互式进程,批处理进程和实时进程。

2.2.2 调度策略

#define SCHED_NORMAL 0 //普通进程
#define SCHED_FIFO 1 //实时进程
#define SCHED_RR 2 //实时进程
#define SCHED_BATCH 3 //保留,未实现
#define SCHED_IDLE 5 //idle进程

Linux中的几种调度策略为SCHED_NORMAL,SCHED_FIFO和SCHED_RR,其中SCHED_NORMAL是用于普通进程的调度类,而SCHED_FIFO和SCHED_RR是用于实时进程的调度类,优先级高于SCHED_NORMAL。

2.2.3 CFS调度算法

CFS即为完全公平调度算法,其基本原理是基于权重的动态优先级调度算法,每个进程使用CPU的顺序由进程已使用的CPU虚拟时间决定,已用的虚拟时间越少,进程排序就越靠前,进程再次被调度执行的概率也就越高。每个进程每次占用CPU后能够执行的时间由进程的权重决定,并保证在某个时间周期内运行队列里的所有进程都能够至少被调度执行一次。

2.3 进程上下文切换

进程切换:为了控制进程的执行,内核必须有能力挂起正在CPU中运行的进程,并恢复执行以前挂起的某个进程,也称为任务切换或进程上下文切换。

进程上下文包括:用户地址空间,控制信息和硬件上下文。

进程切换的基本步骤:

(1)切换页全局目录(CR3)以安装一个新的地址空间,这样不同进程的虚拟地址如0x8048400就会经过不同的页表转换为不同的物理地址。

(2)切换内核态堆栈和硬件上下文,因为硬件上下文提供了内核执行新进程所需要的所有信息,包含CPU寄存器状态。

进程切换关键环节分析示意图如下:

2.4 schedule()函数进程调度相关代码跟踪和分析

配置MenuOS系统,重新编译内核启动:





打开gdb进行远程调试,设置schedule,context_switch和pick_next_task三个断点:



单步跟踪及对应函数代码:



在pick_next_task处停留,使用某种调度策略,选择下一个进程来切换:



在context_switch处停留,实现进程的切换:



由于switch_to内部是内嵌汇编代码,故无法跟踪调试,其实现关键的上下文切换。

3.总结

本文主要学习了进程调度的时机和进程切换进行,分析进程的调度时机,调度策略和算法,并跟踪schedule,pick_next_task和context_switch等函数。Linux系统的一般运行过程为用户态进程X发生中断,由硬件完成将当前CPU上下文压入用户态进程X的内核堆栈,加载当前进程内核堆栈相关信息,挑战到中断处理程序,即中断执行路径的起点。保存现场,在中断处理过程中或中断返回前调用schedule函数,switch_to做了进程上下文切换,之后开始运行用户态另一进程Y,恢复现场,从Y进程的内核堆栈中弹出进程X的内核堆栈相关信息,完成中断上下文的切换,继续运行用户态进程Y。

2019-2020-1 20199310《Linux内核原理与分析》第九周作业的更多相关文章

  1. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

  2. 20169219 linux内核原理与分析第二周作业

    "linux内核分析"的第一讲主要讲了计算机的体系结构,和各寄存器之间对数据的处理过程. 通用寄存器 AX:累加器 BX:基地址寄存器 CX:计数寄存器 DX:数据寄存器 BP:堆 ...

  3. 2019-2020-1 20199314 <Linux内核原理与分析>第二周作业

    1.基础学习内容 1.1 冯诺依曼体系结构 计算机由控制器.运算器.存储器.输入设备.输出设备五部分组成. 1.1.1 冯诺依曼计算机特点 (1)采用存储程序方式,指令和数据不加区别混合存储在同一个存 ...

  4. Linux内核原理与分析-第一周作业

    本科期间,学校开设过linux相关的课程,当时的学习方式主要以课堂听授为主.虽然老师也提供了相关的学习教材跟参考材料,但是整体学下来感觉收获并不是太大,现在回想起来,主要还是由于自己课下没有及时动手实 ...

  5. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  6. Linux内核原理与分析-第二周作业

    写之前回看了一遍秒速五厘米:如果

  7. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  8. 2020-2021-1 20209307 《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业> 这个作业的目标 & ...

  9. 2019-2020-1 20199329《Linux内核原理与分析》第十三周作业

    <Linux内核原理与分析>第十三周作业 一.本周内容概述 通过重现缓冲区溢出攻击来理解漏洞 二.本周学习内容 1.实验简介 注意:实验中命令在 xfce 终端中输入,前面有 $ 的内容为 ...

  10. 2019-2020-1 20199329《Linux内核原理与分析》第十二周作业

    <Linux内核原理与分析>第十二周作业 一.本周内容概述: 通过编程理解 Set-UID 的运行机制与安全问题 完成实验楼上的<SET-UID程序漏洞实验> 二.本周学习内容 ...

随机推荐

  1. MATLAB——m_map指南(1)

    1.例图 (1) clear all m_proj('oblique mercator');%确定投影方式和绘图界线 m_coast;%画出海岸线 m_grid;%添加格网 第一行代码初始化投影,对于 ...

  2. 1049 Counting Ones (30分)

    The task is simple: given any positive integer N, you are supposed to count the total number of 1's ...

  3. Linux - ubuntu下Vim安装失败,报The following packages have unmet dependencies: vim : Depends: vim-common

    错误命令行 root@ubuntu:/etc/apt# apt install vim Reading package lists... Done Building dependency tree R ...

  4. ECMAScript 6,es6 get和set的区别

    前言:ECMAScript 6是什么 一个常见的问题是,ECMAScript 和 JavaScript 到底是什么关系? 要讲清楚这个问题,需要回顾历史.1996 年 11 月,JavaScript ...

  5. CSS躬行记(4)——浮动形状

    CSS规范新增了一个模块:CSS Shapes,shape-outside属性属于该模块,它能影响浮动元素周边内容流的形状(即浮动形状),可接收三类值:形状盒子.函数和图像. 一.形状盒子 形状盒子( ...

  6. go 基础安装

    一.安装: 1.下载GO的地址:https://golang.org/dl/ 点击安装包进行安装(linux直接解压) 设置环境变量(linux) 1. export GOROOT=$PATH:/pa ...

  7. python 函数--匿名函数

    一.匿名函数的定义: 解决一些简单的需要用函数去问题,匿名函数的函数体只有一行. 二.格式: calc = lambda n:n**n 函数名   = 匿名函数  参数:返回值 三.练习:

  8. SQL基础系列(4)-性能优化建议

    10.1 连接查询表的顺序问题 SQLSERVER的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表driving table)将被最先处理,在FROM子句中包 ...

  9. Google 浏览器 离线包下载方式

    最近因工作需要,需要安装google浏览器,并且安装在系统固定目录,用360软件管理下载后发现默认安装在C:\Users\administrator\AppData\Local\Google\Chro ...

  10. BaseRuntimeException自定义业务异常类实现

    public class BaseRuntimeException extends RuntimeException { private final int code; public BaseRunt ...