-----------------------------------------------------------------------------------

理解进程调度时机跟踪分析进程调度与进程切换的过程

-----------------------------------------------------------------------------------

这次实验要理解进程调度时机跟踪分析进程调度与进程切换的过程。这是最后一次实验。我们要完毕这次实验,还是要对任务切换有一定的了解。

Linux任务切换是通过switch_to实现的。

switch_to本身是一个宏,通过利用长跳指令,当长跳指令的操作数是TSS描写叙述符的时候。就会引起CPU的任务的切换。此时,cpu将全部寄存器的状态保存到当前任务寄存器TR所指向的TSS段(当前任务的任务状态段)中,然后利用长跳指令的操作数(TSS描写叙述符)找到新任务的TSS段,然后将当中的内容填写到各个寄存器中,最后。将新任务的TSS选择符更新到TR中。这样系统就正式開始执行新切换的任务了。

有了这点补充,让我们回想一下,之前所学到的知识。

Linux系统中,一个进程的一般运行过程:

即从正在执行的用户态进程X切换到执行用户态进程Y的过程。

1)正在执行的用户态进程X

2)发生中断int 0x80

3)SAVE_ALL //保存现场

4)中断处理过程中或中断返回前调用了schedule(),当中的switch_to做了关键的进程上下文切换

5)标号1之后開始执行用户态进程Y(这里Y以前通过以上步骤被切换出去过因此能够从标号1继续执行)

6)restore_all //恢复现场

7)iret

8)继续执行用户态进程Y

可是我们都知道,这里有几个特殊情况:

通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换。与最一般的情况很类似,仅仅是内核线程执行过程中发生中断没有进程用户态和内核态的转换;

1)内核线程主动调用schedule(),仅仅有进程上下文的切换。没有发生中断上下文的切换。与最一般的情况略简略。

2)创建子进程的系统调用在子进程中的运行起点及返回用户态。如fork。

3)载入一个新的可运行程序后返回到用户态的情况,如execve。

開始实验

依据之前的知识。这次我们跟踪schedule函数来细致分析系统进行进程调度和进程切换的过程。

执行MenuOS,设置3个断点:schedule、context_switch、switch_to

执行到第一个断点处停止了,即schedule函数处停止。使用list命令查看其代码,s命令逐条分析。在这个过程中。我们要留心一下当中的执行轨迹。一会儿要分析。

    继续执行,到第二个断点处停止了,即context_switch处停下。与上同样,继续单步执行。

在这个过程中,要留心一下switch_to。





context_switch中调用了switch_to函数,这个switch_to的宏定义。我们是能够利用单步运行进入其内部观察的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

总结

switch_to从A进程切换到B进程的过程例如以下:

step1:复制两个变量到寄存器:

[prev]"a" (prev)

[next]"d" (next)

这也就是eax <== prev_A或eax<==%p(%ebp_A)

edx <== next_A 或edx<==%n(%ebp_A)

step2:保存进程A的ebp和eflags

           pushfl /*将状态寄存器eflags压栈*/

pushl %ebp

注意,由于如今esp还在A的堆栈中,所以它们是被保存到A进程的内核堆栈中。

step3:保存当前esp到A进程内核描写叙述符中:

movl%%esp, %[prev_sp]\n\t  /*save    ESP  */

这也就是prev_A->thread.sp<== esp_A

在调用switch_to时,prev是指向A进程自己的进程描写叙述符的。

step4:从next(进程B)的描写叙述符中取出之前从B切换出去时保存的esp_B。

movl %[next_sp], %%esp\n\t/* restore ESP */

这也就是esp_B <==next_A->thread.sp

注意,在A进程中的next是指向B的进程描写叙述符的。从这个时候開始,CPU当前运行的进程已经是B进程了,由于esp已经指向B的内核堆栈。可是。如今的ebp仍然指向A进程的内核堆栈,所以全部局部变量仍然是A中的局部变量,比方next实质上是%n(%ebp_A),也就是next_A,即指向B的进程描写叙述符。

