54SA.COM|专注于系统运维管理,为中国SA提供动力!
Getting online shouldn't be tough. $7.99 .COMs
系统管理员之家Banner
当前位置: 主页 > Linux > 系统管理 >

Linux内部时钟处理机制

时间:2011-11-20 00:00来源:网络 编辑:lavy

  2.3 时钟初始化内核初始化部分( start_kernel 函数)和时钟相关的过程主要有以下几个:tick_init()

  init_timers()

  hrtimers_init()

  time_init()

  其中函数 hrtimers_init() 和高精度时钟相关(本文暂不介绍这部分内容)。下面将详细介绍剩下三个函数。

  2.3.1 tick_init 函数函数 tick_init() 很简单,调用 clockevents_register_notifier 函数向 clockevents_chain 通知链注册元素: tick_notifier.这个元素的回调函数指明了当时钟事件设备信息发生变化(例如新加入一个时钟事件设备等等)时,应该执行的操作,该回调函数为 tick_notify (参见2.4节)。

  2.3.2 init_timers 函数函数 init_timers() 的实现如清单2-1(省略了部分和主要功能无关的内容,以后代码同样方式处理)

  注:本文中所有代码均来自于Linux3.0 源代码单2-1 init_timers 函数void __init init_timers(void)

  { int 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);}代码解释:初始化本 CPU 上的软件时钟相关的数据结构,参见3.2节向 cpu_chain 通知链注册元素 timers_nb ,该元素的回调函数用于初始化指定 CPU 上的软件时钟相关的数据结构初始化时钟的软中断处理函数2.3.3 time_init 函数函数 time_init 的实现如清单2-2清单2-2 time_init 函数void __init time_init(void)

  { late_time_init = x86_late_time_init;} static __init void x86_late_time_init(void)

  { x86_init.timers.timer_init();tsc_init();}函数 tsc_init()初始化 tsc 时钟源。x86_init.timers.timer_init()

  实际是函数 hpet_time_init,其代码清单2-3清单2-3 hpet_time_init 函数void __init hpet_time_init(void)

  { if (!hpet_enable())

  setup_pit_timer();setup_default_timer_irq();}函数 hpet_enable 检测系统是否可以使用 hpet 时钟,如果可以则初始化 hpet 时钟。否则初始化 pit 时钟。最后设置硬件时钟发生时的处理函数(参见2.4节)。

  初始化硬件时钟这个过程主要包括以下两个过程(参见 hpet_enable 的实现):初始化时钟源信息( struct clocksource 类型的变量),并将其添加到时钟源链表中,即 clocksource_list 链表(参见图2-1)。

  初始化时钟事件设备信息( struct clock_event_device 类型的变量),并向通知链 clockevents_chain 发布通知:一个时钟事件设备要被添加到系统中。在通知(执行回调函数)结束后,该时钟事件设备被添加到时钟事件设备链表中,即 clockevent_devices 链表(参见图2-1)。有关通知链的内容参见2.2节。

  需要注意的是在初始化时钟事件设备时,全局变量 global_clock_event 被赋予了相应的值。该变量保存着系统中当前正在使用的时钟事件设备(保存了系统当前使用的硬件时钟中断发生时,要执行的中断处理函数的指针)。

  2.4 硬件时钟处理过程由2.3.3可知硬件时钟中断的处理函数保存在静态变量 irq0 中,其定义如清单2-4单2-4 变量irq0定义static struct irqaction irq0 = {.handler = timer_interrupt,。flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,。name = "timer" };由定义可知:函数 timer_interrupt 为时钟中断处理函数,其定义如清单2-5清单2-5 timer_interrupt 函数static irqreturn_t timer_interrupt(int irq, void *dev_id)

  { /* Keep nmi watchdog up to date */ inc_irq_stat(irq0_irqs);global_clock_event->event_handler(global_clock_event);/* MCA bus quirk: Acknowledge irq0 by setting bit 7 in port 0x61 */ if (MCA_bus)

  outb_p(inb_p(0x61)| 0x80, 0x61);return IRQ_HANDLED;}为了说明这个问题,不妨假设系统中使用的是 hpet 时钟。由2.3.3节可知 global_clock_event 指向 hpet 时钟事件设备( hpet_clockevent )。查看 hpet_enable 函数的代码并没有发现有对 event_handler 成员的赋值。所以继续查看时钟事件设备加入事件的处理函数 tick_notify ,该函数记录了当时钟事件设备发生变化(例如,新时钟事件设备的加入)时,执行那些操作(参见2.3.1节),代码如清单2-6清单2-6 tick_notify 函数static int tick_notify(struct notifier_block *nb, unsigned long reason, void *dev)

  { switch (reason) { case CLOCK_EVT_NOTIFY_ADD:return tick_check_new_device(dev);……

  return NOTIFY_OK;}由代码可知:对于新加入时钟事件设备这个事件,将会调用函数 tick_check_new_device .顺着该函数的调用序列向下查找。tick_set_periodic_handler 函数将时钟事件设备的 event_handler 成员赋值为 tick_handle_periodic 函数的地址。由此可知,函数 tick_handle_periodic 为硬件时钟中断发生时,真正的运行函数。

[责任编辑:admin]


------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
用户名:
最新评论 进入详细评论页>>