it-swarm.com.de

zeitverzögerung in c implementieren

Ich weiß nicht genau, wie ich eine Suche nach diesem Wort fassen soll

Ich muss eine Zeitverzögerung in C implementieren.

zum Beispiel möchte ich einige Sachen machen, dann 1 Minute warten, dann weiterarbeiten.

Hat das einen Sinn ergeben? Kann mir jemand helfen?

27
developer

In Standard C (C99) können Sie dazu time() verwenden, etwa:

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

Dies setzt übrigens voraus, dass time() einen Auflösungswert von 1 Sekunde zurückgibt. Ich denke nicht, dass dies durch den Standard vorgeschrieben ist, so dass Sie sich möglicherweise darauf einstellen müssen.


Zur Verdeutlichung ist dies die einzige Möglichkeit, die mir bei ISO C99 bekannt ist (und die Frage ist nur mit "C" gekennzeichnet, was normalerweise "portabel" bedeutet Lösungen sind wünschenswert, obwohl natürlich auch herstellerspezifische Lösungen angegeben werden können.

Wenn Sie sich auf einer Plattform befinden, die eine effizientere Möglichkeit bietet, sollten Sie sie verwenden. Wie mehrere Kommentare gezeigt haben, kann es bei einer engen Schleife wie dieser zu besonderen Problemen kommen im Hinblick auf CPU-Auslastung und Akkulaufzeit.

Jedes vernünftige Time-Slicing-Betriebssystem kann die dynamische Priorität einer Task verlieren, die ständig ihre Vollzeitscheibe ausnutzt, aber die Batterieleistung ist möglicherweise problematischer.

C gibt jedoch nichts über die Betriebssystemdetails in einer gehosteten Umgebung an, und diese Antwort gilt nur für ISO C und ISO C (daher werden sleep, select, Win32-API-Aufrufe usw. nicht verwendet so wie das).

Und denken Sie daran, dass POSIX sleep durch Signale unterbrochen werden kann. Wenn Sie diesen Weg gehen , müssen Sie Folgendes tun:

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

Auf den meisten Desktopsystemen können Sie Folgendes tun:

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

So können Sie dies auf einem Mikrocomputer/Prozessor ohne Timer tun:

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
}

Die Waitloop-Variablen müssen fein abgestimmt werden, die funktionierten für meinen Computer ziemlich gut, aber die Frequenzskala macht es für ein modernes Desktop-System sehr ungenau. Also nicht dort verwenden, es sei denn, du bist nackt im Metall und machst so etwas nicht.

15
Frank
9
user180100

Obwohl bei vielen Implementierungen die Funktion time die aktuelle Zeit in Sekunden zurückgibt, gibt es keine Garantie, dass jede Implementierung dies tut (z. B. geben einige Millisekunden anstelle von zurück Sekunden). Eine tragbarere Lösung ist daher die Verwendung der Funktion difftime .

difftime wird vom C-Standard garantiert, um die Zeitdifferenz in Sekunden zwischen zwei time_t-Werten zurückzugeben. Daher können wir eine tragbare Zeitverzögerungsfunktion schreiben, die auf allen kompatiblen Implementierungen des C-Standards ausgeführt wird.

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

Ein Nachteil bei den Funktionen time und difftime ist, dass der C-Standard niemals eine Granularität angibt. Die meisten Implementierungen haben eine Granularität von einer Sekunde. Während dies für Verzögerungen von einige Sekunden in Ordnung ist, kann unsere Verzögerungsfunktion auf Verzögerungen von unter einer Sekunde zu lange warten.

Es gibt eine portable Standard-C-Alternative: die clock-Funktion.

Die Funktion clock gibt die beste Näherung der Implementierung an die Prozessorzeit zurück, die das Programm seit Beginn einer durch die Implementierung definierten Ära verwendet, die nur für den Programmaufruf relevant ist. Um die Zeit in Sekunden zu bestimmen, sollte der von der clock -Funktion zurückgegebene Wert durch den Wert des Makros CLOCKS_PER_SEC geteilt werden.

Die clock-Funktionslösung ist unserer time-Funktionslösung ziemlich ähnlich:

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

In diesem Fall gibt es einen ähnlichen Vorbehalt wie time und difftime: Die Granularität der clock-Funktion bleibt der Implementierung überlassen. Beispielsweise können Maschinen mit 32-Bit-Werten für clock_t mit einer Auflösung in Mikrosekunden den von clock zurückgegebenen Wert nach 2147 Sekunden (etwa 36 Minuten) umbrechen.

Daher sollten Sie die time- und difftime-Implementierung der Verzögerungsfunktion für Verzögerungen von mindestens einer Sekunde und die clock-Implementierung für Verzögerungen von unter einer Sekunde verwenden.

Ein abschließendes Wort der Vorsicht: clock gibt Prozessorzeit statt Kalenderzeit zurück; clock stimmt möglicherweise nicht mit der tatsächlich verstrichenen Zeit überein (z. B. wenn der Prozess schläft). 

6
Vilhelm Gray

