感谢支持
我们一直在努力

Linux 2.6如何使用时间中断来完成进程调度

进程调度:


Linux里的进程管理调度,如何调度使用不同的进程占用不同的时间片段,主要在核心函数 scheduler_tick (kernel/sched.c)


硬中断触发:


对操作系统来说,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到


该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理了。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识。这些中断值通常被称为中断请求线,这里所说的中断就是硬中断,也是我们常说的中断的上半部分。


硬中断的执行:


不同的架构在linux上是不同的执行,在x86架构中,源码程序在/arch/x86_64/kernel/irq.c 


  1. asmlinkage unsigned int do_IRQ(struct pt_regs *regs)  

  2. {     

  3.     /* high bit used in ret_from_ code  */  

  4.     unsigned irq = ~regs->orig_rax;  

  5.   

  6.     if (unlikely(irq >= NR_IRQS)) {  

  7.         printk(KERN_EMERG “%s: cannot handle IRQ %d\n”,  

  8.                     __FUNCTION__, irq);  

  9.         BUG();  

  10.     }  

  11.   

  12.     exit_idle();  

  13.     irq_enter();  

  14. #ifdef CONFIG_DEBUG_STACKOVERFLOW   

  15.     stack_overflow_check(regs);  

  16. #endif   

  17.     __do_IRQ(irq, regs);  

  18.     irq_exit();  

  19.   

  20.     return 1;  

  21. }  
其中  __do_IRQ() 是处理不同的中断信号的函数, 而在irq_exit()里所处理的是中断的下半部分,也就是我们常说的软中断。

在__do_IRQ()的处理函数中,handle_IRQ_event (irq/handle.c)主要负责调用不同的中断信号所注册的函数。


  1. /** 

  2.  * handle_IRQ_event – irq action chain handler 

  3.  * @irq:    the interrupt number 

  4.  * @regs:   pointer to a register structure 

  5.  * @action: the interrupt action chain for this irq 

  6.  * 

  7.  * Handles the action chain of an irq event 

  8.  */  

  9. irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,  

  10.                  struct irqaction *action)  

  11. {  

  12.     irqreturn_t ret, retval = IRQ_NONE;  

  13.     unsigned int status = 0;  

  14.   

  15.     handle_dynamic_tick(action);  

  16.   

  17.     if (!(action->flags & IRQF_DISABLED))  

  18.         local_irq_enable_in_hardirq();  

  19.   

  20.     do {  

  21.         ret = action->handler(irq, action->dev_id, regs);  

  22.         if (ret == IRQ_HANDLED)  

  23.             status |= action->flags;  

  24.         retval |= ret;  

  25.         action = action->next;  

  26.     } while (action);  

  27.   

  28.     if (status & IRQF_SAMPLE_RANDOM)  

  29.         add_interrupt_randomness(irq);  

  30.     local_irq_disable();  

  31.   

  32.     return retval;  

  33. }  
其中struct irqaction 是就是每个不同的硬件中断所注册的处理函数


我们在来看看时间中断里所注册的处理函数,x86_64/kernel/time.c


  1. static struct irqaction irq0 = {  

  2.     timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, “timer”, NULL, NULL  

  3. };  


timer_interrupt 函数


  1. static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)  

  2. {  

  3.     if (apic_runs_main_timer > 1)  

  4.         return IRQ_HANDLED;  

  5.     main_timer_handler(regs);  

  6. #ifdef CONFIG_X86_LOCAL_APIC   

  7.     if (using_apic_timer)  

  8.         smp_send_timer_broadcast_ipi();  

  9. #endif   

  10.     return IRQ_HANDLED;  

  11. }  
在 main_timer_handler 函数里,我们可以清楚的看到


  1. #ifndef CONFIG_SMP   

  2.     update_process_times(user_mode(regs));  

  3. #endif  
函数update_process_times 里显示的调用了 scheduler_tick


  1. /* 

  2.  * Called from the timer interrupt handler to charge one tick to the current  

  3.  * process.  user_tick is 1 if the tick is user time, 0 for system. 

  4.  */  

  5. void update_process_times(int user_tick)  

  6. {  

  7.     struct task_struct *p = current;  

  8.     int cpu = smp_processor_id();  

  9.   

  10.     /* Note: this timer irq context must be accounted for as well. */  

  11.     if (user_tick)  

  12.         account_user_time(p, jiffies_to_cputime(1));  

  13.     else  

  14.         account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));  

  15.     run_local_timers();  

  16.     if (rcu_pending(cpu))  

  17.         rcu_check_callbacks(cpu, user_tick);  

  18.     scheduler_tick();  

  19.     run_posix_cpu_timers(p);  

  20. }  
我们可以看到在时间中断里会调用进程调度,并且在中断的上半部分,也就是不可被打断。

赞(0) 打赏
转载请注明出处:服务器评测 » Linux 2.6如何使用时间中断来完成进程调度
分享到: 更多 (0)

听说打赏我的人,都进福布斯排行榜啦!

支付宝扫一扫打赏

微信扫一扫打赏