web-dev-qa-db-ja.com

Windows、Linux、Solaris、HP-UX、IBM AIX、Vxworks、Wind River Linuxで数ミリ秒間眠っていますか?

Windows、Linux、Solaris、HP-UX、IBM AIX、Vxworks、Windriver Linuxなどのさまざまなプラットフォームで実行する必要があるミリ秒のスリープが必要なCプログラムを作成する必要があります

  • Windows では、Sleepシステムコールはミリ秒でのみ機能します。
  • Linux では、sleepは秒単位で機能します。 usleepはマイクロ秒単位で実行され、Solarisでも使用できます。
  • Vxworks では、taskDelaysysClkRateSetを使用して実装できることを願っています。

HP-UX、IBM AIX、およびWind River Linuxでこのミリ秒のスリープを実現するにはどうすればよいですか?

11
rashok

おそらく、プラットフォーム固有の#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
}

更新

以下のジョナサンのコメント を参照して、よりモダンで移植性の高い(そして修正された:})バージョンをここで見つけてください。

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

Usleepは廃止されましたが、nanosleepよりもはるかに単純です。そのため、スクリプトのデバッグ中に数秒から数ミリ秒またはゼロにプロダクション用に簡単に調整できる拡張スリープが必要なときに使用しました。

このスヌーズ機能は、sleepとusleepの利点を組み合わせたもので、intまたはfloatを入力して必要な遅延を得ることができ、0.1は10分の1秒スリープし、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 で示唆されているように、以下のバージョンは、呼び出されたスリープ関数のエラーを返します。構造体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);
}
2
John 9631

空のFDセットと必要なタイムアウトを含むselectを検討してください。から man select

一部のコードは、3秒すべての精度でスリープするためのかなり移植可能な方法として、3つのセットすべてが空、nfdsがゼロ、非NULLタイムアウトでselect()を呼び出します。

実際には、Windows以外のシステムに最適なソリューションである可能性があります。

2
Anton Kovalenko