【问题标题】:Is usleep() in C implemented as busy wait?C 中的 usleep() 是否实现为忙等待?
【发布时间】:2011-12-30 16:38:03
【问题描述】:

我正在使用pthreads 构建一个多线程应用程序,并且需要一个线程来定期检查一些东西。在此线程之间的时间不应使用任何 CPU。 usleep() 可以做到这一点吗? usleep() 不忙吗?还是有更好的解决方案?

【问题讨论】:

  • 我认为 pthreads 有一个可能有用的yield() 功能。
  • usleep与C语言无关,它是操作系统的特性。
  • @KerrekSB:pthread_yield 不会降低 CPU 使用率,只会导致线程相对于具有相同优先级的其他线程暂时降低优先级。

标签: c posix


【解决方案1】:

函数 usleep 已从 SUSv4 中删除。您可能应该改用nanosleep 或计时器(setitimer 等)。

正如 R.. 在 cmets 中所指出的,睡眠是否应该实现为忙等待:

  • 线程将继续使用 CPU
  • 其他(低优先级)线程将没有机会运行

因此:

  • 有些可能会使用信号(我认为 SUSv3 提到了 SIGALARM?)
  • 有些人可能会使用花哨的计时器

【讨论】:

  • usleep 不是 C 库的一部分,AFAIK。
  • @JensGustedt 这不是标准的。但是libc(glibc、bsd libc 等)通常有它。所以,如果有人拥有它,那就是 C 库。
  • 标准但 POSIX :)
  • @JensGustedt kernel.org 提到它不在 SUSv4 中。在 SUSv4 中搜索它一无所获。
  • 它不能实现为忙等待,因为这会阻止其他低优先级线程/进程运行。
【解决方案2】:

usleep 不是 C 标准的一部分,而是古老的 POSIX 标准的一部分。但请参见下文。)

不,usleep 的 POSIX 规范明确指出

usleep() 函数会导致调用线程被挂起 从执行...

所以这显然要求它暂停执行并将资源分配给其他进程或线程。

正如其他人已经提到的,POSIX 函数nanosleep 现在正在替换usleep,您应该使用它。 C(因为C11)有一个函数thrd_sleep,它模仿nanosleep

【讨论】:

    【解决方案3】:

    请注意,usleep() 和 nanosleep() 都可以被信号中断。 nanosleep() 允许您传入一个额外的 timespec 指针,如果发生这种情况,剩余时间将被存储在其中。所以如果你真的需要保证你的延迟时间,你可能想写一个简单的 nanosleep() 包装器。

    请注意,这没有经过测试,而是类似以下内容:

    int myNanoSleep(time_t sec, long nanosec)
    {
       /* Setup timespec */
       struct timespec req;
       req.tv_sec = sec;
       req.tv_nsec = nanosec;
    
       /* Loop until we've slept long enough */
       do 
       {
          /* Store remainder back on top of the original required time */
          if( 0 != nanosleep( &req, &req ) )
          {
              /* If any error other than a signal interrupt occurs, return an error */
              if(errno != EINTR)
                 return -1; 
          }
          else
          {
              /* nanosleep succeeded, so exit the loop */
              break;
          }
       } while( req.tv_sec > 0 || req.tv_nsec > 0 )
       return 0; /* Return success */
    }
    

    如果您需要在周期性超时以外的情况下唤醒线程,请查看条件变量和pthread_cond_timedwait()

    【讨论】:

    • 这一直很有趣,因为在 POSIX 睡眠函数中,请求的时间不仅不是上限(因为,与其他操作系统一样,系统可以根据需要随时重新安排线程),但由于信号,甚至不是下限。本质上,类似睡眠的函数可以在他们最喜欢的时候返回。 :-D
    【解决方案4】:

    在 Linux 上,它是通过 nanosleep system call 实现的,这不是忙等待。

    使用strace,我可以看到对usleep(1) 的调用被转换为nanosleep({0, 1000}, NULL)

    【讨论】:

      【解决方案5】:

      usleep() 是基于系统计时器构建的 C 运行时库函数。
      nanosleep() 是系统调用。

      只有 MS-DOS 和类似的,将睡眠功能实现为忙等待。任何提供多任务处理的实际操作系统都可以轻松地提供睡眠功能,作为协调任务和进程的机制的简单扩展。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-17
        • 2011-12-08
        • 2021-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-30
        相关资源
        最近更新 更多