step5:把标号为1的指令地址保存到A进程描写叙述符的ip域:

movl $1f, %[prev_ip]\n\t/* save    EIP  */

这也就是prev_A->thread.ip<== %1f

当A进程下次从switch_to回来时。会从这条指令開始运行。详细方法要看后面被切换回来的B的下一条指令。

step6:将返回地址保存到堆栈。然后调用switch_to()函数,switch_to()函数完毕硬件上下文切换。

pushl %[next_ip]\n\t/* restoreEIP   */

jmp switch_to\n /* regparmcall  */

注意,假设之前B也被switch_to出去过,那么[next_ip]里存的就是以下这个1f的标号,但假设进程B刚刚被创建。之前没有被switch_to出去过,那么[next_ip]里存的将是ret_ftom_fork(參看copy_thread()函数)。

当这里switch_to()返回时,将返回值prev_A又写入了%eax,这就使得在switch_to宏里面eax寄存器始终保存的是prev_A的内容,或者,更准确的说。是指向A进程描写叙述符的“指针”。

step7:从switch_to()返回后继续从1:标号后面開始运行,改动ebp到B的内核堆栈。恢复B的eflags:

popl %%ebp\n\t/* restore EBP */

popfl\n/*restore flags */

假设从switch_to()返回后从这里继续执行。那么说明在此之前B肯定被switch_to调出过,因此此前肯定备份了ebp_B和flags_B,这里执行恢复操作。

此时ebp已经指向了B的内核堆栈,所以上面的prev,next等局部变量已经不是A进程堆栈中的了,而是B进程堆栈中的(B上次被切换出去之前也有这两个变量。所以代表着B堆栈中prev、next的值了),由于prev==%p(%ebp_B),而在B上次被切换出去之前,该位置保存的是B进程的描写叙述符地址。

假设这个时候就结束switch_to的话,在后面的代码中(即context_switch()函数中switch_to之后的代码)的prev变量是指向B进程的,因此,进程B就不知道是从哪个进程切换回来。而从context_switch()中switch_to之后的代码中,我们看到finish_task_switch(this_rq(),prev)中须要知道之前是从哪个进程切换过来的,因此,我们必须想办法保存A进程的描写叙述符到B的堆栈中。这就是last的作用。

step8:将eax写入last。以在B的堆栈中保存正确的prev信息。

"=a"(last)

这也就是last_B <== %eax

而从context_switch()中看到的调用switch_to的方法是:switch_to(prev,next, prev);

所以,这里面的last实质上就是prev,因此在switch_to宏运行完之后,prev_B就是正确的A的进程描写叙述符了。这里,last的作用相当于把进程A堆栈中的A进程描写叙述符地址拷贝到了进程B的堆栈中。

至此。switch_to已经运行完毕,A停止运行。而開始运行B。此后,可能在某一次调度中。进程A得到调度,就会出现switch_to(C,A)这种调用。这时,A再次得到调度,得到调度后。A进程从context_switch()中switch_to后面的代码開始运行,这时候,它看到的prev_A将指向C的进程描写叙述符。

-------------------------------------END----------------------------------------

                     刘建鑫 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程

                     http://mooc.study.163.com/course/USTC-1000029000

-----------------------------------------------------------------------------------

