linux内核分析之软定时器笔记
来源:互联网 发布:开淘宝网店的费用 编辑:程序博客网 时间:2024/06/05 17:51
定时器是一种软件功能,即允许在将来的某个时刻,函数在给定的时间间隔用完时被调用。超时表示与定时器相关的时间间隔已经用完的那个时刻。
linux上考虑两种类型的定时器,即动态定时和间隔定时器。第一种类型由内核使用,而间隔定时器由进程在用户态创建。
动态定时器
动态定时的主要数据结构是一个叫做tvec_bases的per cpu变量,他包含NR_CPUS个元素,系统中每个CPU都有一个。每个元素是一个tvec_base_t类型的数据结构,他包含相应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;
字段tv1的数据解雇为tvec_root_t类型,包含一个vec数组,这个数组由256个list_head元素组成(即256个动态定时器链表组成)。这个结构包含了在紧接着到来的255个节拍内将要到期的所有动态定时器。
字段tv2,tv3和tv4的数据结构都是tvec_t类型,该类型有一个数组vec。这些链表包含在紧接着到来的2^14-1/2^20-1以及2^26-1个节拍内将要到期的所有动态定时器。
字段tv5与前面的字段几乎相同,但唯一区别就是vec数组的最后一项是一个大expires字段值得动态定时器链表。tv5从不需要从其他的数组补充。
动态定时器编程
1,申请timer_list结构并对其初始化,其中必须初始化的有expires,function
struct timer_list {struct list_head entry;unsigned long expires;void (*function)(unsigned long);unsigned long data;struct tvec_base *base;#ifdef CONFIG_TIMER_STATSvoid *start_site;char start_comm[16];int start_pid;#endif#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map;#endif};
2,调用init_timer函数初始化
该函数最终调用下面函数
static void __init_timer(struct timer_list *timer, const char *name, struct lock_class_key *key){timer->entry.next = NULL;timer->base = __raw_get_cpu_var(tvec_bases);#ifdef CONFIG_TIMER_STATStimer->start_site = NULL;timer->start_pid = -1;memset(timer->start_comm, 0, TASK_COMM_LEN);#endiflockdep_init_map(&timer->lockdep_map, name, key, 0);}
可看到初始化的几个相关变量。
3,调用add_timer函数将申请的timer_list结构添加到合适的链表
该函数最终调用如下函数添加到对应的链表
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer){unsigned long expires = timer->expires;unsigned long idx = expires - base->timer_jiffies;struct list_head *vec;if (idx < TVR_SIZE) {int i = expires & TVR_MASK;vec = base->tv1.vec + i;} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {int i = (expires >> TVR_BITS) & TVN_MASK;vec = base->tv2.vec + i;} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;vec = base->tv3.vec + i;} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;vec = base->tv4.vec + i;} else if ((signed long) idx < 0) {/* * Can happen if you add a timer with expires == jiffies, * or you set a timer to go off in the past */vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);} else {int i;/* If the timeout is larger than 0xffffffff on 64-bit * architectures then we use the maximum timeout: */if (idx > 0xffffffffUL) {idx = 0xffffffffUL;expires = idx + base->timer_jiffies;}i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;vec = base->tv5.vec + i;}/* * Timers are FIFO: */list_add_tail(&timer->entry, vec);}
其中对于定时器的修改、删除等操作,内核提供了相应的函数。
- linux内核分析之软定时器笔记
- linux内核定时器分析
- Linux内核定时器笔记
- linux内核分析笔记----定时器和时间管理
- linux内核分析笔记----定时器和时间管理
- linux内核分析笔记----定时器和时间管理
- linux内核分析笔记----定时器和时间管理
- linux内核分析笔记----定时器和时间管理
- Linux kernel之内核定时器
- Linux kernel之内核定时器
- Linux 驱动之内核定时器
- Linux内核之定时器详解
- linux内核驱动之定时器
- linux内核编程之内核定时器
- linux内核分析笔记
- linux内核分析笔记
- Linux内核分析 学习笔记之反汇编分析
- linux-内核-内核定时器
- 黑马程序员_GUI
- sina绑定手机
- Android自动测试之monkeyrunner工具
- 电容感应触摸屏工作原理
- 应用springMVC时 JS等文件找不到错误
- linux内核分析之软定时器笔记
- android
- Android-sharedUserId数据权限
- IIS发布多个WEB网站应用程序
- 电话费多少速度
- 丰东股份
- C语言和设计模式(适配器模式)
- Table of Language Culture Names, Codes, and ISO Values Method [C++]
- 分两块地反对股份大概