内核抢占和schedule()函数的分析

1.线程描述符:

struct thread_info {
    struct task_struct  *task;      
    struct exec_domain  *exec_domain;   
    __u32           flags;      
    __u32           status;     
    __u32           cpu;        
    int         saved_preempt_count;
    ...
};

重要字段解释:
flags: 该字段中有一个位是用于设置内核是否应该被重新调度的标志–need_resched,set_tsk_need_resched()和clear_tsk_need_resched()函数实际上就是对该字段的某一位进行操作(第31位 ?)

saved_preempt_count: 内核此时是否可以进行抢占的标志,为0表示当前进程不持有锁,可以被抢占.大于0则表示此时持有锁,不能被抢占

preempt_counter 字段是32位的, 除了抢占计数器之外还包括其他标志位, 只要 preempt_counter 整体不为0, 就不能进行内核抢占, 这个设计一下子简化了对众多不能抢占的情况的检测: 

Bit  0-7:  抢占计数器, 表示显式禁用内核抢占的次数
Bit  8-15: 软中断计数器, 记录可延迟函数被禁用的次数
Bit 16-27: 硬中断计数器, 表示中断处理程序的嵌套数, irq_enter()递增它, irq_exit()递减它
Bit    28: PREEMPT_ACTIVE 标志, 内核抢占的标志

2.schedule()函数被调度的时机:

1.内核从系统调用或中断处理程序返回时:
1.内核要返回到用户空间时:

如果当前进程的thread_info结构中的need_resched标志被设置,那么就可以调用schedule(),因为内核返回用 
户空间时,它知道自己是安全的,因为既然它可以继续去执行当前进程,那么它当然可以再去选择一个新的进程去执行

2.内核要返回内核空间时:
如果当前进程的thread_info结构体中的need_resched标志被设置而且saved_preempt_count为0时, 通过调用preempt_schedule_irq()函数来间接调用schedule()函数:

asmlinkage void __sched preempt_schedule_irq(void)
{
    struct thread_info *ti = current_thread_info();

    /* Catch callers which need to be fixed */
    BUG_ON(ti->preempt_count || !irqs_disabled());

    do {  
           add_preempt_count(PREEMPT_ACTIVE); //设置thread_info->saved_preempt_count变量的第28位, 即PREEMPT_ACTIVE标志
           local_irq_enable();
           schedule();  //调度
           local_irq_disable();
           sub_preempt_count(PREEMPT_ACTIVE);

           barrier();
    } while (need_resched());
}

此时thread_info->saved_p

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值