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?
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?
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
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
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.
@ 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...
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.
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()".
Dafür gibt es die Funktionen WaitForSingleObject und
WaitForMultipleObjects - Voraussetzung ist natürlich ein "wartbares"
Objekt, wie z.B. ein Eventhandle.
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.
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
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.
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.
> 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.
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
1
bus=open("/dev/meinbus",O_RDWR);
oder etwas vergleichbares.
Irgendwann ist der Zeitpunkt gekommen, dann müsste das etwa so aussehen:
1
#include<poll.h>
2
...
3
4
voidmeine_testfunktion(){
5
structpollfdpfd[1];
6
unsignedcharanswer[40];
7
intret;
8
9
ret=write(bus,"starte Testlauf\n",16);
10
if(ret<0)
11
;/* Fehlerbehandlung */
12
13
/* daraufhin stellt das Display-System den Button dar */
14
15
pfd[0].fd=bus;
16
pfd[0].events=POLLIN;
17
18
ret=poll(pfd,1,3000);
19
/* warte max. 3s auf Daten zum Lesen bei dem "bus" Filedeskriptor */
20
21
if(ret<0)
22
;/* Fehlerbehandlung */
23
24
if(ret==0)
25
;/* Timeout ist aufgetreten, kein Buttondruck */
26
27
if(ret>0)
28
{
29
30
if(pfd[0].revents&POLLIN)
31
{
32
ret=read(bus,answer,40);
33
if(ret<0)
34
;/* Fehlerbehandlung */
35
36
if(strncmp(answer,"button wurde gedrueckt.\n",24))
37
;/* behandle Buttondruck */
38
}
39
}
40
}
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
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
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 ;)
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
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();
> 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.