11

我必须编写一个必须休眠几毫秒的 C 程序,它必须在 Windows、Linux、Solaris、HP-UX、IBM AIX、Vxworks 和 Windriver Linux 等各种平台上运行

  • Windows上,Sleep系统调用仅在毫秒内起作用。
  • Linux上,sleep将在几秒钟内工作;usleep将在微秒内执行,它也可以在 Solaris 上使用。
  • Vxworks中,我希望我可以使用taskDelayand来实现sysClkRateSet

如何在 HP-UX、IBM AIX 和 Wind River Linux 上实现毫秒级睡眠?

4

3 回答 3

16

使用特定于平台的 s 的包装器#define可能会:

#if defined(WIN32)
  #include <windows.h>
#elif defined(__UNIX__)
  #include <unistd.h>
#else
#endif

...

int millisleep(unsigned ms)
{
#if defined(WIN32)
  SetLastError(0);
  Sleep(ms);
  return GetLastError() ?-1 :0;
#elif defined(LINUX)
  return usleep(1000 * ms);
#else
#error ("no milli sleep available for platform")
  return -1;
#endif
}

更新

参考下面 Jonathan 的评论,请在此处找到更现代、更便携(以及更正:})的版本:

#if defined(WIN32)
  #include <windows.h>
#elif defined(__unix__)
  #include <time.h>
  #include <unistd.h>
#else
#endif

...

int millisleep(unsigned ms)
{
#if defined(WIN32)

  SetLastError(0);
  Sleep(ms);
  return GetLastError() ?-1 :0;

#elif _POSIX_C_SOURCE >= 199309L

  /* prefer to use nanosleep() */

  const struct timespec ts = {
    ms / 1000, /* seconds */
    (ms % 1000) * 1000 * 1000 /* nano seconds */
  };

  return nanosleep(&ts, NULL);

#elif _BSD_SOURCE || \
  (_XOPEN_SOURCE >= 500 || \
     _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
  !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)

  /* else fallback to obsolte usleep() */

  return usleep(1000 * ms);

#else

# error ("No millisecond sleep available for this platform!")
  return -1;

#endif
}
于 2013-02-11T18:49:34.260 回答
1

考虑select使用空的 FD 集和所需的超时。来自man select

一些代码调用 select() 时所有三个集合都为空,nfds 为零,并且非 NULL 超时作为一种相当可移植的亚秒精度睡眠方式。

实际上,它可能是任何非 Windows 系统的最佳解决方案。

于 2013-02-11T12:54:08.130 回答
1

我注意到 usleep 已经过时了,但它比 nanosleep 简单得多。因此,当我需要增强睡眠时,我会使用它,以便在调试脚本时轻松调整到毫秒或零以进行生产。

这个贪睡功能结合了 sleep 和 usleep 的优点,因此您可以输入 int 或 float 以获得所需的延迟,并且 0.1 将休眠 10 秒,而 3 将休眠 3 秒。3.5 秒被视为 3 秒。

在 Linux Mint 18.3 (Ubuntu 16.04.9) 上测试为 C 和 C++,使用 gcc 5.4.0。

#include <unistd.h>

void snooze(double t) {(t > 1.0) ? sleep(t) : usleep(t*1000000);}

snooze(0.01);  // call function to sleep for 10ms



为了完整起见,这是一个 nanosleep 版本。它可能比 usleep 版本更准确,并且不会受到过时的威胁。

#include <time.h>
#include <math.h>

void snooze(double t) {
    struct timespec req = {t, fmod(t, 1.0) * 1E9};
    nanosleep(&req, NULL);
}

// struct timespec req = {t, fmod(t, 1.0) * 1E9};
//  is equivalent to:
// struct timespec req = {0};
// req.tv_sec = t;
// req.tv_nsec = fmod(t, 1.0) * 1000000000L;

// NULL as value for *rem so no resumption after signal interrupts

snooze(1.99);  // call for delay of 1.99 seconds

正如@alk所建议的,以下版本在发生 1 时返回被调用的 sleep 函数的错误,如果成功则返回 0。定义结构 rem(aining) 还允许在信号中断后恢复。

int snooze(double t) {
    return (t > 1.0) ? sleep(t) : usleep(t*1000000);
}

int snooze(double t) {
    struct timespec req = {t, fmod(t, 1.0) * 1E9};
    struct timespec rem = {0, 0.0};
    return nanosleep(&req, &rem);
}
于 2018-04-28T03:48:33.293 回答