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. [codevs1036]商务旅行<LCA:tarjan&倍增>

    题目链接:http://codevs.cn/problem/1036/ 今天翻箱倒柜的把这题翻出来做了,以前做的时候没怎么理解,所以今天来重做一下 这题是一个LCA裸题,基本上就把另一道裸题小机房的树 ...

  2. [poj1061]青蛙的约会<扩展欧几里得>

    题目链接:http://poj.org/problem?id=1061 其实欧几里得我一直都知道,只是扩展欧几里得有点蒙,所以写了一道扩展欧几里得裸题. 欧几里得算法就是辗转相除法,求两个数的最大公约 ...

  3. 2019级第一次月赛暨ACM工作室第一次招新赛、补题赛

    A:最简单签到,没有之一 Description 此题简单如题意,就是求最大值 Input 多组输入 每组输入输入一串字符串(包括字母和数字),长度小于500 Output 每行输出字符ASCII值与 ...

  4. ArrayList 迭代器学习笔记

    我们先来看一段代码: List<String> list = new ArrayList<>(); list.add("str1"); list.add(& ...

  5. Maven多模块项目+MVC框架+AJAX技术+layui分页对数据库增删改查实例

    昨天刚入门Maven多模块项目,所以简单写了一个小测试,就是对数据库单表的增删改查,例子比较综合,写得哪里不妥还望大神赐教,感谢! 首先看一下项目结构: 可以看到,一个项目MavenEmployee里 ...

  6. Docker的简介以及Dockerfile编写与使用

    Docker的简介 Docker是在容器的基础上,进行了进一步的封装,极大的简化了容器的创建和维护.使得Docker技术比虚拟机技术更为轻便.快捷. 下面是两张对比图. 可以看到传统虚拟机技术是虚拟出 ...

  7. python3.6 ubuntu部署nginx、 uwsgi、 django

    ubuntu部署nginx. uwsgi. django 将项目上传到服务器 python manager.py runserver 0:80 在浏览器输入服务器的域名或者ip地址,访问成功. 安装u ...

  8. CSS 布局水平 & 垂直对齐

    元素居中对齐 margin: auto; 文本居中对齐 text-align: center; 图片居中对齐 要让图片居中对齐, 可以使用 margin: auto; 并将它放到 块 元素中 左右对齐 ...

  9. Python爬虫系列(七):提高解析效率

    如果仅仅因为想要查找文档中的<a>标签而将整片文档进行解析,实在是浪费内存和时间.最快的方法是从一开始就把<a>标签以外的东西都忽略掉. SoupStrainer 类可以定义文 ...

  10. HttpClient之Get请求和Post请求示例

    HttpClient之Get请求和Post请求示例 博客分类: Java综合   HttpClient的支持在HTTP/1.1规范中定义的所有的HTTP方法:GET, HEAD, POST, PUT, ...