usleep()在C中实现为忙等待吗?

时间:2011-11-16 18:15:57

标签: c posix

我正在使用pthreads构建一个多线程应用程序,需要一个线程来定期检查一些东西。在此线程之间的时间内不应使用任何CPU。这可能是usleep()吗? usleep()没有忙等待吗?或者有更好的解决方案吗?

6 个答案:

答案 0 :(得分:12)

函数usleep已从SUSv4中删除。您应该使用nanosleep代替或定时器(setitimer等)。

作为评论中的R ..注释,睡眠是否应该作为忙碌的等待来实现:

  • 线程将继续使用CPU
  • 其他(较低优先级)线程无法运行

因此:

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

答案 1 :(得分:11)

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

不,usleep的POSIX规范明确指出

  

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

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

正如其他人已经提到的,POSIX函数nanosleep现在正在替换usleep,您应该使用它。 C(自C11起)具有在thrd_sleep之后建模的函数nanosleep

答案 2 :(得分:6)

请注意,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()

答案 3 :(得分:3)

在Linux上,它是使用nanosleep system call实现的,这不是繁忙的等待。

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

答案 4 :(得分:2)

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

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

答案 5 :(得分:0)

值得一提的是,WINE [lazily?]实现usleep作为对select()的调用:

#ifndef HAVE_USLEEP
int usleep (unsigned int useconds)
{
#if defined(__EMX__)
    DosSleep(useconds);
    return 0;
#elif defined(__BEOS__)
    return snooze(useconds);
#elif defined(HAVE_SELECT)
    struct timeval delay;

    delay.tv_sec = useconds / 1000000;
    delay.tv_usec = useconds % 1000000;

    select( 0, 0, 0, 0, &delay );
    return 0;
#else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
    errno = ENOSYS;
    return -1;
#endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
}
#endif /* HAVE_USLEEP */

值得一提的是,nanosleep(在GLIBC中)似乎只是一个空函数调用(其他任何东西,延迟可能会转移到微秒范围内)。

/* Pause execution for a number of nanoseconds.  */
int
__libc_nanosleep (const struct timespec *requested_time,
                  struct timespec *remaining)
{
  __set_errno (ENOSYS);
  return -1;
}