Cからミリ秒までの代替スリープ関数はありますか?


133

Windowsでコンパイルされたいくつかのソースコードがあります。Red Hat Linuxで実行できるように変換しています。

ソースコードには<windows.h>ヘッダーファイルが含まれており、プログラマーはSleep()関数を、ミリ秒の時間待機しました。これはLinuxでは機能しません。

ただし、sleep(seconds)関数は使用できますが、秒単位の整数を使用します。ミリ秒を秒に変換したくありません。Linuxでのgccコンパイルで使用できる代替スリープ機能はありますか?


sleep(/*seconds*/)<unistd.h>私が使用している場合は動作しますが、printf("some things")なしで\n、そのではない動作します。
EsmaeelE 2017年

この場合に使用するには、出力をfflush(stdout);毎回フラッシュする必要があり ますprintf()
EsmaeelE 2017年

回答:


179

はい-古いPOSIX標準が定義されているusleep()ため、これはLinuxで使用できます。

   int usleep(useconds_t usec);

説明

usleep()関数は、呼び出しスレッドの実行を(少なくとも)usecマイクロ秒一時停止します。スリープは、システムアクティビティ、呼び出しの処理に費やした時間、またはシステムタイマーの細分性によって、少し長くなる場合があります。

usleep()マイクロ秒かかるため、ミリ秒単位でスリープするには、入力に1000を掛ける必要があります。


usleep()その後廃止され、その後POSIXから削除されました。新しいコードの場合、nanosleep()推奨されます:

   #include <time.h>

   int nanosleep(const struct timespec *req, struct timespec *rem);

説明

nanosleep()少なくともで指定された時間*reqが経過するか、呼び出しスレッドのハンドラーの呼び出しをトリガーするかプロセスを終了するシグナルの配信が完了するまで、呼び出しスレッドの実行を中断します。

構造timespecは、ナノ秒の精度で時間間隔を指定するために使用されます。次のように定義されます。

       struct timespec {
           time_t tv_sec;        /* seconds */
           long   tv_nsec;       /* nanoseconds */
       };

msleep()を使用して実装された関数の例nanosleep()は、シグナルによって中断された場合にスリープを継続します。

#include <time.h>
#include <errno.h>    

/* msleep(): Sleep for the requested number of milliseconds. */
int msleep(long msec)
{
    struct timespec ts;
    int res;

    if (msec < 0)
    {
        errno = EINVAL;
        return -1;
    }

    ts.tv_sec = msec / 1000;
    ts.tv_nsec = (msec % 1000) * 1000000;

    do {
        res = nanosleep(&ts, &ts);
    } while (res && errno == EINTR);

    return res;
}

19
なぜ複雑な関数の代わりに単純な関数を非推奨にし続けるのですか?nanosecond()で頭を悩ます代わりに、当分の間usleepを使用することもできます。

52

このクロスプラットフォーム機能を使用できます:

#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>   // for nanosleep
#else
#include <unistd.h> // for usleep
#endif

void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
    Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
#else
    usleep(milliseconds * 1000);
#endif
}

3
またはの_POSIX_C_SOURCE >= 199309Lように、がない場合は、の代わりに使用することをお勧めします。ここにクレジットが入ります-ansi-std=c89struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = milliseconds % 1000 * 1000; select(0, NULL, NULL, NULL, &tv);usleep(milliseconds * 1000);
Josh Sanford

正解です。ここにnanosleep()ドキュメントがあります:man7.org/linux/man-pages/man2/nanosleep.2.html。ここで使用される各プラットフォーム固有の関数のドキュメントリンクを投稿すると便利です。
Gabriel Staples

gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_testLinux Ubuntuで、gccバージョン4.8.4 を使用してコンパイルすると、次の警告が表示されることにも注意してくださいwarning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]。解決策は、コードの最上部に次の2つの定義追加することです: 1)#define __USE_POSIX199309および2)#define _POSIX_C_SOURCE 199309L。警告なしでコードをコンパイルするために(そして、コードが利用可能な関数を使用するためにも)両方が必要ですnanoseconds()
Gabriel Staples

関連する回答私が作成したばかり:stackoverflow.com/a/55860234/4561887
Gabriel Staples

32

usleep()POSIX 2008で定義されていない(POSIX 2004まで定義され、POSIX準拠の歴史を持つLinuxおよびその他のプラットフォームで使用可能であることは明らかですが)の代わりに、POSIX 2008標準は以下を定義しますnanosleep()

nanosleep -高解像度の睡眠

#include <time.h>
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);

このnanosleep()関数は、rqtp引数で指定された時間間隔が経過するか、シグナルが呼び出し側スレッドに配信されるまで、現在のスレッドの実行を一時停止します。そのアクションは、シグナルキャッチ関数の呼び出しまたはプロセスの終了です。引数の値がスリープ解決の整数倍に切り上げられるため、またはシステムによる他のアクティビティのスケジュールのため、一時停止時間が要求よりも長くなることがあります。ただし、信号によって中断された場合を除いて、一時停止時間はrqtp、システムクロックCLOCK_REALTIMEで測定された、で指定された時間以上でなければなりません。

このnanosleep()関数を使用しても、信号のアクションや妨害には影響しません。


24

向こうはusleep、謙虚に選択あなたはマイクロ秒の精度で一時停止し、かつリスクなしようになるNULLのファイルディスクリプタセットでSIGALRM合併症。

sigtimedwaitとsigwaitinfoは同様の動作を提供します。


1
「シガラームのリスクなし」:どのリスクとどのケース?sleepとusleepを呼び出しますか?
Massimo

2
@Massimo、用リンク仕様はusleepは、不特定SIGALARM行動上のいくつかの文章を持っています。(基本的に、usleepsleepは、usleepとSIGALARMの安全な使用を複雑にすることが想像できる古いアラームメカニズムを介して実装することが許可されています。この方法でこれを行う最新のシステムは知りませんが、まだ仕様)
ピルクロウ2018年


-7
#include <stdio.h>
#include <stdlib.h>
int main () {

puts("Program Will Sleep For 2 Seconds");

system("sleep 2");      // works for linux systems


return 0;
}

1
これはミリ秒の間スリープせず、オーバーヘッドが大幅に増えるため、タイミングの信頼性がさらに低下します。
Devolus、

1
例は、マイクロ秒の間スリープしません。さらに、これは、usleep()のようなものを使用するだけの場合と比較して、それほど良い解決策ではありません。
Victor Ocampo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.