第八周总结

一、调度时机
不同类型的进程有不同的调度需求
第一种分类: 
      I/O-bound 
           频繁的进行I/O
           通常会花费很多时间等待I/O操作的完成
     CPU-bound 
           计算密集型
           需要大量的CPU时间进行运算
第二种分类 
    批处理进程(batch process) 
           不必与用户交互,通常在后台运行
           不必很快响应
           典型的批处理程序:编译程序、科学计算
    实时进程(real-time process) 
           有实时需求,不应被低优先级的进程阻塞
           响应时间要短、要稳定
           典型的实时进程:视频/音频、机械控制等
    交互式进程(interactive process) 
           需要经常与用户交互,因此要花很多时间等待用户输入操作
           响应时间要快,平均延迟要低于50~150ms
          典型的交互式程序:shell、文本编辑程序、图形应用程序等
二、进程调度的时机
中断处理过程(包括时钟中断、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指向被调度的进程
三、linux进程调度与进程切换
内容:
(1)从schedule()开始,几种不同类型的进程之间的调度选择;在相同类型的进程之间的调度选择算法
首先禁止抢占,获取当前CPU,该CPU的执行队列,队列上正在执行的进程,以及该进程的交换计数信息并释放该进程占用
的锁。
之后,对禁止中断,更新运行队列时钟,该队列的自旋时钟加锁,后清除当前进程的thread_flag中TIF_NEED_RESCHED。
如果进程不在可运行状态,并且可被抢占,若进程处于非阻塞挂起,则将其改为可运行,否则调用deactivate_task()函数,并修改上下文交换次数。其中在deactive_task()函数中调用了denqueue_task()函数:
(2)从CPU的IP值的变化上,说明在switch_to宏执行后,执行分析
(3)堆栈发生切换位置,在切换堆栈前后,current_thread_info变化
 
保存当前进程的flags ;将当前堆栈的基址压栈;保存当前的栈顶;内核堆栈的切换;保存当前进程的eip
(4)地址空间发生切换,解释地址空间的切换不会影响后续切换代码的执行
(5)current宏所代表的进程发生变化的源码位置
(6)任务状态段中关于内核堆栈的信息发生变化源码位置
实验过程:
先把Menu删掉在clone一个
 
 单步调试
设置断点
 
 
实验总结 :通过学习,我们了解到Linux使用了堆栈进行了进程调度。schedule()在需要的时候重新获得大内核锁、重新启用内核抢占、并检查是否一些其他的进程已经设置了当前进程的tlf_need_resched标志,如果是,整个schedule()函数重新开始执行,否则,函数结束。linux调度的核心函数为schedule,schedule函数封装了内核调度的框架。细节实现上调用具体的调度类中的函数实现。当切换进程已经选好后,就开始用户虚拟空间的处理,然后就是进程的切换switch_to()。所谓进程的切换主要就是堆栈的切换,这是由宏操作switch_to()完成的。
posted @ 2016-04-17 08:53  20135331文艺  阅读(191)  评论(0编辑  收藏  举报