web-dev-qa-db-ja.com

cに時間遅延を実装します

これをWordで検索する方法が正確にわからないので、何も見つけることができませんでした。

Cで時間遅延を実装する必要があります。

例えば、私は何かをしたいので、1分待ってから続けます。

それは理にかなっていますか?誰も私を助けることができますか?

29
developer

標準C(C99)では、次のようなtime()を使用してこれを行うことができます。

_#include <time.h>
:
void waitFor (unsigned int secs) {
    unsigned int retTime = time(0) + secs;   // Get finishing time.
    while (time(0) < retTime);               // Loop until it arrives.
}
_

ところで、これはtime()が1秒の解像度値を返すと仮定しています。それが規格によって義務付けられているとは思わないので、調整する必要があるかもしれません。


明確にするために、これはonlyISO C99でこれを行うことを認識している方法です(そして、質問には " C "は通常、ポータブルソリューションが望ましいことを意味しますが、もちろん、ベンダー固有のソリューションも提供されます。

より効率的な方法を提供するプラットフォームを使用している場合は、必ず使用してください。いくつかのコメントが示しているように、特定の問題があるかもしれませんCPU使用率とバッテリー寿命に関して、このようなタイトループを使用します。

適切なタイムスライシングOSは、フルタイムスライスを継続的に使用するタスクの動的優先度を下げることができますが、バッテリーの電力はより問題になる可能性があります。

ただし、Cはホスト環境のOSの詳細についてnothingを指定しており、この回答はISO CおよびISO Cのみに対するものです(したがって、sleepselect、Win32 API呼び出しなど。

POSIX sleep は信号によって中断される可能性があることに注意してください。あなたがareその道を行く場合、あなたは次のようなことをする必要があります:

_int finishing = 0; // set finishing in signal handler 
                   // if you want to really stop.

void sleepWrapper (unsigned int secs) {
    unsigned int left = secs;
    while ((left > 0) && (!finishing)) // Don't continue if signal has
        left = sleep (left);           //   indicated exit needed.
}
_
37
paxdiablo

ほとんどのデスクトップシステムでこれを行う方法は次のとおりです。

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif

void wait( int seconds )
{   // Pretty crossplatform, both ALL POSIX compliant systems AND Windows
    #ifdef _WIN32
        Sleep( 1000 * seconds );
    #else
        sleep( seconds );
    #endif
}

int
main( int argc, char **argv)
{
    int running = 3;
    while( running )
    {   // do something
        --running;
        wait( 3 );
    }
    return 0; // OK
}

タイマーなしのマイクロコンピューター/プロセッサーでこれを行う方法は次のとおりです。

int wait_loop0 = 10000;
int wait_loop1 = 6000;

// for microprocessor without timer, if it has a timer refer to vendor documentation and use it instead.
void
wait( int seconds )
{   // this function needs to be finetuned for the specific microprocessor
    int i, j, k;
    for(i = 0; i < seconds; i++)
    {
        for(j = 0; j < wait_loop0; j++)
        {
            for(k = 0; k < wait_loop1; k++)
            {   // waste function, volatile makes sure it is not being optimized out by compiler
                int volatile t = 120 * j * i + k;
                t = t + 5;
            }
        }
    }
}

int
main( int argc, char **argv)
{
    int running = 3;
    while( running )
    {   // do something
        --running;
        wait( 3 );
    }
    return 0; // OK
}

Waitloop変数は微調整する必要があります。これらは私のコンピューターにかなり近い動作をしましたが、周波数スケールの問題により、現代のデスクトップシステムでは非常に不正確になります。したがって、金属にむき出しになっていて、そのようなことをしていない限り、そこでは使用しないでください。

16
Frank

sleep(3)manページ または スリープ用のMSDN を確認してください

9
user180100

多くの実装には time 関数があり、現在の時刻をsecondsで返しますが、すべての実装がno保証である(たとえば、secondsではなくmillisecondsを返す場合があります)。そのため、よりポータブルなソリューションは、 difftime 関数を使用することです。

difftimeは、2つのtime_t値間の時間差をsecondsで返すために、C標準によって保証されています。そのため、C標準のすべての準拠実装で実行されるポータブル時間遅延関数を作成できます。

#include <time.h>

void delay(double dly){
    /* save start time */
    const time_t start = time(NULL);

    time_t current;
    do{
        /* get current time */
        time(&current);

        /* break loop when the requested number of seconds have elapsed */
    }while(difftime(current, start) < dly);
}

timeおよびdifftime関数の注意点の1つは、C標準が粒度を指定しないことです。ほとんどの実装の粒度はone secondです。これは数秒続く遅延に対しては問題ありませんが、遅延関数は1秒未満続く遅延に対してあまりにも長く待機する場合があります。

移植可能な標準Cの代替手段であるclock関数があります。

clock関数は、プログラムの呼び出しのみに関連する実装定義の時代の始まり以来、プログラムが使用するプロセッサ時間の実装の最適な近似値を返します。秒単位の時間を決定するには、clock関数によって返される値をマクロCLOCKS_PER_SECの値で除算する必要があります。

clock関数ソリューションは、time関数ソリューションと非常によく似ています。

#include <time.h>

void delay(double dly){
    /* save start clock tick */
    const clock_t start = clock();

    clock_t current;
    do{
        /* get current clock tick */
        current = clock();

        /* break loop when the requested number of seconds have elapsed */
    }while((double)(current-start)/CLOCKS_PER_SEC < dly);
}

この場合、timeおよびdifftimeと同様の注意事項があります。clock関数の粒度は実装に任されます。たとえば、microsecondsの解像度を持つclock_tの32ビット値を持つマシンは、2147秒(約36分)後にclockによって返される値をラップする可能性があります。

したがって、少なくとも1秒持続する遅延にはtimeおよびdifftime遅延関数の実装を使用し、持続する遅延にはclock実装を使用することを検討してください1秒未満

最後の注意事項:clockは、calendar timeではなく、processor timeを返します。 clockは、実際の経過時間と一致しない場合があります(プロセスがスリープする場合など)。

6
Vilhelm Gray

1分の遅延の場合、sleep()が適切な選択です。

いつか、1秒未満の遅延で一時停止する場合は、poll()をタイムアウトで考慮することをお勧めします。

どちらもPOSIXです。

3
mouviciel

sleep(int number_of_seconds)を試してください

1
waffle paradox

sleep(int)は良い遅延として機能します。少しの間:

//Doing some stuff...
sleep(60); //Freeze for A minute
//Continue doing stuff...
1
thyrgle

C標準ライブラリにはsleep()関数はありませんが、POSIXにはいくつかのオプションがあります。

POSIX関数 sleep() (unistd.h)は、スリープに必要な秒数の_unsigned int_引数を取ります。これは標準ライブラリ関数ではありませんが、広く利用可能であり、glibcは_--std=c11_のようなより厳密な設定でコンパイルする場合でもサポートするようです。

POSIX関数 nanosleep() (time.h)は、timespec構造体への2つのポインターを引数として取り、スリープ期間をより細かく制御します。最初の引数は遅延時間を指定します。 2番目の引数がNULLポインターでない場合、呼び出しがシグナルハンドラーによって中断された場合の残り時間を保持します。

nanosleep()関数を使用するプログラムは、コンパイルするために feature test macro を含める必要がある場合があります。 _gcc -std=c11 -Wall -Wextra -Wpedantic_の典型的なコンパイラー呼び出しを使用すると、機能テストマクロがないと、次のコードサンプルはLinuxシステムでコンパイルされません。

POSIXには、かつてマイクロ秒単位でスリープ期間を指定する_useconds_t_引数を取る usleep() 関数(unistd.h)がありました。この関数は、厳密なコンパイラ設定で使用する場合、機能テストマクロも必要としました。残念ながら、usleep()はPOSIX.1-2001で廃止されたため、使用すべきではありません。 nanosleep()の代わりにusleep()を使用することをお勧めします。

_#define _POSIX_C_SOURCE  199309L     // feature test macro for nanosleep()

#include <stdio.h>
#include <unistd.h>    // for sleep()
#include <time.h>      // for nanosleep()

int main(void)
{
    // use unsigned sleep(unsigned seconds)
    puts("Wait 5 sec...");
    sleep(5);

    // use int nanosleep(const struct timespec *req, struct timespec *rem);
    puts("Wait 2.5 sec...");
    struct timespec ts = { .tv_sec = 2,          // seconds to wait
                           .tv_nsec = 5e8 };     // additional nanoseconds
    nanosleep(&ts, NULL);
    puts("Bye");

    return 0;
}
_
1
David Bowling
0
ruslik

// xミリ秒遅延するANSI Cメソッドを提供します

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void delayMillis(unsigned long ms) {
    clock_t start_ticks = clock();
    unsigned long millis_ticks = CLOCKS_PER_SEC/1000;
    while (clock()-start_ticks < ms*millis_ticks) {
    }
}    

/* 
 * Example output:
 * 
 * CLOCKS_PER_SEC:[1000000]
 * 
 * Test Delay of 800 ms....
 * 
 * start[2054], end[802058], 
 * elapsedSec:[0.802058]
 */
int testDelayMillis() {

    printf("CLOCKS_PER_SEC:[%lu]\n\n", CLOCKS_PER_SEC);
    clock_t start_t, end_t;
    start_t = clock();
    printf("Test Delay of 800 ms....\n", CLOCKS_PER_SEC);
    delayMillis(800); 
    end_t = clock();
    double elapsedSec = end_t/(double)CLOCKS_PER_SEC;
    printf("\nstart[%lu], end[%lu], \nelapsedSec:[%f]\n", start_t, end_t, elapsedSec);

}

int main() {    
    testDelayMillis();
}
0
Craig D

単純にdelay()関数を呼び出すことができます。したがって、プロセスを3秒で遅延させたい場合は、delay(3000)を呼び出します...

0
Owen

確実に待機し、決して中断されない場合は、POSIXでスリープを使用するか、Windowsでスリープを使用します。 POSIXスリープでは秒単位の時間がかかるため、時間を短くしたい場合は、マイクロ秒を使用するusleep()などの種類があります。 Windowsでのスリープには数ミリ秒かかりますが、それより細かい粒度が必要になることはまれです。

しばらく待機したいが、おそらく緊急の場合に割り込みを許可したい場合があります。スリープはシグナルによって中断される可能性がありますが、この場合はより良い方法があります。

したがって、実際には、イベントで待機するか、タイムアウトを伴う条件変数であることが実際にわかっています。

Windowsでは、呼び出しはWaitForSingleObjectです。 POSIXでは、pthread_cond_timedwait

Windowsでは、WaitForSingleObjectExを使用することもできます。その後、QueueUserAPCを呼び出すことにより、キューに入れられたタスクで実際にスレッドを「中断」できます。 WaitForSingleObject(Ex)は、終了した理由を特定するコードを返すため、「タイムアウト」ステータスが返されたときに、実際にタイムアウトしたことがわかります。終了したいときに待機するイベントを設定します。

pthread_cond_timedwait条件変数のブロードキャストを通知できます。 (複数のスレッドが同じスレッドで待機している場合、それらをすべて起動するためにブロードキャストする必要があります)。ループするたびに、状態を確認する必要があります。スレッドは現在の時刻を取得して、経過したかどうかを確認したり、何らかの条件が満たされているかどうかを確認して、何をすべきかを判断したりできます。何らかの種類のキューがある場合は、確認できます。 (スレッドは、条件変数で待機するために使用されるmutexを自動的にロックするため、条件をチェックするときに、そのスレッドにアクセスするだけです)。

0
CashCow