码迷,mamicode.com
首页 > 系统相关 > 详细

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

时间:2016-04-17 11:42:06      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:

理解进程调度时机跟踪分析进程调度与进程切换的过程
20135111   李光豫
原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 

 

         一.  实验要求

   1、题目自拟,内容围绕对进程调度的时机和进程切换进行;

  •     2、可以结合关键代码、实验截图、堆栈状态、CPU寄存器状态等;

  •                     3、博客内容中需要仔细分析进程的调度时机、switch_to及对应的堆栈状态等。

  • 4、总结部分需要阐明自己对“Linux系统一般执行过程”的理解。

  •     二. 实验内容

  •                                                                    1、理解Linux系统中进程调度的时机,可以在内核代码中搜索schedule()函数,看都是哪里调用了schedule(),判断我们课程内容中的总结是否准确;

    •                                     2、使用gdb跟踪分析一个schedule()函数,验证您对Linux系统进程调度与进程切换过程的理解。

    •                                                      3、特别关注并仔细分析switch_to中的汇编代码,理解进程上下文的切换机制,以及与中断上下文切换的关系;

    • 4、根据本周所学知识分析并理解Linux中进程调度与进程切换过程。

    • 三.实验过程
    •   技术分享
    • 技术分享 
    • 2. (1)gdb跟踪分析一个schedule()函数
    • 技术分享 
    •  
    •  (2)实验代码解析
    • #define switch_to(prevnextlast)
    • \32do {
      \34 * Context-switching clobbers all registers, so we clobber
    • \35 * them explicitly, via unused output variables.
    • \36 * (EAX and EBP is not listed because EBP is saved/restored
    • \37 * explicitly for wchan access and EAX is the return value of
    • \38 * __switch_to()
    • \40unsignedlongebxecxedxesiedi;
    • \42asmvolatile("pushfl\n\t"/* 保存当前进程的flag save flags */
    • \43"pushl %%ebp\n\t"/* 把当前进程的堆栈基址压栈 save EBP */ 
    • \44"movl %%esp,%[prev_sp]\n\t"/* 把当前栈顶保存起来,保存到thread.sp [prev_sp]是使用标号,类似以前的%1,这里使用字符串标记参数
    • save ESP */
    • \45"movl %[next_sp],%%esp\n\t"/*把下一个进程的栈顶放到esp寄存器里面,从这开始,所有的压栈都是在next进程里面了
      restore ESP */
    • \46"movl $1f,%[prev_ip]\n\t"/*存当前进程的eip,在恢复prev当前进程的时候可以从这里开始恢复
      save EIP */
    • \47"pushl %[next_ip]\n\t"/*把next进程起点也就是IP的位置压栈,这里是压到next进程的堆栈,next进程的栈顶就是他的起点。restore EIP */\
      48__switch_canary\49"jmp __switch_to\n"/*不同于call调用函数用寄存器传递参数 regparm call */\
    • 50"1:\t"//从这才开始执行next进程第一条语句,以上的语句是很模糊的,属于哪个进程还不好说,但从45行之后就已经在next进程中压栈了。\
      51"popl %%ebp\n\t"/* restore EBP */
    • \52"popfl\n"/* restore flags */
    • \54/* output parameters */
    • \55 : [prev_sp] "=m" (prev->thread.sp),//当前进程,因为中断内部在内核态,sp内核堆栈栈顶。
    • \56 [prev_ip] "=m" (prev->thread.ip),//thread.ip当前进程的eip\
    • \57"=a" (last),\58\59/* 需要破坏的一些寄存器。clobbered output registers: */
    • \60"=b" (ebx), "=c" (ecx), "=d" (edx),\61"=S" (esi), "=D" (edi)
    • \65/* input parameters: */
    • \66 : [next_sp] "m" (next->thread.sp),//input:next->thread.sp下一个进程内核堆栈栈顶
    • 67 [next_ip] "m" (next->thread.ip),//next->thread.ip下一个进程执行的起点
    • \69/* regparm parameters for __switch_to(): */
    • \70 [prev] "a" (prev),
    • \71 [next] "d" (next)
    • \75 : /* reloaded segment registers */
    • \76"memory");
    • \77while (0)
    • 3. 理解上下文切换机制
    • 进程调度的时机
      中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
      内核线程可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
      用户态进程无法实现主动调度,仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换
    • next = pick_next_task(rq, prev);//进程调度算法都封装这个函数内部
      context_switch(rq, prev, next);//进程上下文切换
      switch_to利用了prev和next两个参数:prev指向当前进程,next指向被调度的进程。
    •  
      四.  实验体会    
    •       本次实验让我们对操作系统多个的进程调度机制有了很好地了解。进程的调度时机与进程的切换,操作系统原理中介绍了大量进程调度算法,这些算法从实现的角       度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已。对于理解操作系统的工作机制,反而是进程的调度时机与进程的切换机制更为关       键。进程的切换,为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换任务切换上下文切换。   

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

标签:

原文地址:http://www.cnblogs.com/lgysblog/p/5400431.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!