我正在使用pthreads
构建一个多线程应用程序,需要一个线程来定期检查一些东西。在此线程之间的时间内不应使用任何CPU。这可能是usleep()
吗? usleep()
没有忙等待吗?或者有更好的解决方案吗?
答案 0 :(得分:12)
函数usleep
已从SUSv4中删除。您应该使用nanosleep
代替或定时器(setitimer
等)。
作为评论中的R ..注释,睡眠是否应该作为忙碌的等待来实现:
因此:
答案 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;
}