为了控制进程的执行,linux内核必须有能力挂起正在cpu上运行的进程,换入想要切换的进程,也就是恢复以前某个挂起的进程,这就是linux的进程切换。
 1进程切换的时机


一般来说,进程切换都是发生在从中断或者系统调用返回用户态的时候,最常见的是时钟中断。在允许内核抢占的情况下,系统调用被中断打断也有可能会引发进程切换。中断处理和系统调用处理都发生在内核态,所以进程之间的切换实际上也是发生在了内核态。

2进程切换做的工作


2.1切换页全局目录以安装一个新的地址空间。


2.2切换内核态堆栈和硬件上下文,硬件上下文提供了新进程运行所需要的所有的寄存器的所有信息。

3进程切换的过程


进程切换统一发生在schedule()函数中,在这个里面我们仅仅先来关注切换的过程,在内核代码中切换进程的过程在switch_to()中,switch_to()是一个宏,其定义如下:

#define switch_to(prev,next,last) do {
\


unsigned long esi,edi;
\


asm volatile("pushfl\n\t"
\


    "pushl %%ebp\n\t"
\


    "movl %%esp,%0\n\t"
/* save ESP */
\


    "movl %5,%%esp\n\t"
/* restore ESP */
\


    "movl $1f,%1\n\t"
/* save EIP */
\


    "pushl %6\n\t"
/* restore EIP */
\


    "jmp __switch_to\n"
\


    "1:\t"
\


    "popl %%ebp\n\t"
\


    "popfl"
\


    :"=m" (prev->thread.esp),"=m" (prev->thread.eip),
\


     "=a" (last),"=S" (esi),"=D" (edi)
\


    :"m" (next->thread.esp),"m" (next->thread.eip),
\


     "2" (prev), "d" (next));
\

} while (0)


3.1参数说明


prev存放的是当前的current进程描述符指针。


next存放的是需要被替换进来的进程的描述符指针。


last比较麻烦,在一次进程被切换出去又切换进来的过程中,一般会涉及到3个进程,进程A,B,C,当进程A运行时,切换到进程B,然后再系统运行一段时间后,系统中运行的进程变为了进程C,然后由进程调度程序调度进程A运行,当调度进程A运行时,进程A使用的是自己的内核栈,里面的prev和next就还是从A切换到B时的prev, next,即prev = A, next=B.然而本次从C切换到A应该将prev改变为C才对,而不是A了。


为解决这个问题switch_to()宏在进入后,会把prev先保存到寄存器eax中,当完成进程切换后,把eax的值存入变量last中。

 



3.2过程说明


采用标准的汇编语言说明如下:


1在eax,edx寄存器中分别保存prev和next的值。


movl prev, %eax


   movl next, %edx


2把eflags和ebp寄存器存入prev进程的内核栈中,ebp寄存器中存放的是当前函数栈帧的栈底。

pushfl


push  %ebp


3把esp寄存器的值存入prev->thread.esp中以使该值记录prev内核栈的栈顶,应该注意由于内核态代码使用统一的ess寄存器,所以该寄存器不需要被保存。


mov %esp, 484(%eax)


4把next->thread.esp的值加载到寄存器esp中,这样就会切换到要被切换进来进程的内核栈上,实际上完成了进程的切换。


mov next->thread.esp %esp


5把标记为1的地址记入prev->thread.eip,这样当该进程被切换回来时,会去执行该地址的指令。


mov $1f, 480(%eax)


6把next->thread.eip值压入内核栈,大多数情况下就是标记1指向的地址。


pushl 480(%edx)

    7跳到__switch_to()函数,__switch_to()函数中我们关注的操作主要有2步:


7.1init_tss[cpu].esp0 = next_p->thread.esp,放入对应tss寄存器,在进行中断处理或
系统调用时,会通过tss的esp0字段设定当前进程内核栈。


7.2ret, 该指令会把栈顶保存的返回地址装入eip寄存器,从而执行返回地址的代
码,在第6步将该值压入了栈中,因此一般地址为标记1的地址,如果该进程是新建进
程,返回地址则是ret_from_fork()函数。

8在这里被进程B替换的进程A再次获得CPU,它会执行恢复eflags和ebp的指令。


1:


popl %ebp


popfl

9copy eax寄存器的内容到last指向的内存区域,由于last和prev指向同样的内存区域,这样last就记录了当前被替换的进程的进程描述符。

       mov %eax, last

