Loading

不受系统时钟跳变影响的精确睡眠

需求

多线程编程需要控制某个线程的执行频率,嵌入式平台部署时会出现频率不稳定的问题且无法在x86复现。
排查出代码采用了系统内建的std::this_thread::sleep_for()函数,会受到系统时钟跳变的影响。
希望使用一个单调递增的时钟作为参考进行休眠。

实现

Google建议我们可以利用<sys/time.h>提供的select方法完成精确睡眠,简化后代码如下:

#include <sys/time.h>

void sleep(long int ms)
{
    struct timeval delay;
    delay.tv_sec = static_cast<long int>(ms / 1000);
    delay.tv_usec = static_cast<long int>((ms - delay.tv_sec * 1000) * 1000);
    (void) select(0, NULL, NULL, NULL, &delay);
}

内核hrtimer.c指出select在内核中使用的CLOCK_MONOTONIC(见参考文献2),即它的休眠不受时间同步影响。

int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
				     const enum hrtimer_mode mode)
{
	return schedule_hrtimeout_range_clock(expires, delta, mode,
					      CLOCK_MONOTONIC);
}

关于CLOCK_MONOTONIC的解释可以在man clock_gettime找到:

CLOCK_MONOTONIC
Clock that cannot be set and represents monotonic time since some unspecified starting point. This clock is not affected by discontinuous jumps in the system time (e.g., if the system administrator manually changes the clock), but is
affected by the incremental adjustments performed by adjtime(3) and NTP.

看来CLOCK_MONOTONIC的确是单调递增的,可以使用select进行精确休眠。

参考

clock_gettime(3): clock/time functions - Linux man page
linux/kernel/time/hrtimer.c at master · torvalds/linux
using select as a sleep call

posted @ 2023-10-18 14:16  azureology  阅读(77)  评论(0编辑  收藏  举报