【问题标题】:Sleeping for milliseconds on Windows, Linux, Solaris, HP-UX, IBM AIX, Vxworks, Wind River Linux?在 Windows、Linux、Solaris、HP-UX、IBM AIX、Vxworks、Wind River Linux 上休眠几毫秒?
【发布时间】:2013-01-26 13:26:36
【问题描述】:

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

  • Windows 上,Sleep 系统调用将仅在毫秒内工作。
  • 开启Linuxsleep 将在秒内工作; usleep 将在微秒内执行,它也可以在 Solaris 上使用。
  • Vxworks中,我希望我可以使用taskDelaysysClkRateSet来实现。

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

【问题讨论】:

  • usleep 是 POSIX,因此应该在所有 POSIX 兼容系统(如 HP/UX、AIX 等)中。虽然它被标记为过时,但有利于nanosleep,另一方面它被标记为可选。
  • 请注意,仅仅因为您可能会找到一种方法来表达 n 毫秒延迟,因此绝对不能保证主机操作系统会给予你正是你所要求的。您列出的操作系统通常不是实时的,因此他们很可能不会保证这样的事情;当您的延迟结束时,更高优先级的任务可能会占用 CPU。
  • 以下链接能回答您的问题吗? stackoverflow.com/questions/1157209/…

标签: c sleep system-calls milliseconds


【解决方案1】:

使用特定平台#defines 的包装器可能会做:

#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's comment below,请在此处找到更现代、更便携(以及更正:})的版本:

#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
}

【讨论】:

  • 在 POSIX 2004 下,usleep() 调用被标记为“过时”,并从 POSIX 2008 中删除。首选替代方法是 nanosleep()。 POSIX 的总体趋势是更喜欢具有纳秒分辨率的struct timespec,而不是只有微秒分辨率的struct timeval,或者不使用结构但也适用于微秒分辨率的usleep()。跨度>
  • @JonathanLeffler:感谢您的通知。已更正。
【解决方案2】:

考虑 select 与空 FD 集和您想要的超时。来自man select

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

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

【讨论】:

  • 感谢您的回复。目前我们只使用这个,在某些平台上select 不可用。像windriver linux select不可用。
  • @rashok 选择功能存在于 HP-UX 和 AIX 上。我对 Wind River Linux 上不存在它的说法感到惊讶。风河Linux就是Linux,怎么会少了select系统调用呢? (或其较新的替代品,newselect 或 pselect6)。
【解决方案3】:

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

此贪睡功能结合了睡眠和睡眠的优点,让您可以 输入一个 int 或 float 以获得所需的延迟,0.1 将睡眠十分之一 a second while 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);
}

【讨论】:

  • 为了完整起见,您可能需要注意使用的函数返回的值。
  • 感谢alk的建议。我添加了选项。
猜你喜欢
  • 2011-05-10
  • 2010-09-11
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2017-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多