理解进程调度时机跟踪分析进程调度与进程切换的过程(Linux)的更多相关文章

  1. 20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结

    week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.gi ...

  2. Linux内核分析之理解进程调度时机跟踪分析进程调度与进程切换的过程

    一.原理分析 1.调度时机 背景不同类型的进程有不同的调度需求第一种分类I/O-bond:频繁的进行I/O:通常会花费很多时间等待I/O操作的完成CPU-bound:计算密集型:需要大量的CPU时间进 ...

  3. Linux内核设计第八周学习总结 理解进程调度时机跟踪分析进程调度与进程切换的过程

    陈巧然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.视频内容 Linux ...

  4. Linux内核分析——理解进程调度时机跟踪分析进程调度与进程切换的过程

    20135125陈智威 +原创作品转载请注明出处 +<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验 ...

  5. linux内核分析第八周-理解进程调度时机跟踪分析进程调度与进程切换的过程

    实验原理: 一.调度时机 不同类型的进程有不同的调度需求 第一种分类:        I/O-bound             频繁的进行I/O            通常会花费很多时间等待I/O操 ...

  6. linux内核分析 第八周 理解进程调度时机跟踪分析进程调度与进程切换的过程

    笔记: 实验:使用gdb跟踪分析一个schedule()函数

  7. Linux内核分析实验八------理解进程调度时机跟踪分析进程调度与

    一.进程调度与进程调度的时机分析 1.不同类型的进程有不同的调度需求 Linux既支持普通的分时进程,也支持实时进程. Linux中的调度是多种调度策略和调度算法的混合. 2.调度策略:是一组规则,它 ...

  8. linux内核分析作业8:理解进程调度时机跟踪分析进程调度与进程切换的过程

    1. 实验目的 选择一个系统调用(13号系统调用time除外),系统调用列表,使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 分析汇编代码调用系统调用的工作过程,特别是参数的传递的方 ...

  9. 通过gdb跟踪进程调度分析进程切换的过程

    作者:吴乐 山东师范大学 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 本实验目的:通过gdb在lin ...

随机推荐

  1. Kibana安装及使用说明

    Kibana安装及使用说明 Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索.查看交互存储在Elasticsearch索引中的数据. 官方地址:https://www. ...

  2. C# 微信小程序获取openid sessionkey

    项目介绍 1.微信小程序获取openid和session_key 2.后台使用C#开发 项目流程 准备工作 1 获取appid 1.1 下载微信web开发工具 https://developers.w ...

  3. BZOJ5137[Usaco2017 Dec]Standing Out from the Herd

    看了半天题 不知道怎么用SAM维护 于是借(chao)鉴(xi)的一发神犇的 只要判断这个子串之前被标记的记号(也就是他属于第几个串)和这次转移到的是否相同 如果不同就说明该子串属于多个串 直接标记- ...

  4. wikioi 1294 全排列 dfs

    1294 全排列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Description 给出一个n, 请输出n的所有全排列 输入描述 Inpu ...

  5. PAT甲级1119. Pre- and Post-order Traversals

    PAT甲级1119. Pre- and Post-order Traversals 题意: 假设二叉树中的所有键都是不同的正整数.一个唯一的二进制树可以通过给定的一对后序和顺序遍历序列来确定,也可以通 ...

  6. SQLyog客户端无法连接MySQL服务器

    环境:centos下使用yum 命令安装了mysql服务 1.进入linux 通过命令service mysqld start启动mysql的服务 2.使用sqlyog 连接mysql发现连接不上,如 ...

  7. EXPLAIN 用法

    重点是第二种用法,需要深入的了解. 先看一个例子: mysql> explain select * from t_order; +----+-------------+---------+--- ...

  8. MySQL Innodb 存储引擎学习篇

    master thread的县城优先级别最高.其内部由几个循环(loop)组成:主循环(loop).后台循环(background loop).刷新循环(flush loop).暂停循环(suspen ...

  9. js 闭包范式概述

    在前几篇文章中我介绍过js的闭包,这一篇主要简单的介绍一下js中闭包的范式. 那么何谓闭包的范式呢? 首先回想一下闭包的概念,闭包是外部函数与函数内部之间通信的桥梁,通过对函数的返回,使得外部的函数能 ...

  10. ICD2 VPP limiter for new PIC microcontrollers.

    http://www.circuitsathome.com/mcu/pic_vpp_limiter VOUT = 2.5V * ( 1 + 24/10 ) = 2.5 * 3.4 = 8.5V New ...