Linux系统进程间隔定时器Itimer(下)(2)
文章作者 100test 发表时间 2007:03:14 16:45:11
来源 100Test.Com百考试题网
7.7.3.2 setitimer()系统调用的实现
函数sys_setitimer()不仅设置调用进程的指定间隔定时器,而且还返回该间隔定时器的原有信息。它有三个参数:(1)which,含义与sys_getitimer()中的参数相同。(2)输入参数value,指向用户空间中的一个itimerval结构,含有待设置的新值。(3)输出参数ovalue,指向用户空间中的一个itimerval结构,用于接收间隔定时器的原有信息。
该函数的源码如下(kernel/itimer.c):
/* SMP: Again, only we play with our itimers, and signals are SMP safe
* now so that is not an issue at all anymore.
*/
asmlinkage long sys_setitimer(int which, struct itimerval *value,
struct itimerval *ovalue)
{
struct itimerval set_buffer, get_buffer.
int error.
if (value) {
if(copy_from_user(&.set_buffer, value, sizeof(set_buffer)))
return -EFAULT.
} else
memset((char *) &.set_buffer, 0, sizeof(set_buffer)).
error = do_setitimer(which, &.set_buffer, ovalue ? &.get_buffer : 0).
if (error || !ovalue)
return error.
if (copy_to_user(ovalue, &.get_buffer, sizeof(get_buffer)))
return -EFAULT.
return 0.
} |
对该函数的注释如下:
(1)在输入参数指针value非空的情况下,调用copy_from_user()宏将用户空间中的待设置信息拷贝到内核空间中的set_buffer结构变量中。如果value指针为空,则简单地将set_buffer结构变量全部置0。
(2)调用do_setitimer()函数完成实际的设置操作。如果输出参数ovalue指针有效,则以内核变量get_buffer的地址作为do_setitimer()函数的第三那个调用参数,这样当do_setitimer()函数返回时,get_buffer结构变量中就将含有当前进程的指定间隔定时器的原来信息。Do_setitimer()函数返回0值表示成功,非0值表示失败。
(3)在do_setitimer()函数返回非0值的情况下,或者ovalue指针为空的情况下(不需要输出间隔定时器的原有信息),函数就可以直接返回了。
(4)如果ovalue指针非空,调用copy_to_user()宏将get_buffer()结构变量中值拷贝到ovalue所指向的用户空间中去,以便让用户得到指定间隔定时器的原有信息值。
函数do_setitimer()的源码如下(kernel/itimer.c):
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
register unsigned long i, j.
int k.
i = tvtojiffies(&.value->it_interval).
j = tvtojiffies(&.value->it_value).
if (ovalue &.&. (k = do_getitimer(which, ovalue)) < 0)
return k.
switch (which) {
case ITIMER_REAL:
del_timer_sync(¤t->real_timer).
current->it_real_value = j.
current->it_real_incr = i.
if (!j)
break.
if (j > (unsigned long) LONG_MAX)
j = LONG_MAX.
i = j jiffies.
current->real_timer.expires = i.
add_timer(¤t->real_timer).
break.
case ITIMER_VIRTUAL:
if (j)
j .
current->it_virt_value = j.
current->it_virt_incr = i.
break.
case ITIMER_PROF:
if (j)
j .
current->it_prof_value = j.
current->it_prof_incr = i.
break.
default:
return -EINVAL.
}
return 0.
} |