linux 调度

ps 优先级   和标准级别比较 【-40,99】

top                                             【-99,40】


调度类:

实时进程:fifo rr

普通进程:cifs

内核抢占:

  1. 高优先级实时进程抢占低优先级实时进程
  2.  高优先级实时进程抢占 普通优先级进程 

普通进程之间没有抢占的概念


内核发生场景:

用户空间:

  1. 中断返回到用户空间  (resume_userspace ->work_pending)
  2. 系统调用返回到用户空间

内核空间:

  1. 中断返回到内核空间
  2. spinlock锁释放
  3. 调用schedule
  4. 队列中有阻塞任务

thread_info  中的preempt_count 指示内核空间是否可以被抢占,0表示可以被抢占。


内核抢占结束后重新启用会调用,preempt_check_resched.  

preempt_check_resched 调用preempt_schedule . 


wake up 函数执行流程

wake_up 调用default_wake_function -> try_to_wake_up  作用:将任务放入运行队列。


一 调度时机
1)显示调度,进程自己因为缺少相应的所申请的资源,显示调用调度器,让出处理器,比如:内核申请的
信号阻塞了,自旋锁锁住了
2)隐式调度,整个linux系统在运行过程中的非显示的调用调度器,这又分两种情况
A)用户态抢占调度  比如:在系统调用,中断处理,异常处理返回用户态时,该进程的时间片已经用完
B)内核态抢占调度  比如:当前内核态执行过程中事先没有禁止内核态抢占,有中断产生时,中断处理
又产生了更高级优先进程,那么就会直接抢占前面的内核态执行

内核态抢占的抢占点有两处:(A)中断处理返回内核态时(如果事先没有禁止内核态抢占---preempt_disable)
(B)重新起用内核态抢占时---preempt_enable

相关数据结构及函数如下:
struct task中
{
unisgned int preempt_count;-----(PREEMPT 0-7位表示内核态禁止抢占计数器,SOFTIRQ 8-15表示软中断禁止
计数器,HARDIRQ 16-27表示中断嵌套的深度)
}
只要PREEMPT为0时才允许内核态抢占.

preempt_disable()--------------主要执行inc_preempt_count()(增加PREEMPT,从而禁止内核态抢占)
preempt_enable()--------------主要执行preempt_enable_no_resched()和preempt_check_resched()
preempt_enable_no_resched()主要执行dec_preempt_count()
preempt_check_resched()主要执行test_thread_flag(TIF_NEED_RESCHED)
(是否设置了需要调度的标志)和preempt_schedule()(进行内核态抢占调度)

二 常见的调度点
1)进程被阻塞时 比如申请资源时被阻塞 
2)调整参数时   比如通过sched_setscheduler() ,nice()等函数调整进程的调度策略,静态优先级时
3)睡眠进程被唤醒时  比如wake_up唤醒等待队列中的进程时,如果该进程具有更高优先级则会设置当前
进程TIF_NEED_RESCHED,如果允许内核态抢占,则会调度一次,
( 这是由等待队列中的默认的唤醒函数控制的,默认的唤醒函数为: 
int default_wake_function(wait_queue_t*,unisgned int  mode,int sync,void* key)
EXPORT_SYMBOL(default_wake_function)
因为EXPORT_SYMBOL了default_wake_function,所以我们可以制作我们自己的唤醒函数.
4)中断处理完时  如果中断处理过程中设置了TIF_NEED_SCHED标志,中断返回时,不论是要返回内核态
还是用户态,都会发生一次抢占.当然,在这也会检查有没有软中断需要处理.
5)执行了preempt_enable()函数  (见前面说明)


struct thread_info {
struct task_struct*task;/* main task structure */
struct exec_domain*exec_domain;/* execution domain */
__u32 flags;/* low level flags */
__u32 status;/* thread synchronous flags */
__u32 cpu;/* current CPU */
int preempt_count;/* 0 => preemptable,
  <0 => BUG */
mm_segment_t addr_limit;
struct restart_block    restart_block;
void __user *sysenter_return;
#ifdef CONFIG_X86_32
unsigned long           previous_esp;   /* ESP of the previous stack in
  case of nested (IRQ) stacks
*/
__u8 supervisor_stack[0];
#endif
int uaccess_err;
};


ret_from_int  ret_from_exception   ret_from_sys_call


参考资料:

中断返回,系统调用返回 , 异常返回 。

http://blog.csdn.net/zhw888888/article/details/6602754


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值