www.mikrocontroller.net

Forum: PC-Programmierung Zeitverzögerung in C


Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich möchte gerne auf einem PC eine Zeitverzögerung von n Sekunden haben, 
so kriegt man es wohl hin aber dann wartet der Rechner aktiv oder? Wie 
macht man es besser?

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

#define WARTEZEIT 5 /* Wartezeit in Sekunden */

int main()
{
  time_t start_seconds;
  time_t current_seconds;

  start_seconds = time (NULL);
  current_seconds = start_seconds;
  printf ("Starting seconds: %d\n", (int)start_seconds);

  while( current_seconds < start_seconds + WARTEZEIT) /* busy waiting */
    current_seconds = time (NULL);
  printf("current_seconds = %d\n%d seconds elapsed", (int)current_seconds, WARTEZEIT);

  return 0;
}

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sleep(5000);

oder bei linux muss/kann man es mit poll oder select machen.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf POSIX-Systemen:
#include <unistd.h>

...
sleep(5);

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das gibt es anscheinend nicht unter Windows/MinGW? :-(

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Das gibt es anscheinend nicht unter Windows/MinGW? :-(

glaube ich nicht.

http://msdn.microsoft.com/en-us/library/ms686298%2...

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also _sleep() scheint es zu geben, aber er meint trotzdem "implicit 
declaration of function", ist also wohl nicht im unistd.h drin obwohl 
dieser existiert?

Autor: eklige Tunke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Das gibt es anscheinend nicht unter Windows/MinGW? :-(
Doch laut Beitrag "MinGW (CodeBlocks 8.02) : sleep()" gibt es Sleep() 
[großes S] in der windows.h.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Das gibt es anscheinend nicht unter Windows/MinGW? :-(

Sleep() (mit großem "S") ist ein Win32-API-Funktion, deklariert in 
winbase.h

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und nicht vergessen Sleep erwartet die Zeit in Millisekunden. Zudem kann 
man keine kürzeren Zeiten als ~15ms erreichen (wegen Scheduler)
Also auch ein Sleep(5) braucht 15ms und nicht 5

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sind 10 msec, schon seit längerem nicht mehr 15.

Und die Granularität des Schedulers lässt sich reduzieren, als 
theoretisches Minimum ist dann auch 1 msec möglich.
Das geht mit der Multimediatimer-Funktion timeBeginPeriod, der wird 
als Parameter die gewünschte Schedulergranularität in msec übergeben.
Die ist in winmm.h deklariert.

Autor: eklige Tunke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Timmo H. (masterfx) && Rufus t. Firefly (rufus) (Moderator)
Das wichtigste ist wahrscheinlich, dass er, wenn ich den Beitrag oben 
jetzt richtig verstehe, würde er gern anders warten. Siehe:
Lila Pause schrieb:
> so kriegt man es wohl hin aber dann wartet der Rechner aktiv oder? Wie
> macht man es besser?
Wobei ich sagen würde, dass das da oben passt, wenn er etwas anderes 
zutun hätte. Hat er aber anscheinend nicht, darum kann er imho auch 
Sleep() nehmen.
Ansonsten bräuchte er wohl einen Software-Timer...

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, Sleep() ist kein aktives Warten. Aktives Warten ist die 
Warteschleife im Anfangsposting.
Sleep() hingegen gibt die Rechenzeit an den Scheduler zurück, der sie 
daraufhin anderen Prozessen/Threads zukommen lassen kann.

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, und wie mach ich das wenn ich n Sekunden lang auf ein bestimmtes 
Ereignis warten will, und wenn es innerhalb dieser Zeitspanne passiert: 
dann soll darauf reagiert werden, und wenn es nicht passiert soll die 
Rechenzeit eben den anderen Prozessen zugeteilt werden? Also so eine Art 
"bedingtes sleep()".

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dafür gibt es die Funktionen WaitForSingleObject und 
WaitForMultipleObjects - Voraussetzung ist natürlich ein "wartbares" 
Objekt, wie z.B. ein Eventhandle.

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahso, nee ich bräuchts dann doch für Linux :)

Was gemacht werden soll:
Auf einem Display erscheint eine Anzeige. Der Benutzer soll nun 
innerhalb einer gewissen Zeitspanne, zum Beispiel innerhalb von drei 
Sekunden, auf diese Anzeige reagieren. Dafür drückt er auf eine Taste. 
Wenn der Tastendruck innerhalb von drei Sekunden erfolgte, gilt das als 
erfolgreiche Bestätigung, wenn nicht zählt es als ein Timeout und wäre 
sozusagen der Fehlerfall.
Hm, vielleicht kann man es doch mit busy-waiting machen, aber ist doch 
recht inelegant oder? Vielleicht einen phtread erzeugen, der auf den 
Tastendruck wartet? Bin mir grad nicht 100% sicher ob pthreads auf der 
Zielplattform verfügbar sind, d.h. vielleicht müsste ich die Bibliothek 
dafür extra hinzulinken wenn sie noch nicht da ist und möglicherweise 
ist das nicht erlaubt, weiß gerade nicht wieviel Platz auf dem 
Zielsystem man dafür bräuchte.

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zur Entwirrung: Ich sitze gerade an einem Rechner mit Windows und MinGW, 
laufen soll das Ganze aber später auf einem Linux Rechner.

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Auf einem Display erscheint eine Anzeige. Der Benutzer soll nun
> innerhalb einer gewissen Zeitspanne, zum Beispiel innerhalb von drei
> Sekunden, auf diese Anzeige reagieren. Dafür drückt er auf eine Taste.

Reden wir hier von dem normalen Monitor und der normalen Tastatur?

Falls ja: Welches Toolkit verwendest Du zur GUI-Programmierung?

Falls nein: Über welche Schnittstellen sind Display und Tastatur 
angebunden? Bei einer seriellen Schnittstelle wäre hier ein poll() bzw. 
ein select() das Mittel der Wahl.

Viele Grüße,
        Simon

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Budig schrieb:
> Reden wir hier von dem normalen Monitor und der normalen Tastatur?

Nein, der Steuerungsrechner kommuniziert über ein Bussystem mit dem 
Display und teilt diesem so die anzuzeigenden Informationen mit.

> Falls ja: Welches Toolkit verwendest Du zur GUI-Programmierung?

Auf dem Display-Rechner wird in C++ und mit Qt programmiert, nützt mir 
selbst aber nichts, ich progammiere den Steuerungsrechner und habe dort 
eben C als Programmiersprache.

> Falls nein: Über welche Schnittstellen sind Display und Tastatur
> angebunden? Bei einer seriellen Schnittstelle wäre hier ein poll() bzw.
> ein select() das Mittel der Wahl.

Im Endeffekt werden Signale über eine Art Prozessleitsystem zwischen 
beiden hin- und hergeschickt, die ich dann im Speicher (des 
Steuerungsrechners) in Form von globalen Variablen vorliegen habe.

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hier noch eine professionelle UML-Grafik ;)

              +-------------+                              +-----------+
              |             |                              |           |
              | Steuerungs- |------ starte_Testlauf ------>|  Display  |------------------------+
              | rechner     |                              |           |                        |
              |             |                              |           |                        |
              +-------------+                              +-----------+ <---- zeige_Button ----+
                     |                                           |
                     |                                           |
                     |<------------ Button gedrueckt? -----------|
  +------------------|                                           |
  |                  |                                           |
  |                  |                                           |
  +-wenn Button ---->|                                           |
    gedrueckt und    |                                           |
    weniger als 3    |                                           |
    Sekunden ver-    |                                           |
    gangen: Test=OK, |                                           |
    else: nicht OK   |                                           |
                     |---------- Testergebnis anzeigen --------->|                                           |
                     |                                           |---------------+
                     |                                           |               |
                     |                                           |<---Anzeige----+
                     |                                           |
                     |                                           |
                     |     ( ------ ggf. Wiederholung ------> )  |
                     |              mit anderem Signal/          |
                     |              Button                       |
                     |                                           |
                     |                                           |
                     |                                           |
                     |                                           |
                     X                                           X

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:

> Zur Entwirrung: Ich sitze gerade an einem Rechner mit Windows und MinGW,
> laufen soll das Ganze aber später auf einem Linux Rechner.

Nicht die optimale Wahl. In aller Kürze:
MinGW für Verwendung vom Windows-API.
Cygwin für Verwendung vom Unix/Linux-API.

Wenn man also unter Windows entwickelt, aber eigentlich Linux meint, 
dann ist man mit Cygwin besser dran.

Autor: sebastians (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Im Endeffekt werden Signale über eine Art Prozessleitsystem zwischen
> beiden hin- und hergeschickt, die ich dann im Speicher (des
> Steuerungsrechners) in Form von globalen Variablen vorliegen habe.

Dann schau mal ins Handbuch deines Prozessleitsystems obs da eine 
Funktion gibt, mit der du auf Ereignisse warten kannst. Oder Callbacks 
bei Ereignissen aufrufen lassen kannst.

Wenns nichts gibt, wirst du pollen müssen. Dazu nimmst du dann sleep 
oder einen anderen Timer mit möglichst hohem Wert (um die CPU möglichst 
wenig zu belasten), aber niedrig genug für die gewünschte Reaktionszeit.

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> der Steuerungsrechner kommuniziert über ein Bussystem mit dem
> Display und teilt diesem so die anzuzeigenden Informationen mit.

Ok, Du programmierst den Steuerungsrechner und der läuft letztlich mit 
Linux.

Die Information, dass der Button gedrückt wurde, kommt über ein 
"Bussystem", meine Kristallkugel sagt mir, dass der letztlich über eine 
Device-Datei in dem Linux-System repräsentiert wird, d.h. du machst 
irgendwann ein

bus = open ("/dev/meinbus", O_RDWR);

oder etwas vergleichbares.

Irgendwann ist der Zeitpunkt gekommen, dann müsste das etwa so aussehen:
#include <poll.h>
...

void meine_testfunktion () {
  struct pollfd pfd[1];
  unsigned char answer[40];
  int ret;

  ret = write (bus, "starte Testlauf\n", 16);  
  if (ret < 0)
    ;/* Fehlerbehandlung */

  /* daraufhin stellt das Display-System den Button dar */

  pfd[0].fd = bus;
  pfd[0].events = POLLIN;

  ret = poll (pfd, 1, 3000);
  /* warte max. 3s auf Daten zum Lesen bei dem "bus" Filedeskriptor */

  if (ret < 0)
    ;/* Fehlerbehandlung */

  if (ret == 0)
    ;/* Timeout ist aufgetreten, kein Buttondruck */

  if (ret > 0)
    {

      if (pfd[0].revents & POLLIN)
        {
          ret = read (bus, answer, 40);
          if (ret < 0)
            ;/* Fehlerbehandlung */

          if (strncmp (answer, "button wurde gedrueckt.\n", 24))
            ; /* behandle Buttondruck */
        }
    }
}

So in etwa (von der Struktur her). Natürlich ist dieser Code nur mal 
eben aus dem Kopf hingehackt und kein Stück getestet, Du solltest auf 
jeden Fall selber nachlesen, was die einzelnen Teile machen und sie auf 
deine Bedürfnisse anpassen - es ist ja eher unwahrscheinlich, dass über 
den Bus derartige Klartextmeldungen kommen  :)

Zentral für das Warten auf Input ist der poll() Systemaufruf. 
Busy-Waiting - wie du es vorschlägst - ist eine ganz schlechte Idee. Bei 
poll() wird der wartende Prozess echt schlafengelegt und aufgeweckt, 
sobald Input zum Lesen zur Verfügung steht.

Ich hoffe das hilft,
        Simon

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sebastians schrieb:
> Wenns nichts gibt, wirst du pollen müssen. Dazu nimmst du dann sleep
> oder einen anderen Timer mit möglichst hohem Wert

Wenn das unter Linux läuft, dann macht man das nicht, sondern nimmt - 
wie in dem letzten Posting von mir skizziert - poll() oder select(), 
wobei ich poll() bequemer finde.

Damit kann man eine maximale Wartezeit vorgeben, wird aber sofort 
aufgeweckt, falls Daten auf einem der beobachteten Filedeskriptoren 
anliegen (man kann poll ein Array von struct pollfd's geben, dann 
überwacht der mehrere).

(das "if (strncmp...)" sollte natürlich eigentlich "if (!strncmp...)" 
heißen)

Viele Grüße,
        Simon

Autor: Lila Pause (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon, vielen Dank für die Tipps, nur mit den /dev "Dateien" und 
Filedeskriptoren kann ich da nicht ran. Das Empfangsmodul für den 
Feldbus (MVB) stellt die Signale, die für die Verarbeitung benötigt 
werden, wie gesagt in Form von globalen Variablen im Speicher zur 
Verfügung. Mit diesen kann/darf/soll/muss ich operieren. Ich kann 
höchstens neue Signale definieren die dann zusätzlich in die bisher 
schon vorhandenen Telegramme eingefügt werden, aber der Datenfluss ist 
so vorgegeben und wenn ich da selbst nochmal dran rumpfusche, haut mir 
mein Chef auf die Finger ;)

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Das Empfangsmodul für den
> Feldbus (MVB) stellt die Signale, die für die Verarbeitung benötigt
> werden, wie gesagt in Form von globalen Variablen im Speicher zur
> Verfügung.

OK, dann musst Du das API dieses Empfangsmoduls (das ist Software, 
richtig?) absuchen und nach Synchronisationsmechanismen suchen. Falls 
Dir nur Busy-Waiting bleiben sollte, dann ist das API schlecht und 
sollte überdacht werden.

Läuft das Empfangsmodul als separater Thread? Oder als eigener Prozess 
der über shared Memory mit deinem Programm kommuniziert?

Viele Grüße,
        Simon

Autor: serg (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lila Pause schrieb:
> Das gibt es anscheinend nicht unter Windows/MinGW? :-(

Rolf Magnus schrieb:
> Auf POSIX-Systemen:#include <unistd.h>
>
>
>
> ...
>
> sleep(5);

die Funktion gibt die heiß nicht sleep(); sondern usleep();

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die Funktion gibt die heiß nicht sleep(); sondern usleep();

usleep soll man nicht mehr verwenden. Das wurde in POSIX.1-2001 als 
deprecated markiert und in POSIX.1-2008 komplett entfernt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.