- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想知道 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/
我正在尝试在 Linux 中使用库插入来 Hook 函数调用。我捕捉得很好,但有些情况我遗漏了……其中一个是 nanosleep()。我正在挂接的二进制文件每隔一秒就会使用此函数使线程休眠...如果我
我正在查看来自嵌入式 MIPS Linux 应用程序的核心转储。 GDB 正在报告 SIGBUS,并且处理信号的线程似乎位于 nanosleep 的系统调用中 - 更高级别的代码基本上称为 sleep
我有一个使用 nanosleep 的程序(混合了 C 和 Fortran,虽然这似乎不相关)。但是,如果我的 timespec 的 tv_sec 值为 0,它就不会休眠。 tv_nsec 值可能比整秒
在我的工作场所中的并发代码中,多次发生具有非零常量的nanosleep()或usleep(),以释放CPU而不依赖于futex(),或者使用 sleep 同步原语使线程进入休眠状态(例如例如,等待并发
我需要使用 nanosleep我的用户空间线程库中的函数来实现大约所需数量的等待,因为它可以在异步信号中断的情况下节省剩余时间。我使用 SIGALRM 抢先切换线程;因此,重要的是要考虑使用不可重入函
我编写了以下代码,以 0.3 秒的间隔逐个字符地打印段落。但是当我编译并运行它时,它会在句子中打印所有内容。为什么纳秒函数不起作用? #include #include #include #in
我在 while 循环中有一个 nanosleep 函数。这是我在《Linux系统编程:直接与内核和C库对话》一书中找到的一个例子 while(nanosleep(a, b) && errno
这段代码会做什么? struct timespec wait; wait.tv_sec = 0; wait.tv_nsec = 0; nanosleep(&wait, NULL); 或 ... c
我想知道 sleep/nanosleep 内部是如何实现的?考虑这段代码: { // on a thread other than main() thread while(1) { /
我正在使用 nanosleep 将进程停止一段时间。如何在要求的时间之前中断 nanosleep?谢谢! 最佳答案 如@Kerrek SB 所述,设置一个信号处理程序来处理 SIGUSR1,使用 ki
我注意到一个调用 nanosleep 的小测试程序在内核高于 2.6.22 的 Linux 机器上运行时显示 CPU 使用率的巨大差异。 #include int main (void) {
Unix 有多种 sleep API(sleep、usleep、nanosleep)。我所知道的唯一用于 sleep 的 Win32 函数是 Sleep(),它以毫秒为单位。 我看到大多数 sleep
我正在尝试在我的代码中测试 nanosleep 的性能。当我调用 nanosleep 并在 0 秒和 0 纳秒内传递时,与甚至不调用 nanosleep 相比,我得到了不同的值。如果我用 0 作为参数
我想在我的代码中用 nanosleep 替换过时的 usleep 函数: static int timediff( struct timeval *large, struct timeval *sma
我在使用 Linux 的 nanosleep 系统调用时遇到了一些问题。这段代码应该在退出前等待 2 秒,但它并没有: .text .globl _start _start: pushq %rbp m
我在 g++ 中编译了以下测试,nanosleep 太长了,它需要 60 微秒完成,我预计它只花费不到 1 微秒: int main() { gettimeofday(&startx, NUL
我想用我的 RaspberryPi 3 驱动步进电机。我需要每秒生成大约 10000 个脉冲,这意味着我需要以大约 100us 的间隔生成脉冲。我知道 Raspberry 可以生成 PWM,但事实并非
我有一个 C 程序,它使用 for(;;) 从/向套接字执行接收/发送操作。循环和一个 select()监视文件描述符。我还需要这个程序每 80 毫秒向一个数据包发送一个数据包,我该如何实现呢?也许我
我有 2 个与 C 语言 Linux 系统编程相关的理论问题,关于 nanosleep 和进程破坏。 所以,第一个: 仅使用nanosleep就可以使CPU负载达到97%。例如,让我们考虑一个在子进程
这个问题在这里已经有了答案: How to use nanosleep for sleeping random amounts of time? (2 个答案) 关闭 8 年前。 我知道这是一个新手
我是一名优秀的程序员,十分优秀!