linux 定时器 API
内核提供给驱动许多函数来声明,注册,以及去除内核定时器. 下列的引用展示了基本的 代码块: ? #include <linux/timer.h> struct timer_list { /* ... */ unsigned long expires; void (*function)(unsigned long); unsigned long data; }; void init_timer(struct timer_list *timer); struct timer_list TIMER_INITIALIZER(_function,_expires,_data); ? void add_timer(struct timer_list * timer); int del_timer(struct timer_list * timer); ? 这个数据结构包含比曾展示过的更多的字段,但是这 3 个是打算从定时器代码自身以外 被存取的. 这个 expires 字段表示定时器期望运行的 jiffies 值; 在那个时间,这个 function 函数被调用使用 data 作为一个参数. 如果你需要在参数中传递多项,你可以 捆绑它们作为一个单个数据结构并且传递一个转换为 unsiged long 的指针,在所有支持 的体系上的一个安全做法并且在内存管理中相当普遍( 如同 15 章中讨论的 ). expires 值不是一个 jiffies_64 项因为定时器不被期望在将来很久到时,并且 64-位操作在 32- 位平台上慢. ? 这个结构必须在使用前初始化. 这个步骤保证所有的成员被正确建立,包括那些对调用者 不透明的. 初始化可以通过调用 init_timer 或者 安排 TIMER_INITIALIZER 给一个静态 结构,根据你的需要. 在初始化后,你可以改变 3 个公共成员在调用 add_timer 前. 为 在到时前禁止一个已注册的定时器,调用 del_timer. ? jit 模块包括一个例子文件,/proc/jitimer ( 为 "just in timer"),它返回一个头文 件行以及 6 个数据行. 这些数据行表示当前代码运行的环境; 第一个由读文件操作产生 并且其他的由定时器. 下列的输出在编译内核时被记录: ? phon% cat /proc/jitimer time delta?? inirq pid?? cpu command 33565837????????? 0? 0? 1269? 0? cat
? 在这个输出,time 字段是代码运行时的 jiffies 值,delta 是自前一行的 jiffies 改 变值,inirq 是由 in_interrupt 返回的布尔值,pid 和 command 指的是当前进程,以 及 cpu 是在使用的 CPU 的数目( 在单处理器系统上一直为 0). ? 如果你读 /proc/jitimer 当系统无负载时,你会发现定时器的上下文是进程 0,空闲任 务,它被称为"对换进程"只要由于历史原因. ? 用来产生 /proc/jitimer 数据的定时器是缺省每 10 jiffies 运行一次,但是你可以在 加载模块时改变这个值通过设置 tdelay ( timer delay ) 参数. ? 下面的代码引用展示了 jit 关于 jitimer 定时器的部分. 当一个进程试图读取我们的文 件,我们建立这个定时器如下: ? unsigned long j = jiffies; /* fill the data for our timer function */ data->prevjiffies = j; ? data->buf = buf2; data->loops = JIT_ASYNC_LOOPS; ? /* register the timer */ data->timer.data = (unsigned long)data; data->timer.function = jit_timer_fn; data->timer.expires = j + tdelay; /* parameter */ add_timer(&data->timer); ? /* wait for the buffer to fill */ wait_event_interruptible(data->wait,!data->loops); ? The actual timer function looks like this: void jit_timer_fn(unsigned long arg) { struct jit_data *data = (struct jit_data *)arg; unsigned long j = jiffies; data->buf += sprintf(data->buf,"%9li %3li %i %6i %i %sn", j,j - data->prevjiffies,in_interrupt() ? 1 : 0,current->pid,smp_processor_id(),current->comm); if (--data->loops) { data->timer.expires += tdelay; data->prevjiffies = j; add_timer(&data->timer); ? } else { wake_up_interruptible(&data->wait); } } ? 定时器 API 包括几个比上面介绍的那些更多的功能. 下面的集合是完整的核提供的函数 列表: ? int mod_timer(struct timer_list *timer,unsigned long expires); ? 更新一个定时器的超时时间,使用一个超时定时器的一个普通的任务(再一次,关 马达软驱定时器是一个典型例子). mod_timer 也可被调用于非激活定时器,那里 你正常地使用 add_timer. ? int del_timer_sync(struct timer_list *timer); ? 如同 del_timer 一样工作,但是还保证当它返回时,定时器函数不在任何 CPU 上 运行. del_timer_sync 用来避免竞争情况在 SMP 系统上,并且在 UP 内核中和 del_timer 相同. 这个函数应当在大部分情况下比 del_timer 更首先使用. 这个 函数可能睡眠如果它被从非原子上下文调用,但是在其他情况下会忙等待. 要十分 小心调用 del_timer_sync 当持有锁时; 如果这个定时器函数试图获得同一个锁,系统会死锁. 如果定时器函数重新注册自己,调用者必须首先确保这个重新注册不 会发生; 这常常同设置一个" 关闭 "标志来实现,这个标志被定时器函数检查. ? int timer_pending(const struct timer_list * timer); ? 返回真或假来指示是否定时器当前被调度来运行,通过调用结构的其中一个不透明 的成员. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |