进程调度

1、中断:起到切出进程指令流的作用。中断处理程序是与进程无关的内核指令流。中断类型:

  • 硬中断:可屏蔽中断和不可屏蔽中断。高电平说明有中断请求。
  • 软中断/异常:
    • 故障:出问题,但可以恢复到当前指令,如除零错误。
    • 退出:不可恢复的严重故障,只能退出。如连续发生故障。
    • 陷阱(Trap):程序主动产生的异常。

2、Linux内核通过schedule函数实现进程调度,调用schedule函数的时候就是进程调度的时机。进程调度时机如下:

  • 用户进程通过特定的系统调用主动让出CPU;
  • 中断处理程序在内核返回用户态是进行调度;
  • 内核线程主动调用schedule函数让出CPU;
  • 中断处理程序主动调用schedule函数让出CPU。

调度策略与算法

1、 基本调度策略

  • 实时进程的调度策略(优先级0~99,静态设定)

    • SCHED_FIFO 先进先出
    • SCHED_RR 轮转策略(时间片)

      -普通进程的调度类 —— SCHED_NORMAL,只有nice值,映射到优先级为100~139。按优先级占比计算占用CPU的时间。

2、 CFS调度算法

  • 调度周期:进程越多,周期越长;上限默认8ms;一个时间周期内队列的所有进程都会至少被调度一次。

    __sched_period = nr_running(进程数)*sysctl_sched_min_granularity(默认值)
  • 理论运行时间:每次可获取CPU后最长可占用时间为ideal_runtime.

    ideal_runtime = __sched_period * 进程权重/队列运行总权重
  • 虚拟运行时间:每个进程拥有一个vruntime,每次需要调度时就运行队列中拥有最小的vruntime的进程来运行,最长运行时间为ideal_runtime.

    vruntime = 实际运行时间 * NICE_0_LOAD / 进程权重

    = 实际运行时间 * 1024 / 进程权重

    NICE_0_LOAD = 1024, 表示nice值为0的进程权重
  • 时钟中断周期:1/CONFIG_HZ秒
  • Linux传统优先级与权重的转化关系是经验值。
  • Linux采用红黑树来存储就绪进程指针,插入时根据vruntime排序,调度时选择最左边的即可。

进程的切换

为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换;

挂起正在CPU上执行的进程,与中断时保存现场是不同的,中断前后是在同一个进程上下文中,只是由用户态转向内核态执行;

进程上下文包含了进程执行需要的所有信息

  • 用户地址空间: 包括程序代码,数据,用户堆栈等
  • 控制信息 :进程描述符,内核堆栈等
  • 硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)

schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换

next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部

context_switch(rq, prev, next);//进程上下文切换

Linux操作系统架构



实验楼实验八

运行

cd LinuxKernel
rm menu -rf
git clone https://github.com/mengning/menu.git
cd menu
ls
make rootfs

启动并调试

cd..
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s gdb
file linux-3.18.6/vmlinux
target remote:1234
b schedule
b context_switch
b __switch_to
b pick_next_task

依次调试各个断点截图如下









关键代码分析

context_switch关键代码部分

