gpt4 book ai didi

c++ - sleep/nanosleep 是否通过使用繁忙的等待方案来工作?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:26:59 26 4
gpt4 key购买 nike

我想知道 sleep/nanosleep 内部是如何实现的?考虑这段代码:

{ // on a thread other than main() thread
while(1)
{
//do something
sleep(1);
}
}

CPU 是否会进行持续的上下文切换以检查是否完成了 1 秒的 sleep (即内部忙等待)。

我怀疑它是这样工作的,效率太低了。但是它是如何工作的呢?

同样的问题也适用于 nanosleep。

注意:如果这是特定于实现/操作系统的,那么我如何才能实现一个不会导致持续上下文切换的更有效的方案?

最佳答案

实现 sleep()nanosleep() 的典型方法是将参数转换为操作系统调度程序使用的任何比例(同时四舍五入)并添加当前时间到它形成一个“绝对唤醒时间”;然后告诉调度程序在达到“绝对唤醒时间”之前不要给线程 CPU 时间。不涉及忙等待。

请注意,无论操作系统的调度程序使用什么规模,通常取决于可用的硬件和/或用于计时的硬件。它可以小于纳秒(例如,80x86 上的本地 APIC 用于“TSC 截止时间模式”)或大至 100 毫秒。

另请注意,操作系统保证延迟不会少于您要求的;但通常不能保证它不会更长,并且在某些情况下(例如,重负载系统上的低优先级线程)延迟可能比请求的大得多。例如,如果你要求休眠 123 纳秒,那么在调度程序决定它可以给你 CPU 时间之前你可能会休眠 2 毫秒,然后在调度程序实际给你 CPU 时间之前可能再睡 500 毫秒(例如,因为其他线程正在使用 CPU)。

一些操作系统可能会尝试减少这种“比请求的 sleep 时间长得多”的问题,而一些操作系统(例如为硬实时设计的)可能会提供某种保证(有限制 - 例如受线程优先级限制)最小延迟到期和恢复 CPU 之间的时间。为此,操作系统/内核会将参数转换为操作系统调度程序使用的任何比例(同时向下舍入而不是向上舍入)并且可能会减去一小部分“以防万一”;以便调度程序在请求的延迟到期之前(而不是之后)唤醒线程;然后当线程被赋予 CPU 时间时(在上下文切换到线程的成本之后,并且可能在预取线程保证使用的各种缓存行之后)内核将忙于短暂等待直到延迟实际到期。这允许内核将控制权交还给非常接近延迟到期的线程。

例如,如果您要求休眠 123 纳秒,那么调度程序可能不会给您 100 纳秒的 CPU 时间,然后它可能会花费 10 纳秒切换到您的线程,然后它可能会忙于等待剩余的 13 纳秒。即使在这种情况下(完成忙等待),它通常也不会忙等待整个延迟时间。然而,如果延迟非常短,内核只会做最后的忙等待。

最后,有一个特例可能值得一提。在 POSIX 系统上,sleep(0); 通常被滥用为 yield()。我不太确定这种做法的合法性 - 调度程序不可能支持类似 yield() 的东西,除非该调度程序愿意浪费 CPU 时间做不重要的工作,而更重要的工作等待。

关于c++ - sleep/nanosleep 是否通过使用繁忙的等待方案来工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30969481/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com