基于数据结构timer_vec_root,Linux定义了一个全局变量tv1,以表示内核所关心的前256个定时器向量。这样内核在处理是否有到期定时器时,它就只从定时器向量字段tv1.vec[256]中的某个定时器向量内进行扫描。而tv1的index数组则指定当前正在扫描定时器向量字段tv1.vec[256]中的哪一个定时器向量,也即该链表的索引linux内核定时器linux安装,其年率为0,最大值为255(以256为模)。每位时钟节拍时index数组还会加1。其实,index数组所指定的定时器向量tv1.vec[index]中包含了当前时钟节拍内早已到期的所有动态定时器。而定时器向量tv1.vec[index+k]则包含了接出来第k个时钟节拍时刻将到期的所有动态定时器。当index值又重新变为0时,就意味着内核早已扫描了tv1变量中的所有256个定时器向量。在这些情况下就必须将这些以松散定时器向量语义来组织的定时器向量补充到tv1中来。
(2)而对于内核不关心的、interval值在[0xff,0xffffffff]之间的定时器,它们的到期急迫程度也随其interval值的不同而不同。其实interval值越小,定时器急迫程度也越高。因而在将它们以松散定时器向量进行组织时也应当区别对待。一般,定时器的interval值越小,它所处的定时器向量的松散度也就越低(也即向量中的各定时器的expires值相差越小);而interval值越大,它所处的定时器向量的松散度也就越大(也即向量中的各定时器的expires值相差越大)。
内核规定,对于这些满足条件:0x100≤interval≤0x3fff的定时器,只要表达式(interval>>8)具有相同值的定时器都将被组织在同一个松散定时器向量中。为此,为组织所有满足条件0x100≤interval≤0x3fff的定时器,就须要26=64个松散定时器向量。同样地,为便捷起见,这64个松散定时器向量也置于一起产生字段,并作为数据结构timer_vec的一部份。基于数据结构timer_vec,Linux定义了全局变量tv2linux 删除文件夹,来表示这64条松散定时器向量。如上述代码段所示。
对于这些满足条件0x4000≤interval≤0xfffff的定时器,只要表达式(interval>>8+6)的值相同的定时器都将被置于同一个松散定时器向量中。同样,要组织所有满足条件0x4000≤interval≤0xfffff的定时器,也须要26=64个松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux定义了tv3全局变量来表示这64个松散定时器向量。
对于这些满足条件0x100000≤interval≤0x3ffffff的定时器,只要表达式(interval>>8+6+6)的值相同的定时器都将被置于同一个松散定时器向量中。同样,要组织所有满足条件0x100000≤interval≤0x3ffffff的定时器,也须要26=64个松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux定义了tv4全局变量来表示这64个松散定时器向量。
对于这些满足条件0x4000000≤interval≤0xffffffff的定时器,只要表达式(interval>>8+6+6+6)的值相同的定时器都将被置于同一个松散定时器向量中。同样,要组织所有满足条件0x4000000≤interval≤0xffffffff的定时器,也须要26=64个松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux定义了tv5全局变量来表示这64个松散定时器向量。
最后linux内核定时器,为了引用便捷,Linux定义了一个表针字段tvecs[],来分别指向tv1、tv2、…、tv5结构变量。如上述代码所示。
7.6.3内核动态定时器机制的实现
在内核动态定时器机制的实现中,有三个操作时十分重要的:(1)将一个定时器插入到它应当所处的定时器向量中。(2)定时器的迁移,也正式一个定时器从它原先所处的定时器向量迁移到另一个定时器向量中。(3)扫描并执行当前已然到期的定时器。
7.6.3.1动态定时器机制的初始化
函数init_timervecs()实现对动态定时器机制的初始化。该函数仅被sched_init()初始化解释器所调用。动态定时器机制初始化过程的主要任务就是将tv1、tv2、…、tv5这5个结构变量中的定时器向量表针字段vec[]初始化为NULL。如下所示(kernel/timer.c):
void init_timervecs (void)
{
int i;
for (i = 0; i < TVN_SIZE; i++) {
INIT_LIST_HEAD(tv5.vec + i);
INIT_LIST_HEAD(tv4.vec + i);
INIT_LIST_HEAD(tv3.vec + i);
INIT_LIST_HEAD(tv2.vec + i);
}
for (i = 0; i < TVR_SIZE; i++)
INIT_LIST_HEAD(tv1.vec + i);
}
上述函数中的宏TVN_SIZE是指timer_vec结构类型中的定时器向量表针字段vec[]的大小,值为64。宏TVR_SIZE是指timer_vec_root结构类型中的定时器向量字段vec[]的大小,值为256。