Linux系统进程间隔定时器Itimer(下)(3)
文章作者 100test 发表时间 2007:03:14 16:45:10
来源 100Test.Com百考试题网
对该函数的注释如下:
(1)首先调用tvtojiffies()函数将timeval格式的初始值和当前值转换成以时钟滴答为单位的时间值。并分别保存在局部变量i和j中。
(2)如果ovalue指针非空,则调用do_getitimer()函数查询指定间隔定时器的原来信息。如果do_getitimer()函数返回负值,说明出错。因此就要直接返回错误值。否则继续向下执行开始真正地设置指定的间隔定时器。
(3)如果which=ITITMER_REAL,表示设置ITIMER_REAL间隔定时器。(a)调用del_timer_sync()函数(该函数在单CPU系统中就是del_timer()函数)将当前进程的real_timer定时器从内核动态定时器链表中删除。(b)将it_real_incr和it_real_value分别设置为局部变量i和j。(c)如果j=0,说明不必启动real_timer定时器,因此执行break语句退出switch…case控制结构,而直接返回。(d)将real_timer的expires成员设置成(jiffies+当前值j),然后调用add_timer()函数将当前进程的real_timer定时器加入到内核动态定时器链表中,从而启动该定时器。
(4)如果which=ITIMER_VIRT,则简单地用局部变量i和j的值分别更新it_virt_incr和it_virt_value就可以了。
(5)如果which=ITIMER_PROF,则简单地用局部变量i和j的值分别更新it_prof_incr和it_prof_value就可以了。
(6)最后,返回0值表示成功。
7.7.3.3 alarm系统调用
系统调用alarm可以让调用进程在指定的秒数间隔后收到一个SIGALRM信号。它只有一个参数seconds,指定以秒数计的定时间隔。函数sys_alarm()的源码如下(kernel/timer.c):
/*
* For backwards compatibility? This can be done in libc so Alpha
* and all newer ports shouldn t need it.
*/
asmlinkage unsigned long sys_alarm(unsigned int seconds)
{
struct itimerval it_new, it_old.
unsigned int oldalarm.
it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0.
it_new.it_value.tv_sec = seconds.
it_new.it_value.tv_usec = 0.
do_setitimer(ITIMER_REAL, &.it_new, &.it_old).
oldalarm = it_old.it_value.tv_sec.
/* ehhh.. We can t return 0 if we have an alarm pending.. */
/* And we d better return too much than too little anyway */
if (it_old.it_value.tv_usec)
oldalarm .
return oldalarm.
} |
这个系统调用实际上就是启动进程的ITIMER_REAL间隔定时器。因此它完全可放到用户空间的C函数库(比如libc和glibc)中来实现。但是为了保此内核的向后兼容性,2.4.0版的内核仍然将这个syscall放在内核空间中来实现。函数sys_alarm()的实现过程如下:
(1)根据参数seconds的值构造一个itimerval结构变量it_new。注意!由于alarm启动的ITIMER_REAL间隔定时器是一次性而不是循环重复的,因此it_new变量中的it_interval成员一定要设置为0。
(2)调用函数do_setitimer()函数以新构造的定时器it_new来启动当前进程的ITIMER_REAL定时器,同时将该间隔定时器的原定时间隔保存到局部变量it_old中。
(3)返回值oldalarm表示以秒数计的ITIMER_REAL间隔定时器的原定时间隔值。因此先把it_old.it_value.tv_sec赋给oldalarm,并且在it_old.it_value.tv_usec非0的情况下,将oldalarm的值加1(也即不足1秒补足1秒)。