Chinaunix首页 | 论坛 | 博客
  • 博客访问: 121430
  • 博文数量: 41
  • 博客积分: 2564
  • 博客等级: 少校
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-20 19:17
文章分类

全部博文(41)

文章存档

2009年(41)

我的朋友

分类: LINUX

2009-03-31 15:15:36

Linux 2.4.35 时钟中断分析(续)

    在上一篇文章中,我们跟踪到了timer_bh()这个函数。timer_bh()是时钟中断的下半部,是一个软中断,它位于Timer.c:

void timer_bh(void)
{
    update_times();
    run_timer_list();
}


从代码可以看出,它主要有两个任务,一个是update_times(),另一个是run_timer_list()。update_times()主要任务是更新系统时间,同时还计算系统的负载情况,这里不做详细分析。下面来看看run_timer_list()是干什么的:

static inline void run_timer_list(void)
{
    spin_lock_irq(&timerlist_lock);
    while ((long)(jiffies - timer_jiffies) >= 0) {
        LIST_HEAD(queued);
        struct list_head *head, *curr;
        if (!tv1.index) {
            int n = 1;
            do {
                cascade_timers(tvecs[n]);
            } while (tvecs[n]->index == 1 && ++n < NOOF_TVECS);
        }
        run_timer_list_running = &queued;
repeat:
        head = tv1.vec + tv1.index;
        curr = head->next;
        if (curr != head) {
            struct timer_list *timer;
            void (*fn)(unsigned long);
            unsigned long data;

            timer = list_entry(curr, struct timer_list, list);
             fn = timer->function;
             data= timer->data;

            detach_timer(timer);
            timer->list.next = timer->list.prev = NULL;
            timer_enter(timer);
            spin_unlock_irq(&timerlist_lock);
            fn(data);
            spin_lock_irq(&timerlist_lock);
            timer_exit();
            goto repeat;
        }
        run_timer_list_running = NULL;
        ++timer_jiffies;
        tv1.index = (tv1.index + 1) & TVR_MASK;

        curr = queued.next;
        while (curr != &queued) {
            struct timer_list *timer;

            timer = list_entry(curr, struct timer_list, list);
            curr = curr->next;
            internal_add_timer(timer);
        }            
    }
    spin_unlock_irq(&timerlist_lock);
}


从代码中可以看到,这个函数的主体是一个while循环,而while循环中的主体是一个goto循环(repeat)。在goto循环中,有那么几句:

...
     timer = list_entry(curr, struct timer_list, list);
     fn = timer->function;
     data= timer->data;
...
     fn(data);
...


关于list_entry宏的用途,博客中“通过结构体成员得到结构体的起始地址”一文有详细介绍。timer是一个timer_list结构,即Linux中的定时器,它的详细成分如下:

struct timer_list {
    struct list_head list;
    unsigned long expires;
    unsigned long data;
    void (*function)(unsigned long);
};

其中expires成员记录的是定时器的“到期”时间,function指向定时器的处理函数,data是定时器处理函数的参数。看到这里,应该可以“猜测”到run_timer_list()是干嘛用的了:扫描定时器队列,然后运行那些已经“到期”了的定时器处理函数,同时将他们从定时器队列中删除。当然,这只是一个大概的流程,还要很多细节上面的实现没有研究。
    关于定时器的细节,可以另外开一个“Linux定时器分析”专题,不属于时钟中断的范畴。到此,Linux 2.4.35时钟中断的分析结束。本人水平有限,有什么写得不妥的地方,欢迎大家指出,共同讨论,共同提高!
阅读(800) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~