朱宇轲 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

这次我们来分析Linux中进程调度和切换的原理。

关于Linux的进程调度,有很多相关的算法,比如先进先出、最短作业优先等,这个不是我们讨论的重点,对此有兴趣的同学可以翻阅《现代操作系统》中的第二章来对其进行深入的了解。

在Linux中,进程的切换主要是通过调用schedule函数来实现的,shedule调用的时机为:

  • 中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();

  • 内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
  • 用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。

也就是说,进程的切换主要是在中断处理过程中实现,此时是被动调度,一般的用户态进程走的都是这条路子;而对于内核线程来说,它可以在执行的过程中直接调用shedule函数,进行主动调度。

进程的切换需要挂起一个进程,然后保存当前进程相关的上下文,之后进入新的进程,当回到之前的进程时再重新载入之前的上下文。这和中断的保存变量是不一样的:中断是发生在同一个进程之中,只不过由用户态进入了内核态,而进程切换是两个进程之间的变换,需要保存更多的信息。

需要保存的进程上下文为:

  • 用户地址空间:包括程序代码,数据,用户堆栈等

  • 控制信息:进程描述符,内核堆栈等

  • 硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)

接下来我们来简要分析一下shedule函数。

进入函数中,可以看到这么一句:

next = pick_next_task(rq, prev);

这就是Linux中执行进程调度的函数,具体的细节予以封装,我们也不细深究。

context_switch(rq, prev, next);

这一句就是执行所谓的进程上下文切换,进入里面。

switch_to(prev, next, prev);

该函数执行了具体的切换操作,它的代码如下:

"pushfl\n\t"		/* save    flags */	\
"pushl %%ebp\n\t" /* save EBP */ \
"movl %%esp,%[prev_sp]\n\t" /* save ESP */ \
"movl %[next_sp],%%esp\n\t" /* restore ESP */ \
"movl $1f,%[prev_ip]\n\t" /* save EIP */ \
"pushl %[next_ip]\n\t" /* restore EIP */ \
__switch_canary \
"jmp __switch_to\n" /* regparm call */ \
"1:\t" \
"popl %%ebp\n\t" /* restore EBP */ \
"popfl\n" /* restore flags */

prev_sp、next_sp、prev_ip、next_ip是输入和输出参数,分别表示当前进程和下一个进程的ip与sp。

这段代码其实应该也不是很难理解,就是将内核堆栈的ebp压栈,然后将next进程的sp放入内核堆栈的esp中,同时将变换前的esp保存到prev进程的sp中。之后将1处的代码段放入prev中,并将next的ip压栈。

在这里需要注意的是,之后的jmp _switch_to会执行ret操作,此时就会出栈,将next的ip放入EIP里,接下来就会执行next进程的代码了。

而通过movl $1f,%[prev_ip]语句,当我们再次回到prev进程的时候,就会执行代码段1之后的语句,返回之前存储的上下文(EBP、FLAGS等),重新执行prev进程。

Linux的进程切换基本就是如此,下面是本次实验的截图:

今天就讲到这里,谢谢大家。

Linux进程切换代码分析的更多相关文章

  1. ARM Linux 大小核切换 ——cortex-A7 big.LITTLE 大小核 切换代码分析

    ARM Linux 大小核切换——cortex-A7 big.LITTLE 大小切换代码分析 8核CPU或者是更多核的处理器,这些CPU有可能不完全对称.有的是4个A15和4个A7,或者是4个A57和 ...

  2. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  3. Linux进程内存用量分析之堆内存篇

    https://mp.weixin.qq.com/s/a6mLMDinYQGUSaOsGYCEaA 独家|Linux进程内存用量分析之堆内存篇 姬晨烜 58技术 2019-12-06 导语 本文将介绍 ...

  4. Linux进程资源占用分析

    [时间:2018-03] [状态:Open] [关键词:linux, 进程,proc,top] 0 引言 最近在分析安卓程序上的monkey测试日志时发现,需要了解下Linux进程资源占用情况及其查看 ...

  5. Linux中断 - GIC代码分析

    一.前言 GIC(Generic Interrupt Controller)是ARM公司提供的一个通用的中断控制器,其architecture specification目前有四个版本,V1-V4(V ...

  6. Linux进程管理子系统分析【转】

    本文转载自:http://blog.csdn.net/coding__madman/article/details/51298732 Linux进程管理: 进程与程序: 程序:存放在磁盘上的一系列代码 ...

  7. linux进程切换问题

    #define switch_to(prev,next,last) do { \ unsigned long esi,edi; \ asm volatile("pushfl\n\t" ...

  8. Linux - 进程控制 代码(C)

    进程控制 代码(C) 本文地址:http://blog.csdn.net/caroline_wendy 输出进程ID.getpid(). 代码: /*By C.L.Wang * Eclipse CDT ...

  9. linux系统调用实现代码分析【转】

    转自:http://linux.chinaunix.net/doc/kernel/2001-07-30/637.shtml 启动早就读完,现在为了写笔记再从启动之后粗略的大体读一遍,基本就是几个大模块 ...

随机推荐

  1. UOJ Test Round 1

    第一题: 题目大意: 给出N个字符串,字符串的前面部分都是字母且都是一样的,后面部分是数字,按照后面的数字排序.N<=10000 解题过程: 1.第一题是真良心,一开始的做法是把后面的数字分离出 ...

  2. C#面向对象总结1

    1.面向过程-----> 面向对象 面向过程:面向的是完成这件事的过程,强调的是完成这件事的动作. 面向对象:找个对象帮你做事. 意在写出一个通用的代码,屏蔽差异. 我们在代码中描述一个对象,一 ...

  3. jboss入门学习1

    环境准备 win8 jdk1.6 jboss4.0.5 oracle10g 修改jboss默认端口 server/default/conf/jboss-service.xml 1.WebService ...

  4. Oracle数据库高效sql语句的整理

    业务需求说明:由于之前公司后台APP端有一个document表,该表中包含了所有的信息,新的需求就是通过该表创建出一个新的用户表(usertable)和一个档案表(document,该表只保留原doc ...

  5. 二分查找C++

    #include <iostream> using namespace std; //二分查找:每次都从中间位置寻找,如果找到了就返回,如果没找到, //则分两种情况: //(1)中间元素 ...

  6. cocos2dx 3.8版关于#include "GB2ShapeCache-x.h"

    关于coco2d-x 3.8版的PhysicsEditor.exe1.09版的GB2ShapeCache-x.h.cpp中有些方法更新了和容器的使用方法,还有就是头文件include "CC ...

  7. linux信号处理时机

    信号号称所谓软中断,事实上,还是没有真正的硬件中断那样能随时改变cpu的执行流 硬件中断之所以能一发生就得到处理是因为处理器在每个指令周期的结尾都会去检查中断,这种粒度是很细的 但是信号的实现只是在进 ...

  8. iOS-----类和对象,nil/Nil/NULL的区别

    iOS中类和对象,nil/Nil/NULL的区别 类与对象的概念 类是对同一类事物高度的抽象,类中定义了这一类对象所应具有的静态属性(属性)和动态属性(方法). 对象是类的一个实例,是一个具体的事物. ...

  9. D - Half of and a Half 大数

    D - Half of and a Half Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I ...

  10. IOS UIImagePickerController 保存图片到 相册

    // 异步下载图片 dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0); disp ...