`
xitong
  • 浏览: 6188630 次
文章分类
社区版块
存档分类
最新评论

内核定时器 timer_list 分析

 
阅读更多

structtimer_list
|-----------------------------------|
|structlist_head entry |
|unsigned longexpires |
|void (*function)(unsigned long)|
|unsignedlongdata |
|struct tvec_t_base_s*base |--+
|-----------------------------------|-|
|void *start_site |
-| CONFIG_TIMER_STATS
|char start_comm[16]|
-|
|int start_pid |
-|
|-----------------------------------|
-|
|
+--------------------------------------+
| 时钟向量base结构tvec_t_base_s
| structtvec_t_base_s
+-->|---------------------------------|
|spinlock_t lock |
|struct timer_list *running_timer |
|unsigned long timer_jiffies
-| base的基准时间
|tvec_root_t tv1 | root hash链表
|tvec_t tv2 | 二级hash链表
|tvec_t tv3 | 三级hash链表
|tvec_t tv4 | 四级hash链表
|tvec_t tv5 | 五级hash链表
|---------------------------------|
____cacheline_aligned_in_smp


expires 定时器定时的滴答数(当前的滴答数为jiffies)
function 到那个时刻内核调用的函数
data 由于可能多个定时器调用一个函数,为了使得这个函数能够区分不同的定时器,通过在结构中data来标识这个定时器,并且通过调用function(data)使得function能区分它们,也就是 data起到ID的作用。


使用时钟,先声明一个timer_list结构,调用init_timer对它进行初始化。 time_list结构里expires是标明这个时钟的周期,单位采用jiffies的单位。function就是时间到了以后的回调函数,它的参数就是timer_list中的data。 data这个参数在初始化时钟的时候赋值,一般赋给它设备的device结构指针。在预置时间到系统调用function,同时系统把这个time_list从定时队列里清除。所以如果需要一直使用定时函数,要在function里再次调用add_timer()把这个timer_list加进定时队列。


管理定时器的接口
----------------------------------------------------------
创建定时器需要先定义它:
struct timer_list my_timer;
接着需要通过一个辅助函数初始化定时器数据结构的内部值,初始化必须在使用其他定时器管理函数对定时器进行操作前完成。
init_timer(&my_timer);
现在可以填充结构中需要的值了(与定时器直接相关的三个参数):
my_timer.expires= jiffies + delay; // 定时器超时时的节拍数
my_timer.data = 0; // 给定时器处理函数传入参数0
my_timer.function= my_function; // 定时器超时时调用的函数
my_timer.expires表示超时时间,它是以节拍为单位的绝对计数值。如果当前jiffies计数等于或大于my_timer.expires,那么my_function指向的处理函数就会开始执行,另外该函数还要使用长整型参数my_timer.data。如果你不需要这个参数,可以简单地传递0(或任何其他值)给处理函数。

最后,必须激活定时器:
add_timer(&my_timer);
大功告成,定时器可以工作了!但请注意定时值的重要性。当前节拍计数大于等于指定的超时值时,内核就开始执行定时器处理函数。虽然内核可以保证不会在超时时间到期前运行定时器处理函数,但是有可能延误定时器的执行。一般来说,定时器都在超时后马上就回执行,但是也有可能被推迟到一下时钟节拍才能运行,所以不能用定时器来实现任何硬实时任务。

有时可能需要更改已经激活的定时器超时时间,所以内核通过函数mod_timer()来实现该功能,该函数可以改变指定的定时器超时时间:
mod_timer(&my_timer, jiffies+new_delay);
mod_timer()函数也可操作那些已经初始化,但还没有被激活的定时器,如果定时器未被激活,mod_timer()会激活它。如果调用时定时器未被激活,该函数返回0;否则返回1。但不论哪种情况,一旦从mod_timer()函数返回,定时器都将被激活而且设置了新的定时值。

如果需要在定时器超时前停止定时器,可以使用del_timer()函数:
del_timer(&my_timer);
被激活或未被激活的定时器都可以使用该函数,如果定时器还未被激活,该函数返回0;否则返回1。注意,你不需要为已经超时的定时器调用该函数,因为它们超时后会自动被删除。


当删除定时器时,必须小心一个潜在的竞争条件。当del_timer()返回后,可以保真的只是: 定时器不会再被激活(也就是,将来不会执行),但是在多处理机器上定时器中断可能已经在其他处理器上运行了,所以删除定时器时需要等待可能在其他处理器上运行的定时器处理程序都退出,这时就要使用del_timer_sync()函数执行删除工作:
del_timer_sync(&my_timer);
和del_timer()函数不同,del_timer_sync()函数不能在中断上下文中使用。




tvec_t, tvec_root_t
hash链表--
tvec_t_base_s中的hash链表
-------------------------------------------------------
--typedefstruct tvec_s
|------------------------|
|structlist_headvec[0]
|
|------------------------|
| |
|------------------------|
| |
|------------------------|
| |
|------------------------|
| |
|------------------------|
|struct list_head vec[31]|
|------------------------|
tvec_t

typedefstruct tvec_root_s
|-------------------------|
|struct list_head vec[0]
-|
|-------------------------|
| |
|-------------------------|
| |
|-------------------------|
| |
|-------------------------|
| |
|-------------------------|
|struct list_head vec[128]|
|-------------------------|
tvec_root_t


TVN_SIZE = 32 (or 128)
TVR_SIZE = 128 (or 512)

-------------------------------------------------------
根据内核是否配置了CONFIG_BASE_SMALL来确定向量链表数是32还是128
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
根据内核是否配置了CONFIG_BASE_SMALL来确定root链表数是128还是512
#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)



boot_tvec_bases
-------------------------------------------------------
定义内核时钟base全局变量
typedef struct tvec_t_base_s tvec_base_t;
tvec_base_tboot_tvec_bases;
EXPORT_SYMBOL(boot_tvec_bases);

为每个CPU定义一个时钟向量基表
staticDEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };



就位后的timer和tvec_t_bash_s的关系视图
----------------------------------------------------------
tvec_t_base_s
|----------|
| |
| |
| |
| |
| |
| |
| |
| |
| |timer_list
timer_listtimer_list
|----------| |----------| |----------| |----------|
|-vec[i]-|<---->|entry |<---->|entry |<---->|entry |
|----------| |expires | |expires | |expires |
| | |function()| |function()| |function()|
| | |data | |data | |data |
| | +--|*base | +--|*base | +--|*base |
| | |-|----------| |
-|----------| |-|----------|
| | | | |
| | | | |
|----------|<--+-----------------+-----------------+

分享到:
评论

相关推荐

    简单谈谈Linux内核定时器

    软件意义上的定时器最终依赖硬件定时器来实现, 内核在时钟中断发生后检测各定时器是否到期 , 到期后的定时器处理函数将作为软中断在底半部执行 。实质上,时钟中断处理程序会 换起TIMER_SOFTIRQ软中断 ,运行当前...

    Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现 - DroidPhone的专栏 - 博客频道 - CSDN

    摘要视图订阅登录 | 注册Linux时间管系统(7)01.struct hrtimer {1251838次第1606名51篇0篇4篇555条定时器的到期时间用k

    TCP-IP详解卷2_1.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷2_2.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷2:实现.part1

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP_IP详解卷1

    第23章 TCP的保活定时器 251 23.1 引言 251 23.2 描述 252 23.3 保活举例 253 23.3.1 另一端崩溃 253 23.3.2 另一端崩溃并重新启动 254 23.3.3 另一端不可达 254 23.4 小结 255 第24章 TCP的未来和性能 256 24.1 ...

    TCP/IP详解part_2

    第23章 TCP的保活定时器 251 23.1 引言 251 23.2 描述 252 23.3 保活举例 253 23.3.1 另一端崩溃 253 23.3.2 另一端崩溃并重新启动 254 23.3.3 另一端不可达 254 23.4 小结 255 第24章 TCP的未来和性能 256 24.1 ...

    TCP-IP详解卷二:实现

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCPIP协议详解卷二.part2.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_...

    TCPIP协议详解卷二.part1.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_...

    TCPIP协议详解卷二.part4.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_...

    TCPIP协议详解卷二.part3.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_...

    TCP-IP详解卷二:实现part2

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷2:实现.rar

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解-卷2实现分两部分-part2

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCPIP协议详解卷2:实现

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷2:实现——2

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷2

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解卷二:实现part1

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

    TCP-IP详解-卷2实现分两部分-part1

    2.2.3 内核统计 28 2.3 mbuf的定义 29 2.4 mbuf结构 29 2.5 简单的mbuf宏和函数 31 2.5.1 m_get函数 32 2.5.2 MGET宏 32 2.5.3 m_retry函数 33 2.5.4 mbuf锁 34 2.6 m_devget和m_pullup函数 34 2.6.1 m_devget函数 ...

Global site tag (gtag.js) - Google Analytics