加入收藏 | 设为首页 | 会员中心 | 我要投稿 佛山站长网 (https://www.0757zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

浅析Linux中的时间编程和实现原理(三) Linux内核的工作

发布时间:2016-10-31 01:41:10 所属栏目:Linux 来源:网络整理
导读:引子 时间系统的工作需要软硬件以及操作系统的互相协作,在上一部分,我们已经看到大多数时间函数都依赖内核系统调用,GlibC 仅仅做了一次请求的转发。因此必须

ITIMER_REAL 是用内核动态 Timer 来实现的,每次创建 ITIMER_REAL 时钟时,内核调用 init_timer 创建一个定时器对象,并用 add_timer 将该定时器添加到系统 Timer 时间轮中,该定时器的到期处理函数被设定为 it_real_fn()。此函数将向当前进程发送 SIGALRM 信号,并重新调用 add_timer() 重新启动自身。这样便实现了 ITIMER_REAL 时钟。进程描述符中的 it_real_value 仅用于读取,以便用户通过 /proc 读取时钟信息。

另外两种间隔 Timer 则不能简单地依靠动态 Timer 来实现。因为它们参照的是进程的时间而非实时时间,因此要依赖进程的时间统计。实现原理如下:

每次时钟中断产生时,内核判断中断触发时进程是否正处于内核态,如果在内核态,则将 it_prof_value 和 it_virt_value 都减一;如果在用户态,则只对 it_prof_value 减一,而 it_virt_value 不变。当 it_prof_value 为 0 时,对当前进程发送 SIGPROF 信号,并把 it_prof_incr 的值重新填入 it_prof_value,等待下次到期触发。当 it_virt_value为 0 时,则对当前进程发送 SIGVTALRM 信号,并用it_virt_incr的值重新填充 it_virt_value。这样就实现了 POSIX 对 setitimer 所定义的 ITIMER_VIRTUAL 和 ITIMER_PROF 时钟。

不过这种实现有一个问题:在 Linux 中线程是一个单独的调度实体,即轻量级进程。因此一个进程中的每个线程都拥有自己的进程描述符。这意味着每个线程都有自己的 it_virt_value 和 it_prof_value。因此 ITIMER_VIRTUAL,ITIMER_PROF 的计时范围是 per-thread,而 POSIX 规定间隔 Timer 必须是 per-process 的。

比如某进程有 2 个线程,现在建立一个 2 秒到期的 ITIMER_VIRTUAL,假设第一个线程得到了 1 秒的 CPU 时间,此时线程 2 也得到了 1 秒的 CPU 时间。按照 POSIX 标准,此时定时器应该到期。但是根据我们前面所描述的原理,这个时候 ITIMER_VIRTUAL 并没有被触发。如果是在 Thread1 中调用 setitimer,则线程 2 的进程描述符中 it_virt_value 为 0,线程 1 进程描述符中的 it_virt_value 此时为 1 秒,还没有到期,因此进程则必须等到线程 1 运行到 2 秒才能触发这个定时器。这不符合 POSIX 标准,因此从 2.6.12 开始,对上述基本实现进行了一定的改进,虽然从原理上说,这个改进很小,但代码却有比较大的改变。

(编辑:佛山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读