没有合适的资源?快使用搜索试试~ 我知道了~
Linux的动态定时器-时间轮
0 下载量 53 浏览量
2021-01-09
14:10:02
上传
评论
收藏 98KB PDF 举报
温馨提示
试读
7页
定时器—有时也称为动态定时器或内核定时器—是管理内核时间的基础。定时器是一种软件功能,即允许在将来的某个时刻,函数在给定的时间间隔用完时被调用。注意的是定时器并不会周期运行,它在超时后自行销毁,这也是定时器被称为动态定时器的一个原因。动态定时器不断地创建和销毁,而且它的运行次数也不受限制。 定时器在内核代码中属于一个基础组件。要想完全弄清楚linux2.6中内核定时器的实现,得先从初始化开始。 在start_kernel(void)–>init_timers(void) void __init init_timers(void) { int err = timer_cpu_n
资源详情
资源评论
资源推荐
Linux的动态定时器的动态定时器-时间轮时间轮
定时器—有时也称为动态定时器或内核定时器—是管理内核时间的基础。定时器是一种软件功能,即允许在将来的某个时
刻,函数在给定的时间间隔用完时被调用。注意的是定时器并不会周期运行,它在超时后自行销毁,这也是定时器被称为动态
定时器的一个原因。动态定时器不断地创建和销毁,而且它的运行次数也不受限制。
定时器在内核代码中属于一个基础组件。要想完全弄清楚linux2.6中内核定时器的实现,得先从初始化开始。
在start_kernel(void)–>init_timers(void)
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_BAD);
register_cpu_notifier(&timers_nb);
open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
}
在timer_cpu_notify(&timers_nb,(unsigned long)CPU_UP_PREPARE,
(void*)(long)smp_processor_id());
中执行
init_timers_cpu(cpu) //初始化本cpu中的timers
初始化的主要代码是:
spin_lock_init(&base->lock);
for (j = 0; j < TVN_SIZE; j++) {
INIT_LIST_HEAD(base->tv5.vec + j);
INIT_LIST_HEAD(base->tv4.vec + j);
INIT_LIST_HEAD(base->tv3.vec + j);
INIT_LIST_HEAD(base->tv2.vec + j);
}
for (j = 0; j < TVR_SIZE; j++)
INIT_LIST_HEAD(base->tv1.vec + j);
base->timer_jiffies = jiffies;
base->next_timer = base->timer_jiffies;
这段代码的主体是base,base的定义是:structtvec_base *base;
这个tvec_base是动态定时器的主要数据结构,每个cpu上有一个,它包含相应cpu中处理动态定时器需要的所有数据。为
简化分析仅考虑单cpu。给出这个数据机构:
struct tvec_base {
spinlock_t lock;
struct timer_list *running_timer;
unsigned long timer_jiffies;
unsigned long next_timer;
struct tvec_root tv1;
struct tvec tv2;
struct tvec tv3;
struct tvec tv4;
struct tvec tv5;
} ____cacheline_aligned;其中,timer_list是具体定时器的结构体(后面再具体看timer_list结构体);上面包含
tv1,tv2,tv3,tv4,tv5;内核定时器的巧妙设计在于此。
#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
#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)
struct tvec {
struct list_head vec[TVN_SIZE];
};
struct tvec_root {
struct list_head vec[TVR_SIZE];
};
从这个定义看到,tv1是长度为256的数组,数组成员是list_head;同样的,tv2,tv3,tv4和tv5都是长度为64的数组,数
组成员是list_head。List_head是linux内核代码中广泛使用的双向链表。在阻塞和非阻塞中的等待队列时看到了list_head的应
用。那么,tv1-tv5都是数组+链表的实现,其实hash的有一种简单实现是数组+链表的组合,那么这几个有些hash的味道,具
体是不是,还要分析道后面才知道。
再回到前面的初始化中,
for(j = 0; j < TVN_SIZE; j++) {
INIT_LIST_HEAD(base->tv5.vec+ j);
INIT_LIST_HEAD(base->tv4.vec+ j);
weixin_38543120
- 粉丝: 6
- 资源: 932
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0