更改系统时间对睡眠线程的影响是什么?

时间:2009-01-09 11:51:35

标签: posix sleep bsd clock

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

  • CLOCK_REALTIME - POSIX要求此信息存在。这是挂钟时间。

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

  • CLOCK_UPTIME - 我看不出它与CLOCK_MONOTONIC有什么不同(正常运行时间也从不跳回),但至少我知道当内核启动时此时钟从零开始(而它没有定义内核启动时CLOCK_MONOTONIC的初始值。

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

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

我已经从许多来源读到,这些功能实际上通过计算唤醒时间(获取当前时间,为其添加睡眠量)来工作,然后系统将定期检查当前时间是否为之后而不是唤醒时间,如果是,它将再次唤醒线程。仅在间隔时间内检查的事实是手册页说明当前睡眠将至少睡眠这段时间(仅在被信号中断时更短)的原因,但它可能会睡得更久(取决于多久)系统检查我们是否已经超过唤醒时间,并且取决于调度程序允许此线程再次运行所需的时间。)

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

根据各种来源,睡眠(至少纳米睡眠)在内部使用CLOCK_REALTIME作为时钟。这意味着,如果告诉nanosleep()睡眠30秒,然后将系统时钟更改为1小时,线程将立即唤醒(未来1小时远远超过唤醒时间nanosleep( )计算)。这也完全没问题。 然而如果我说在30秒内醒来然后用户发现他的系统时钟提前一小时并将他的时钟倒退一小时会发生什么?然后我的线程会睡1小时30秒?因为那会很糟糕。

2 个答案:

答案 0 :(得分:3)

据我所知,睡眠功能通常更像是递减计数器。你说“睡10秒”,转换成调度程序中的“睡眠1000个计划滴答”,然后每次调度程序检查睡眠进程时,它会减少剩余的时间。

通过这种方式,睡眠时间将始终是实际睡眠时间,而不是在将来的某个时间睡觉。这是因为你怀疑,如果我们将来选择一个时间,我们可能永远不会到达那里(或者可能在意想不到的时间内到达那里)。这与您希望在程序中使用sleep一致。这并不意味着做类似日历的计算。

你也可以进行一个简单的测试,使程序休眠30秒,使用nix“time”命令计算函数运行的时间,并在它开始后将系统时钟改回5分钟,看看会发生什么。

答案 1 :(得分:2)

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