static inline void context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next)
{
...
arch_start_context_switch(prev); if (unlikely(!mm)) { //如果被切换进来的进程的mm为空切换,内核线程mm为空
next->active_mm = oldmm; //将共享切换出去的进程的active_mm
atomic_inc(&oldmm->mm_count); //有一个进程共享,所有引用计数加一
enter_lazy_tlb(oldmm, next); //将per cpu变量cpu_tlbstate状态设为LAZY
} else //普通mm不为空,则调用switch_mm切换地址空间
switch_mm(oldmm, mm, next);
...
//这里切换寄存器状态和栈
switch_to(prev, next, prev);

switch_to关键代码部分

#define switch_to(prev, next, last)
do {
/*
* Context-switching clobbers all registers, so we clobber
* them explicitly, via unused output variables.
* (EAX and EBP is not listed because EBP is saved/restored
* explicitly for wchan access and EAX is the return value of
* __switch_to())
*/
unsigned long ebx, ecx, edx, esi, edi; asm volatile(
"pushfl\n\t" //保存当前进程flags
"pushl %%ebp\n\t" //当前进程堆栈基址压栈
"movl %%esp,%[prev_sp]\n\t" //保存ESP,将当前堆栈栈顶保存起来
"movl %[next_sp],%%esp\n\t" //更新ESP,将下一栈顶保存到ESP中
// 完成内核堆栈的切换
"movl $1f,%[prev_ip]\n\t" //保存当前进程的EIP
"pushl %[next_ip]\n\t" //将next进程起点压入堆栈,即next进程的栈顶为起点
__switch_canary //next_ip一般为$1f,对于新创建的子进程是ret_from_fork
"jmp __switch_to\n" //prve进程中,设置next进程堆栈,jmp与call不同,是通过寄存器传递参数(call通过堆栈),所以ret时弹出的是之前压入栈顶的next进程起点
//完成EIP的切换
"1:\t" //next进程开始执行
"popl %%ebp\n\t" //restore EBP
"popfl\n" //restore flags //输出量
: [prev_sp] "=m" (prev->thread.sp), //保存当前进程的esp
[prev_ip] "=m" (prev->thread.ip), //保存当前进仓的eip
"=a" (last), //要破坏的寄存器
"=b" (ebx), "=c" (ecx), "=d" (edx),
"=S" (esi), "=D" (edi) __switch_canary_oparam //输入量
: [next_sp] "m" (next->thread.sp), //next进程的内核堆栈栈顶地址,即esp
[next_ip] "m" (next->thread.ip), //next进程的eip // regparm parameters for __switch_to():
[prev] "a" (prev),
[next] "d" (next) __switch_canary_iparam : //重新加载段寄存器
"memory");
} while (0)

2019-2020-1 20199312 《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. PHP 23种设计模式

    学习PHP,对设计模式永远是逃不掉的:今天把php23种设计模式及其demo好好整理如下: 记录PHP关于23种设计模式的简单Demo. Demo地址:https://segmentfault.com ...

  2. [转帖]《吊打面试官》系列-Redis基础

    <吊打面试官>系列-Redis基础 https://www.cnblogs.com/aobing/archive/2019/11/07/11811194.html   你知道的越多,你不知 ...

  3. mysql中数据表记录的增删查改(1)

    数据记录的增删改查 insert into `数据表名称` (`字段名称`, ...) values ('1', ...); delete from `数据表名称` where 子句; update ...

  4. 用Python递归做个多层次的文件执行

    想用 递归实现多层次的 '.py'执行但是发现好像不能 import os def func(path): if os.path.isdir(path): for name in os.listdir ...

  5. Numpy学习笔记(上篇)

    目录 Numpy学习笔记(上篇) 一.Jupyter Notebook的基本使用 二.Jpuyter Notebook的魔法命令 1.%run 2.%timeit & %%timeit 3.% ...

  6. LOJ3146 APIO2019路灯(cdq分治+树状数组)

    每个时刻都形成若干段满足段内任意两点可达.将其视为若干正方形.则查询相当于求历史上某点被正方形包含的时刻数量.并且注意到每个时刻只有O(1)个正方形出现或消失,那么求出每个矩形的出现时间和消失时间,就 ...

  7. 缓存的设计及PHP实现LFU

    1. 恒定缓存性能有哪些因素? 命中率.缓存更新策略.缓存最大数据量. 命中率:指请求缓存次数和缓存返回正确结果次数的比例.比例越高,缓存的使用率越高,用来衡量缓存机智的好坏和效率.如果数据频繁更新, ...

  8. 支持移动端裁剪图片插件Jcrop(结合WebUploader上传)

    (此教程包括前端实现图片裁剪,后端进行获取裁剪区并保存) 最近有一个需求,微信公众号上传图片,支持自定义裁剪. 以前用过一款裁剪插件cropper,很久没用了,不知道对移动端操作兼容如何,重新从网上搜 ...

  9. 前端开发 ECMAScript-1概述

    https://www.cnblogs.com/gaoya666/p/8560745.html ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Com ...

  10. 【转载】C#中List集合SingleOrDefault和FirstOrDefault方法有何不同

    在C#的List集合类的操作过程中,有时候我们会使用到List集合的SingleOrDefault方法和FirstOrDefault等方法,这2个方法都是System.Linq.Enumerable类 ...