如果你看一下 时钟获取时间() 函数,在所有 BSD 中都可用,并且实际上被定义为 POSIX 标准的一部分,您会看到至少支持三种类型的时钟(许多系统支持比这些时钟更多的时钟,但实际上 POSIX 标准只要求一种存在,所有其他都是可选的):

  • 实时时钟 - POSIX 要求此内容存在。这是墙上的时钟。

  • 时钟单调 - 不知道这是什么(以及 SI 秒意味着什么),但我知道这个时钟永远不会向后跳,它只能单调增加值。

  • CLOCK_UPTIME - 我看不出这与 CLOCK_MONOTONIC 有什么不同(正常运行时间也永远不会向后跳),但至少我知道这个时钟在内核启动时从零开始(而它没有定义内核启动时 CLOCK_MONOTONIC 的初始值)

让我们暂时忽略其他时钟。CLOCK_REALTIME 不能保证单调向上计数,对吧?这是实际的“系统时间”。我可以随意更改系统时间。我可以将其设置为过去 3 个月或未来 5 年,每次我的系统使用网络上的 NTP 服务器同步时间时,时间可能会向前或向后跳跃。

现在我们在 BSD 系统中有两个睡眠函数。 睡觉()纳米睡眠(). 。我不确定,但我希望 sleep() 在 nanosleep 之上实现,毕竟我可以通过使用 nanosleep() 轻松模拟 sleep() 并且仅在 struct timespec 中设置秒数,保持纳秒为零。

我在许多来源读到,这些函数实际上是通过计算唤醒时间(获取当前时间,添加睡眠量)来工作的,然后系统将定期检查当前时间是否为 之后 比唤醒时间长,如果是,则会再次唤醒线程。事实上,这只是每隔一段时间检查一次,这就是为什么手册页说当前睡眠将至少睡眠这个时间(只有在被信号中断时才会更短),但它可能会睡眠更长时间(取决于频率)系统检查我们是否已经超过了唤醒时间,并取决于调度程序允许该线程再次运行之前需要多长时间)。

这对我来说完全是理智的......但有一个问题一直困扰着我:

根据各种来源,睡眠(至少是nanosleep)使用CLOCK_REALTIME作为内部时钟。这意味着,如果告诉 nanosleep() 休眠 30 秒,然后将系统时钟更改为未来 1 小时,线程将几乎立即唤醒(未来 1 小时远远早于唤醒时间 nanosleep( )计算)。这也完全没问题。 然而 如果我说 30 秒后唤醒,然后用户发现他的系统时钟提前一小时并将时钟向后设置一小时,会发生什么情况?那么我的线程会休眠1小时30秒?因为那样的话就比较糟糕了。

有帮助吗?

解决方案

据我所知,睡眠函数通常更像是一个递减计数器。您说“睡眠 10 秒”,这会在调度程序中翻译为“睡眠 1000 个计划周期”,然后每次调度程序检查睡眠进程时,都会减少剩余的时间。

这样,睡眠时间将始终是实际睡眠时间,而不是睡到未来某个时间。其原因正如您所怀疑的那样,如果我们选择未来的时间,我们可能永远不会到达那里(或者可能会在意想不到的时间内到达那里)。这与您希望在程序中使用睡眠的目的一致。它并不意味着进行类似日历的计算。

你还可以做一个简单的测试,让一个程序休眠30秒,使用nix“time”命令来计时该函数运行的时间,然后在它启动后将你的系统时钟调回5分钟,看看会发生什么。

其他提示

该线程将检查设置为睡眠持续时间而不是睡眠终点的内部计数器。使用的内部计数器与当前系统时间无关,因此系统时间发生变化不会受到影响。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top