我正在阅读 alarm()调用如何在linux上运行。
alarm(5)会在至少5秒内向进行此调用的进程发送 SIGALRM 。
由于内核设置为零的向下计数器,此时会发出警报。
我的疑问在这里 - 我们可以有N个进程进行报警,并且系统中有一个可用于此目的的计数器。所以内核必须跟踪一个向下计数器发送信号所需的所有进程。它是如何做到的?
[它是否维护一个排序链表,每个节点都表示该过程?]
答案 0 :(得分:2)
我没有Linux内核开发人员,但鉴于alarm()
的{{3}},您已经可以预期它是如何实现的。
首先,很明显警报值是每个进程。由于内核已经保留了每个进程的数据结构(man-page),因此它只在那里存储了所需的警报时间。然后Linux只使用其内部计时器系统在指定时间注册回调。然后,所述回调将SIGALRM传递给您的流程。
不需要内核全局状态或警报的链接显式链接列表。内核只保留一个进程列表,并将警报超时存储为每个进程数据的一部分。
如果你想深入挖掘,调用树看起来像这样:
task_struct
task_struct->signal->real_timer
;然后通过电话进一步深入研究,Linux高分辨率内核计时器系统可以完成许多工作,例如:区分实时(如果有人改变计算机上的时间/日期,可能会倒退)和单调时间。请查看hrtimer_start()以获取概述。
出于这个问题的目的,它在内部保留了一个按到期时间排序的计时器列表(很快就会使计时器到期,之后到期计时器到期)。出于性能原因,这不是作为双向链表实现的,而是作为this LWN article实现的。在处理完任何回调之后,hrtimers查看其列表,选择第一个条目(最快到期定时器),然后告诉底层硬件定时器及时中断以服务下一个事件。当发生这种情况时,hrtimers会调用相关的回调,并重复该过程。
因此有定时器列表(实现为树),但没有明确的递减计数器,该部分通过硬件定时器处理。该部分源代码的主要参考是red-black tree。