Für Verzögerungen von bis zu einer Minute ist sleep() eine gute Wahl.

Wenn Sie eines Tages bei Verzögerungen von weniger als einer Sekunde anhalten möchten, sollten Sie poll() mit einem Timeout in Betracht ziehen.

Beide sind POSIX.

3
mouviciel

sleep(int number_of_seconds) ausprobieren

1
waffle paradox

sleep(int) arbeitet als gute Verzögerung. Für eine Minute:

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

Es gibt keine sleep()-Funktionen in der C-Standardbibliothek, aber POSIX bietet einige Optionen.

Die POSIX-Funktion sleep() (unistd.h) verwendet ein unsigned int-Argument für die Anzahl der Sekunden, die für den Schlaf benötigt werden. Obwohl dies keine Standard Library-Funktion ist, ist sie allgemein verfügbar, und glibc scheint sie zu unterstützen, selbst wenn mit strengeren Einstellungen wie --std=c11 kompiliert wird.

Die POSIX-Funktion nanosleep() (time.h) führt zwei Zeiger auf timespec-Strukturen als Argumente und ermöglicht eine genauere Steuerung der Schlafdauer. Das erste Argument gibt die Verzögerungsdauer an. Wenn das zweite Argument kein Nullzeiger ist, enthält es die verbleibende Zeit, wenn der Aufruf durch einen Signalhandler unterbrochen wird.

Programme, die die nanosleep()-Funktion verwenden, müssen möglicherweise ein Feature-Test-Makro enthalten, um kompilieren zu können. Das folgende Codebeispiel kann auf meinem Linux-System nicht ohne ein Feature-Test-Makro kompiliert werden, wenn ein typischer Compiler-Aufruf von gcc -std=c11 -Wall -Wextra -Wpedantic verwendet wird.

POSIX hatte einmal eine usleep() - Funktion (unistd.h), die ein useconds_t-Argument benötigte, um die Schlafdauer in Mikrosekunden anzugeben. Diese Funktion erforderte auch ein Feature-Test-Makro, wenn sie mit strengen Compilereinstellungen verwendet wird. Leider wurde usleep() mit POSIX.1-2001 nicht mehr benötigt und sollte nicht mehr verwendet werden. Es wird empfohlen, nanosleep() jetzt anstelle von usleep() zu verwenden.

#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

// Stellt eine ANSI C-Methode zum Verzögern von x Millisekunden bereit

#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

sie können die delay () - Funktion einfach aufrufen. Wenn Sie also den Vorgang in 3 Sekunden verzögern möchten, rufen Sie die Verzögerung (3000) auf. 

0
Owen

Wenn Sie sicher sind, dass Sie warten möchten und niemals unterbrochen werden, verwenden Sie den Ruhezustand in POSIX oder den Ruhezustand in Windows. In POSIX dauert der Schlaf in Sekunden. Wenn Sie also weniger Zeit benötigen, gibt es Varianten wie usleep(), die Mikrosekunden verwenden. Der Ruhezustand in Windows dauert Millisekunden, selten benötigen Sie eine feinere Granularität.

Es kann sein, dass Sie eine gewisse Zeit warten möchten, jedoch Unterbrechungen zulassen möchten, möglicherweise im Notfall. Der Schlaf kann durch Signale unterbrochen werden. In diesem Fall gibt es jedoch eine bessere Methode.

Daher habe ich in der Praxis tatsächlich festgestellt, dass Sie mit einem Timeout auf ein Ereignis oder eine Zustandsvariable warten.

In Windows lautet Ihr Aufruf WaitForSingleObject. In POSIX ist es pthread_cond_timedwait.

In Windows können Sie auch WaitForSingleObjectEx verwenden, und Sie können Ihren Thread tatsächlich mit jeder in der Warteschlange befindlichen Task "unterbrechen", indem Sie QueueUserAPC aufrufen. WaitForSingleObject (Ex) gibt einen Code zurück, der bestimmt, warum es beendet wurde. Sie werden also wissen, wann der Status "TIMEDOUT" zurückgegeben wird, dass tatsächlich ein Timeout aufgetreten ist. Sie legen das Ereignis fest, auf das es wartet, wenn es beendet werden soll.

Mit pthread_cond_timedwait können Sie die Zustandsvariable Broadcast signalisieren. (Wenn mehrere Threads auf denselben Thread warten, müssen Sie Broadcasts senden, um sie alle aufzuwecken). Bei jeder Schleife sollte der Zustand überprüft werden. Ihr Thread kann die aktuelle Uhrzeit abrufen und feststellen, ob die Zeit abgelaufen ist, oder er kann feststellen, ob eine Bedingung erfüllt ist, um zu bestimmen, was zu tun ist. Wenn Sie eine Warteschlange haben, können Sie dies überprüfen. (Ihr Thread wird automatisch mit einem Mutex gesperrt, mit dem er auf die Bedingungsvariable gewartet hat. Wenn er also die Bedingung überprüft, hat er alleinigen Zugriff darauf).

0
CashCow