2013-01-14 14 views
10

add_timer APIで作成されたタイマーが期限切れになり、タイマー構造体で割り当てられた関数が実行されると、どのコンテキストで実行されますか?コンテキストが中断しているのか、カーネルのプロセスコンテキストが中断しているこれは、割り込みコンテキストではもちろんであるLinuxカーネルタイマー機能はどのコンテキストで動作しますか?

+3

? Linuxとそのカーネルタイマーを意味するならば、 'linux/timer.c'の' add_timer() 'へのコメントとして割り込みコンテキストになります:"カーネルは - >関数( - >データ)コールバックを行います**未来の - >満了点でタイマー割り込み**から。割り込みハンドラはいくつかのカーネルでプロセスコンテキストで実行されるかもしれませんが、私はそれをカウントすることをお勧めしません。 – Eugene

+0

こんにちは、申し訳ありませんが、もちろんLinuxカーネルです。ありがとう。 – user1977760

答えて

7

、より正確には、のsoftirqコンテキストで、(カーネル/ timer.c)以下を参照:

何のことをいっているのOS
static inline void __run_timers(struct tvec_base *base) 
{ 
     struct timer_list *timer; 

     spin_lock_irq(&base->lock); 
     while (time_after_eq(jiffies, base->timer_jiffies)) { 
       struct list_head work_list; 
       struct list_head *head = &work_list; 
       int index = base->timer_jiffies & TVR_MASK; 

       /* 
       * Cascade timers: 
       */ 
       if (!index && 
         (!cascade(base, &base->tv2, INDEX(0))) && 
           (!cascade(base, &base->tv3, INDEX(1))) && 
             !cascade(base, &base->tv4, INDEX(2))) 
         cascade(base, &base->tv5, INDEX(3)); 
       ++base->timer_jiffies; 
       list_replace_init(base->tv1.vec + index, &work_list); 
       while (!list_empty(head)) { 
         void (*fn)(unsigned long); 
         unsigned long data; 
         bool irqsafe; 

         timer = list_first_entry(head, struct timer_list,entry); 
         fn = timer->function; 
         data = timer->data; 
         irqsafe = tbase_get_irqsafe(timer->base); 

         timer_stats_account_timer(timer); 

         base->running_timer = timer; 
         detach_expired_timer(timer, base); 

         if (irqsafe) { 
           spin_unlock(&base->lock); 
           call_timer_fn(timer, fn, data); // <=========== HERE 
           spin_lock(&base->lock); 
         } else { 
           spin_unlock_irq(&base->lock); 
           call_timer_fn(timer, fn, data); // <============ HERE 
           spin_lock_irq(&base->lock); 
         } 
       } 
     } 
     base->running_timer = NULL; 
     spin_unlock_irq(&base->lock); 
} 


/* 
* This function runs timers and the timer-tq in bottom half context. 
*/ 
static void run_timer_softirq(struct softirq_action *h) 
{ 
     struct tvec_base *base = __this_cpu_read(tvec_bases); 

     hrtimer_run_pending(); 

     if (time_after_eq(jiffies, base->timer_jiffies)) 
       __run_timers(base); 
} 

void __init init_timers(void) 
{ 
     int err; 

     /* ensure there are enough low bits for flags in timer->base pointer */ 
     BUILD_BUG_ON(__alignof__(struct tvec_base) & TIMER_FLAG_MASK); 

     err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, 
           (void *)(long)smp_processor_id()); 
     init_timer_stats(); 

     BUG_ON(err != NOTIFY_OK); 
     register_cpu_notifier(&timers_nb); 
     open_softirq(TIMER_SOFTIRQ, run_timer_softirq); // <============= HERE 
} 
関連する問題