闹钟或其他基于时间的应用程序如何工作?

闹钟或其他基于时间的应用程序如何工作?

我一直很奇怪,当我们在移动设备上设置闹钟时,它会不断检查系统时间并尝试将其与设置的值匹配。这样,闹钟可能会消耗大量的 CPU 电量,并使移动设备的性能变慢。

不仅警报应用程序,HTTP 服务器也会不断检查新请求,JavaScript 或任何其他语言中的事件监听器也会不断查找事件。还有更多。

这些过程需要大量的计算,那么它们是如何如此轻松地管理任务的呢?它们如何充分利用 CPU 并准确工作而不消耗太多 CPU 功率?

答案1

这些过程需要大量的计算,......

你的假设是错误的。
你的意思并不清楚“基于时间的应用程序”,但我会将程序概括为请求短时间(即少于一秒或最多几秒)的延迟(又称睡眠)或通知(又称信号),而不是长时间的延迟/暂停或通知,通常由未来的时钟时间和日历日期指定。
无论如何,处理通常减少到以计时器分辨率递减(并测试零)列表中的计数器,这是使用整数算法的简单计算。


程序延迟或短时间通知通常由相对于当前时间的时间间隔指定。这样的系统调用可以命名为延迟()或者睡觉()有变化如msleep()usleep()允许以秒或亚秒为单位指定持续时间。
这样的系统调用将创建一个计时器条目,其中持续时间被转换并存储为基于counttimer resolution在系统计时器的每次计时中,counter每个计时器条目的都会减一。counter变为零的表示计时器已过期,并且将执行相应进程的回调例程。

典型的 Linux 桌面上有一个勾号(又名赫兹) 和timer resolution10 毫秒。此计时器列表在系统计时器的每次计时中都会被处理(即递减和测试)。因此,任何时间请求都会有效地四舍五入到最接近的 0.01 秒。

Linux 在嵌入式应用中的使用促使了 的引入high-resolution timers,它利用了专用的定时器硬件。hrtimer 的分辨率可达 1 纳秒(当硬件支持时)。不是在每个时钟周期处理定时器列表,而是在每次到期时生成一个 hrtimer 中断。

在 Linux 系统上,请参阅文件/proc/timer_list用于计时器信息(例如分辨率),包括活动计时器条目。


程序延迟或长时间通知可以通过相对于当前时间或未来特定(即绝对)时间和日期的时间间隔来指定。长时间延迟和时钟事件的分辨率最好精确到秒,因此此类定时事件的处理每秒只需发生一次(即每分钟仅 60 次)。
如果所有定时事件都以按时间顺序排列的列表形式维护,并带有增量值,则每秒只需处理该列表中的第一项(而不是整个列表)。每秒所需的处理仅包括减少计数器并检查零值,即过期计时器。
[以上是我编写的嵌入式系统的描述。我不知道 Linux 如何处理相对时间与绝对时间以及短间隔与长间隔。]

请注意,Unix/Linux 传统上使用“自纪元以来的秒数”来表示时钟时间和日历日期,因此可以使用表示秒的整数值来操纵时间间隔或经过的时间或绝对时间(即时钟时间和日历日期)。时钟和日历计算是简单的整数算术运算。

微软 Windows 可能也使用了类似的方案。在内部以秒、分、时、日(月份)、月和年的形式维护时钟和日历信息会导致复杂的处理和潜在的软件缺陷。例如,基于 MStar 固件(用于 MStar 7816 SoC)的 DVR 产品都存在缺陷,会在午夜(即新的一天的开始)过早终止预定的录制。当时间和日期表示为秒的单个计数(自纪元以来)时,日期之间的转换变得透明/无关紧要,并且不会导致这样的午夜缺陷。


基于时间的作业调度程序,例如克伦德守护进程也不会“需要大量计算”。指定作业执行的时间分辨率是minute。换句话说,定时任务每分钟只需审查一次,守护进程会调用睡觉()来打发时间。除非系统超载,克伦德守护进程不会对处理器施加很大的负载。


前面的描述是使用软件处理时间事件,这需要系统有电并正在执行。但系统可能需要在硬件处于休眠/挂起状态时处理事件。对于这种情况,需要额外的硬件,一种典型的解决方案是使用具有独立电源(例如自己的电池)的实时时钟/日历(又名 RTC)。基本 RTC 可以在计算机系统关闭时保持时间。功能更强大的 RTC 将具有警报功能,可以指定未来的时间和日期来生成中断,进而可以利用该中断唤醒休眠系统。

相关内容