Linux内部的时钟处理机制全面剖析(1)(7)
3.3 添加或删除软件时钟
在了解了软件时钟的数据组织关系之后,现在来看一下如何添加以及删除一个软件时钟。
3.3.1 添加软件时钟
在 Linux 内核中要添加一个软件时钟,首先必须分配 struct timer_list 类型的变量,然后调用函数 add_timer() 将该软件时钟添加到相应调用 add_timer 函数的 CPU 的 base 中。 Add_timer 是对函数 __mod_timer() 的一层包装。函数 __mod_timer() 的代码如清单3-2:
清单3-2 __mod_timer 函数 int __mod_timer(struct timer_list *timer, unsigned long expires) if (base != new_base) { |
清单3-2 __mod_timer 函数
代码解释:
- 取得软件时钟所在 base 上的同步锁 struct tvec_base 变量中的自旋锁),并返回该软件时钟的 base ,保存在 base 变量中
- 如果该软件时钟处在 pending 状态在 base 中,准备执行),则卸载该软件时钟
- 取得本 CPU 上的 base 指针类型为 struct tvec_base* ),保存在 new_base 中
- 如果 base 和 new_base 不一样,也就是说软件时钟发生了迁移从一个 CPU 中移到了另一个 CPU 上),那么如果该软件时钟的处理函数当前没有在迁移之前的那个 CPU 上运行,则先将软件时钟的 base 设置为 NULL ,然后再将该软件时钟的 base 设置为 new_base 。否则,跳到5。
- 设置软件时钟的到期时间
- 调用 internal_add_timer 函数将软件时钟添加到软件时钟的 base 中本 CPU 的 base )
- 释放锁
注:卸载软件时钟的意思是指将软件时钟从软件时钟所在 base 中删除,以后所说的卸载软件时钟也都是这个意思 |
这里有必要详细说明一下软件时钟如何被添加到软件时钟的 base 中的添加到本 CPU base 的 tv1~tv5 里面),因为这是软件时钟处理的基础。来看函数 internal_add_timer 函数的实现,如清单3-3
清单3-3 internal_add_timer 函数 static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) |
代码解释:
- 计算该软件时钟的到期时间和 timer_jiffies 当前正在处理的软件时钟的到期时间)的差值,作为索引保存到 idx 变量中。
- 判断 idx 所在的区间,在
- [0, ]或者( , 0)该软件时钟已经到期),则将要添加到 tv1 中
- [, ],则将要添加到 tv2 中
- [, ],则将要添加到 tv3 中
- [, ],则将要添加到 tv4 中
- [, ),则将要添加到 tv5 中,但实际上最大值为 0xffffffffUL
- 计算所要加入的具体位置哪个链表中,即 tv1~tv5 的哪个子链表,参考图3-1)
- 最后将其添加到相应的链表中
从这个函数可以得知,内核中是按照软件时钟到期时间的相对值相对于 timer_jiffies 的值)将软件时钟添加到软件时钟所在的 base 中的。
评论暂时关闭