窥探 kernel --- 进程抢占和切换

本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7563540


抢占时伴随着schedule()的执行。内核提供了一个TIF_NEED_RESCHED标志来表明是否要用schedule()调度一次。

根据抢占发生的时机分为用户抢占和内核抢占。用户抢占发生在内核即将返回到用户空间的时候。内核抢占发生在返回内核空间的时候。

1、用户抢占:内核在即将返回用户空间时检查进程是否设置了TIF_NEED_RESCHED标志,如果设置了,就会发生用户抢占。用户抢占发生的时机:从系统调用或中断处理程序返回用户空间的时候。

2、内核抢占:在不支持内核抢占的内核中,内核进程如果自己不主动停止,就会一直的运行下去。无法响应实时进程。抢占内核虽然牺牲了上下文切换的开销,但获得了更大的吞吐量和响应时间。2.6的内核添加了内核抢占,同时为了某些地方不被抢占,又添加了自旋锁。在进程的thread_info结构中添加了preempt_count该数值为0,当进程使用一个自旋锁时就加1,释放一个自旋锁时就减1.为0时表示内核可以抢占。

内核发生抢占的时机:1、从中断处理程序返回内核空间时,内核会检查preempt_count和TIF_NEED_RESCHED标志,如果进程设置了TIF_NEED_RESCHED标志,并且preempt_count为0,发生内核抢占。2、当内核再次用于可抢占性的时候,当进程所有的自旋锁都释放了,释放程序会检查TIF_NEED_RESCHED标志,如果设置了就会调用schedule。3、显示调用schedule时4、内核中的进程被堵塞的时候。

 

 

 

进程的切换:

从一个运行的进程转换到另一个可运行的进程时,称为进程切换(process switch)或上下文切换(context switch).

1、硬件上下文(hardware context)

2、任务状态段tss

3、硬件上下文的切换:linux内核中的硬件上下文不像intel原始设计的那样存放在tss中而是用一个特定了数据结构来存储。

4、context_switch

/*

 *context_switch - switch to the new MM and the new
 *thread's register state.
 */

static inline void
context_switch(struct rq *rq, structtask_struct *prev,
            struct task_struct *next)
{
     structmm_struct *mm, *oldmm;
     prepare_task_switch(rq,prev, next);
     trace_sched_switch(prev,next);
     /*获取即将调度的进程内存指针*/
     mm =next->mm;
     /*保存当前要替换的进程使用的内存数据结构*/
     oldmm= prev->active_mm;
     /*
      * For paravirt, this is coupled with an exitin switch_to to
      * combine the page table reload and the switchbackend into
      * one hypercall.
      */
     arch_start_context_switch(prev);
     /*如果指向的即将调用的进程内存指针为null,则为内核线程*/
     if(!mm) {
         next->active_mm= oldmm;
         /*内存描述结构使用计数加1*/
         atomic_inc(&oldmm->mm_count);
         enter_lazy_tlb(oldmm,next);
     }else

         /*不是内核线程,切换页表*/
         switch_mm(oldmm,mm, next);

     if(!prev->mm) {
         prev->active_mm= NULL;
         rq->prev_mm= oldmm;
     }

     /*

      * Since the runqueue lock will be released bythe next
      * task (which is an invalid locking op but inthe case
      * of the scheduler it's an obviousspecial-case), so we
      * do an early lockdep release here:
      */

#ifndef __ARCH_WANT_UNLOCKED_CTXSW
     spin_release(&rq->lock.dep_map,1, _THIS_IP_);
#endif

     /*Here we just switch the register state and the stack. */
     /*处理器状态切换*/
     switch_to(prev,next, prev);
     barrier();

     /*
      * this_rq must be evaluated again because prevmay have moved
      * CPUs since it called schedule(), thus the'rq' on its stack
      * frame will be invalid.
      */
     finish_task_switch(this_rq(),prev);

}


你可能感兴趣的:(thread,数据结构,struct,null,linux内核,locking)