本文简要介绍了Linux实现POSIX定时器的内核代码。内核中对posix定时器的实现代码在kernelposix-timers.c/h中,本文使用的代码是2.6.29;关于用户空间如何使用POSIX定时器请查阅相关man文档。
  Linux提供的POSIX定时器功能主要由以下几个函数组成:

 

int timer_create(clockid_t which_clock, struct sigevent* timer_event_spec, timer_t* created_timer_id);
int timer_gettime(timer_t timer_id, struct itimerspec* setting);
int timer_settime(timer_t timer_id, int flags, struct itimerspec* new_setting, struct itimerspec* old_setting);
int timer_delete(timer_t timer_id);

  除此之外,还有一些附加函数,比如:

 

clock_nanosleep
clock_getres
clock_settime
clock_gettime
timer_getoverrun

  定时器的创建/删除新建定时器的函数是timer_create。
  int timer_create(clockid_t which_clock, struct sigevent* timer_event_spec, timer_t* created_timer_id);
  参数which_clock可以是系统默认的CLOCK_REALTIME,CLOCK_MONOTONIC,或者其它被登记的clock。
  参数timer_event_spec是定时器到期时的通知方式。在kernel中,timer_event_spec的it_sigev_notify域可以是SIGEV_SIGNAL、SIGEV_NONE、SIGEV_THREAD_ID;但是在用户空间,除上述三个值之外,还有一个SIGEV_THREAD。SIGEV_THREAD比较特殊,是POSIX库在用户空间实现的,与内核无关。www.linuxidc.com这可以在代码的includeasm-genericsiginfo.h中找到说明:

 

/*
* sigevent definitions
*
* It seems likely that SIGEV_THREAD will have to be handled from
* userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
* thread manager then catches and does the appropriate nonsense.
* However, everything is written out here so as to not get lost.
*/
#define SIGEV_SIGNAL   0     /* notify via signal */
#define SIGEV_NONE      1     /* other notification: meaningless */
#define SIGEV_THREAD  2     /* deliver via thread creation */
#define SIGEV_THREAD_ID 4       /* deliver to thread */

  另外,SIGEV_THREAD_ID被用于实现POSIX线程库,应用程序也不能随意使用。(见附注)
  参数created_timer_id是创建定时器成功后,返回的定时器编号。
  下面看一下新建定时器的具体实现:

 

int timer_create(clockid_t which_clock, struct sigevent* timer_event_spec, timer_t* created_timer_id);
struct k_itimer * new_timer = alloc_posix_timer(); // 分配定时器占用的内存
。。。       // 调用idr模块将new_timer与一个id关联,并设置相关域
// 下面的COCK_DISPATCH宏默认调用到common_timer_create函数
CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
。。。       // 将struct sigevent* timer_event_spec保存到new_timer的相应结构中,这里有                // 用户空间和内核空间的转换
。。。       // 将new_timer挂入struct task_struct::signal->posix_timers中。这里如果指定                        // 了it_sigev_notify域为SIGEV_THREAD_ID,那么task_struct为定时器到期                        // 时需要通知的线程;否则,task_struct为当前线程所属进程
// posix_timers队列维护一个task中所有已使用的定时器链表,该链表用于进                        // 程退出时删除所有已使用的posix定时器
common_timer_create函数初始化k_itimer中的hrtimer域,hrtimer是Linux的高精度时钟
static int common_timer_create(struct k_itimer *new_timer)
{
hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
return 0;
}