浅析Linux中的时间编程和实现原理(三) Linux内核的工作
|
Per-process ITIMER_VIRTUAL 和 ITIMER_PROF 2.6.12 中合并了 Roland McGrath 的 per-process timer 系列 Patch。使得 itimer.c,posix-timer.c 有了不少改变,还多了一个 posix-cpu-timer.c 文件。虽然代码实现上有很大的不同,但实际上基本的实现思路还是和之前介绍的差不多,不过进一步考虑了对多线程情况下的修正。这里简单介绍一下实现的思路。 每个进程描述符中,引入了两个计数器:utime 和 stime。utime 代表当前进程(也可能是一个线程)花费在用户态的时间。 在时钟中断中,如果内核发现中断时当前进程(线程)正在用户态,则 utime 增加一个 jiffies;如果在内核态则 utime 不增加,stime 增加。总的说来,就是统计好当前进程或线程的运行时间。现在,按下时钟中断暂且不表。 创建 ITIMER_VIRTUAL时 (内核响应函数为do_setitimer),内核将该 Timer 的value 和 interval 分别设置到当前进程描述符的 signal->it_virt_value 和 signal->it_virt_incr 中。假设一个程序有 2 个线程,Thread1 和 Thread2。内核将有两个进程描述符对应这两个线程,taskStruct1 和 taskStruct2。再假设程序是在 Thread1 中调用 setitimer。那么 taskStrcut1的signal->it_virt_value 和 signal->it_virt_incr 被设置;而 taskStruct2 的相应数据则保持为 0。让我们再回到时钟中断。 统计完 utime 和 stime 之后,时钟中断开始检查当前进程描述符的 signal->it_virt_value 值,如果该值非零,则表明有一个 ITIMER_VITURAL,到期时间为 signal->it_virt_value。老的内核实现在这里就判断 utime 是否大于 it_virt_value,如果大于则表明时钟到期。为了统计多线程情况,从 2.6.12 开始,时钟中断在这里不仅要查看当前进程描述符的 utime,还要加上当前进程组中所有线程的 utime,然后再判断总的 utime 是否大于 signal->it_virt_value。比如前面所假设的例子,Thread2 被时钟中断打断时,统计自己的 utime,但由于其 signal->it_virt_value 为 0,因此没有其他的工作需要做了。当 Thread1 被时钟中断打断时,其 signal->it_virt_value 大于 0,因此中断处理中要遍历线程组中所有的线程,将每个线程的 utime 汇总,即总的 utime=taskStruct1->utime+taskStruct2->utime。再用这个总的 utime 和 signal->it_virt_value(即时钟到期时间)进行比较是否到期。仅此而已。 ITIMER_PROF 的思路类似,但它不仅要比较 utime,还要比较 stime。不再赘述。 Posix timer 从 2.5.63 开始,内核能够支持 posix timer 了,之前,其支持是有限的:只支持 CLOCK_REALTIME 和 CLOCK_MONOTONIC 两种 clock ID。这两种 POSIX Timer 建立在内核动态 Timer 之上,精度是一个 tick。比如,创建 realtime 定时器,内核将调用 init_timer() 创建一个动态 Timer,并制定其到期处理函数位 posix_timer_fn;当启动该定时器时,内核将调用 add_timer() 启动该内核动态 Timer;当该定时器到期时,将触发 posix_timer_fn,该函数采用定时器注册的通知方式进行处理,比如 SIGEV_SIGNAL,该函数就会调用 sigaddset 发送一个信号。 (编辑:佛山站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