linux进程解析--进程切换的更多相关文章

  1. linux进程解析--进程的创建

    通常我们在代码中调用fork()来创建一个进程或者调用pthread_create()来创建一个线程,创建一个进程需要为其分配内存资源,文件资源,时间片资源等,在这里来描述一下linux进程的创建过程 ...

  2. linux进程解析--进程的退出及销毁

    一进程的退出: 当一个进程运行完毕或者因为触发系统异常而退出时,最终会调用到内核中的函数do_exit(),在do_exit()函数中会清理一些进程使用的文件描述符,会释放掉进程用户态使用的相关的物理 ...

  3. Linux内核分析--进程创建,执行,切换

    学号:351 原创作品转载请注明出处本实验来源 https://github.com/mengning/linuxkernel/ 实验要求 从整理上理解进程创建.可执行文件的加载和进程执行进程切换,重 ...

  4. Linux内核分析— —进程的切换和系统的一般执行过程

    进程调度的时机 linux进程调度是基于分时和优先级的 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用s ...

  5. Linux内核分析——进程的切换和系统的一般执行过程

    进程的切换和系统的一般执行过程 一.进程切换的关键代码switch_to分析 (一)进程调度与进程调度的时机分析 1.不同类型的进程有不同的调度需求 第一种分类: (1)I/O-bound:频繁进行I ...

  6. 20135239 益西拉姆 linux内核分析 进程的切换和系统的一般执行过程

    week 8 进程的切换和系统的一般执行过程 [ 20135239 原文请转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course ...

  7. 【原创】(三)Linux进程调度器-进程切换

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  8. [进程管理]Linux进程状态解析之T、Z、X

             Linux进程状态:T (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态.          向进程发送一个SIGSTOP信号,它就会因响应该信号而进入 ...

  9. linux(六)__进程与任务控制

    一.程序.进程.线程 1.程序是一个普通文件,是一系列指令和数据的集合,是一个静态的实体,是程序员写好之后存储于外设之上的代码.它是"死"的,而进程和程序都是"活&quo ...

随机推荐

  1. 从零开始写驱动——vfd专用驱动芯片HT16514并行驱动程序编写

    前言 一直看别人搞的 vfd 很漂亮,前段时间淘了个 vfd 模块来,但没有模块资料,还好芯片没有打磨的,良心商家啊.周末抽空来研究一下这个东西. 从零开始 打开外壳 测试线路 查看芯片是 HT165 ...

  2. MFC下DLL编程(图解)

    DLL(Dynamic Link Library,动态链接库)是微软公司为Windows和OS/2操作系统设计一种供应用程序在运行时调用的共享函数库.DLL是应用程序的一种扩展,也是软件共享和重用的传 ...

  3. 数组名和指针的深入理解(C++)

    指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.魔幻数组名请看程序(本文程序在WIN32平台下编译): #includ ...

  4. Add Two Numbers - C++链表操作

    题目意思很简单,两个链表分别表示两个数,将两个数相加的结果存入一个新的链表中. 思路同样很简单:两个链表如果一样长,对应位置相加,如果某一个链表多了,则根据加的结果有无进位继续处理,全部结束后要考虑会 ...

  5. [LeetCode]题解(python):095-Unique Binary Search Trees II

    题目来源: https://leetcode.com/problems/unique-binary-search-trees-ii/ 题意分析: 给一个整数,返回所有中序遍历是1到n的树. 题目思路: ...

  6. Windows下配置PHP

    啥也不说了,照着这两篇做,OK 1. windows下apache+php+mysql 环境配置方法 详细出处参考:http://www.jb51.net/article/30128.htm 2.ht ...

  7. 用C#开发较完整的Windows任务管理器

    原文 用C#开发较完整的Windows任务管理器 这个代码没有什么技术含量,仅仅使用 WMI 和 API 实现了 Windows 任务管理器的部分功能. 但代码里面封装了一个 SystemInfo 的 ...

  8. 转载Spring IntrospectorCleanupListener

    "在服务器运行过程中,Spring不停的运行的计划任务和OpenSessionInViewFilter,使得Tomcat反复加载对象而产生框架并用时可能产生的内存泄漏,则使用Introspe ...

  9. hdoj 3555 Bomb(DFA+dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 思路分析:该问题要求求解1—N中的数中含有49的数的个数,可以使用DFA来递推dp公式:详细解释 ...

  10. 文本相似度算法——空间向量模型的余弦算法和TF-IDF

    1.信息检索中的重要发明TF-IDF TF-IDF是一种统计方法,TF-IDF的主要思想是,如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分 ...