【问题标题】:how linux's alarm() is handled by kernel内核如何处理linux的alarm()
【发布时间】:2014-03-16 13:32:06
【问题描述】:

我正在阅读有关 alarm() 调用如何在 linux 上工作的信息。
alarm(5) 将在至少 5 秒内向进行此调用的进程发送 SIGALRM
由于内核设置的递减计数器达到零,警报是在那个时刻引起的。
我的疑问在这里——我们可以有 N 个进程发出警报,并且系统中有一个可用于此目的的递减计数器。因此内核必须使用一个向下计数器来跟踪它必须向其发送信号的所有进程。它是怎么做到的?

[它是否维护一个排序的链表,每个节点都表示过程?]

【问题讨论】:

    标签: linux timer linux-kernel system-calls alarm


    【解决方案1】:

    我不是 Linux 内核开发人员,但鉴于 alarm()man-page,您已经可以预料到它是如何实现的。

    首先,很明显警报值是每个进程的。由于内核已经保存了每个进程的数据结构(task_struct),它只是在其中存储了所需的警报时间。然后 Linux 只是使用它的内部定时器系统在指定的时间注册一个回调。然后,所述回调将 SIGALRM 传递给您的进程。

    警报不需要内核全局状态或链接的显式链接列表。内核只是简单地保存一个进程列表并将警报超时存储为每个进程数据的一部分。

    如果你想深入挖掘,调用树看起来像这样:

    进一步挖掘,Linux 高分辨率内核计时器系统做了很多事情,例如区分实时(如果有人更改计算机上的时间/日期,可能会倒退)和单调时间。请查看this LWN article 了解概览。

    出于这个问题的目的,它在内部保留了一个按到期时间排序的计时器列表(即将到期的计时器首先到期,之后到期的计时器最后)。出于性能原因,这不是作为双向链表实现的,而是作为red-black tree 实现的。在处理完任何回调后,hrtimers 查看其列表,选择第一个条目(最快到期的计时器),然后告诉底层硬件计时器及时中断以服务下一个事件。发生这种情况时,hrtimers 会调用相关的回调,并重复该过程。

    所以有定时器列表(实现为树),但没有明确的递减计数器,这部分是通过硬件定时器处理的。这部分源代码的主要参考是enqueue_hrtimer()

    【讨论】:

    • 但是回调是如何在需要的时间触发的呢?有一个向下计数器。但是内核管理的这么多进程的这么多警报是怎么来的呢?这是我的疑问!
    • 查看内核源代码树中的文件kernel/time/alarmtimer.c(也可能是include/linux/timerqueue.h)。通常没有什么比阅读源代码更好的了。
    • 如果我可以毫无问题地阅读所有内核源代码,那将会很有帮助!如果我现在开始阅读它,那么我可能会更加困惑。
    • 我更新了我的答案,以深入了解 hrtimers 本身的工作方式。希望这能回答您的问题。
    猜你喜欢
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    相关资源
    最近更新 更多