Forum: PC-Programmierung Problem - C nanosleep()


von ich (Gast)


Lesenswert?

Hallo zusammen,

ich habe das Gefühl, dass die Funktion nanosleep() bei mir nur teilweise 
funktioniert.
1
struct timespec tim;
2
tim.tv_sec = 0;
3
tim.tv_nsec = 1000000; 
4
5
nanosleep(&tim,NULL);

Ich messe die Zeit mit QueryPerformanceCounter().
Das Problem: Wähle ich für tim.tv_nsec eine Zahl < 10000000 (z.B. 
100us), so ist die Deltazeit über QueryPerformanceCounter = 0. Kann mir 
jemand einen Tipp geben, wie ich nanosleep() für kleinere Zeiten (z.B. 
1us) nutzen kann?

von nicht"Gast" (Gast)


Lesenswert?

Hast du mal den Rückgabewert geprüft?

Evtl. tritt ja ein Fehler auf.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ist QueryPerformanceCounter nicht eine Win32-Funktion? Woher hast Du 
dann ein nanosleep?

von S. R. (svenska)


Lesenswert?

Bist du dir sicher, dass die Zeitauflösung überhaupt so genau ist, wie 
du dir das vorstellst? Nur weil du Timestamps mit ns-Auflösung bekommen 
kannst, heißt das nicht, dass das System überhaupt mit ns-Auflösung 
misst.

von Rolf M. (rmagnus)


Lesenswert?

S. R. schrieb:
> Nur weil du Timestamps mit ns-Auflösung bekommen kannst, heißt das nicht,
> dass das System überhaupt mit ns-Auflösung misst.

Außerdem bedeutet es nicht, dass das System einen Prozess überhaupt für 
so eine kurze Zeit schlafen legen kann. In der Regel gibt es dafür eine 
gewisse mindest-Granularität.

von Peter II (Gast)


Lesenswert?

Rolf M. schrieb:
> S. R. schrieb:
>> Nur weil du Timestamps mit ns-Auflösung bekommen kannst, heißt das nicht,
>> dass das System überhaupt mit ns-Auflösung misst.
>
> Außerdem bedeutet es nicht, dass das System einen Prozess überhaupt für
> so eine kurze Zeit schlafen legen kann. In der Regel gibt es dafür eine
> gewisse mindest-Granularität.

er muss ja nicht zwingend schlafen, bei kurzen Zeiten darf man auch mal 
aktiv warten.

von Rolf M. (rmagnus)


Lesenswert?

Peter II schrieb:
> er muss ja nicht zwingend schlafen, bei kurzen Zeiten darf man auch mal
> aktiv warten.

Zumindest aus der man-Page auf meinem System lese ich eine solche Option 
nicht heraus. Es steht dort allerdings, dass es sowas unter Linux früher 
mal gab, es aber entfernt wurde:
1
   Old behavior
2
       In order to support applications requiring much  more  pre‐
3
       cise  pauses  (e.g., in order to control some time-critical
4
       hardware), nanosleep() would handle pauses of up to 2 ms by
5
       busy  waiting with microsecond precision when called from a
6
       thread scheduled under a real-time policy  like  SCHED_FIFO
7
       or  SCHED_RR.  This special extension was removed in kernel
8
       2.5.39, hence is still present in current 2.4 kernels,  but
9
       not in 2.6 kernels.

Ergänzung:
Es scheint auch generell nicht vorgesehen zu sein, nanosleep per 
busy-wait zu implementieren.
http://pubs.opengroup.org/onlinepubs/009695399/functions/nanosleep.html 
meint:

*********************************************************************
The nanosleep() function shall cause the current thread to be 
suspended from execution until either the time interval specified by 
the rqtp argument has elapsed or a signal is delivered to the calling 
thread, and its action is to invoke a signal-catching function or to 
terminate the process.
*********************************************************************

Das findet man genau so auch in der Linux-Manage wieder. Der Thread muss 
also angehalten werden. Ich vermute, dass die busy-loop-Variante auch 
deshalb aus Linux wieder entfernt wurde.

: Bearbeitet durch User
von Noch einer (Gast)


Lesenswert?

Hast du die Sourcen der Library mit der nanosleep Funktion?

Mal nachschauen, ob die einfach durch 10000000 teilen und danach einen 
gröber auflösende Windows Timer benutzen.

von ich (Gast)


Lesenswert?

OK vielleicht gehen wir das Thema anders herum an. Wenn eine 
while-Schleife alle 1us einmal durchlaufen werden soll, wie realisiere 
ich so etwas auf dem PC?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Unter welchem Betriebssystem?

von bastel_ (Gast)


Lesenswert?

Manpage für nanosleep verweist auf
clock_nanosleep
timer_create
Da kann man die Clocksource angeben

von Rolf M. (rmagnus)


Lesenswert?

ich schrieb:
> OK vielleicht gehen wir das Thema anders herum an. Wenn eine
> while-Schleife alle 1us einmal durchlaufen werden soll, wie realisiere
> ich so etwas auf dem PC?

Ich glaub nicht, dass man auf einem PC eine Zykluszeit von 1 µs 
zuverlässig hinbekommt.

von MaWin (Gast)


Lesenswert?

ich schrieb:
> Wenn eine
> while-Schleife alle 1us einmal durchlaufen werden soll, wie realisiere
> ich so etwas auf dem PC?

Gar nicht.
Es treten ständig Unterbrechungen und SMIs auf, die dieses knappe Timing 
zerstören.
Über >10µs könnte man vielleicht mit einem RT-Kernel reden, aber 1µs ist 
unrealistisch.

: Wiederhergestellt durch Admin
von Noch einer (Gast)


Lesenswert?

>Gar nicht

Festplatten, Monitore, Netzwerk... Überall werden solche Schleifen 
gebraucht.

Musst halt genau so lösen. Einen Teil deines Programmes auf dem 
Prozesser. Den kritischen Teil auf zusätzlicher Hardware.

von Mark B. (markbrandis)


Lesenswert?

ich schrieb:
> OK vielleicht gehen wir das Thema anders herum an. Wenn eine
> while-Schleife alle 1us einmal durchlaufen werden soll, wie realisiere
> ich so etwas auf dem PC?

Es wäre gut wenn Du einmal beschreiben würdest, was Du eigentlich machen 
willst. Damit ist nicht gemeint "ich will eine while-Schleife eine 
Million mal pro Sekunde laufen lassen".

Welche Anforderung soll denn damit erfüllt werden, dass eine so extrem 
kurze Zeitspanne dafür benötigt wird?

von Εrnst B. (ernst)


Lesenswert?

Noch einer schrieb:
> Festplatten, Monitore, Netzwerk... Überall werden solche Schleifen
> gebraucht.

Seit Jahrzehnten nicht mehr, und selbst damals war das unüblich.
Heutzutage gibt es SATA-Controller, Grafikkarten, Netzwerkkarten.

von Rolf M. (rmagnus)


Lesenswert?

Εrnst B. schrieb:
> Noch einer schrieb:
>> Festplatten, Monitore, Netzwerk... Überall werden solche Schleifen
>> gebraucht.
>
> Seit Jahrzehnten nicht mehr, und selbst damals war das unüblich.

Was? Dass die genannten Geräte einen µC enthalten, der sich darum 
kümmert? Also sprich:

Noch einer schrieb:
> Den kritischen Teil auf zusätzlicher Hardware.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Was? Dass die genannten Geräte einen µC enthalten, der sich darum
> kümmert? Also sprich:

Was hat das mit dem Thema zu tun?

: Wiederhergestellt durch Admin
von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Was hat das mit dem Thema zu tun?

Lies einfach nochmal das Posting, auf das Ernst geantwortet hat. 
Speziell den Satz, den ich zitiert hab. Vielleicht fällt's dir dann wie 
Schuppen aus den Haaren.

von MaWin (Gast)


Lesenswert?

Rolf M. schrieb:
> Lies einfach nochmal das Posting,

Ja und? Es geht hier darum Code auf dem PC auszuführen und nicht auf 
irgendwelchen sekundären Controllern.

: Wiederhergestellt durch Admin
von Mark B. (markbrandis)


Lesenswert?

MaWin schrieb:
> Rolf M. schrieb:
>> Lies einfach nochmal das Posting,
>
> Ja und? Es geht hier darum Code auf dem PC auszuführen und nicht auf
> irgendwelchen sekundären Controllern.

Es geht vermeintlich darum. Denn wirklich sinnvoll ist die Forderung, 
auf einem PC etwas im Mikrosekundentakt auszuführen, wohl ziemlich 
sicher nicht.

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Rolf M. schrieb:
>> Lies einfach nochmal das Posting,
>
> Ja und? Es geht hier darum Code auf dem PC auszuführen und nicht auf
> irgendwelchen sekundären Controllern.

Und deiner Meinung nach ist "gar nicht" als Antwort besser als ein 
Hinweis darauf, was man normalerweise stattdessen macht?

von ich (Gast)


Lesenswert?

Auf die Frage, was ich eigentlich machen will, kann ich nur antworten, 
wenn ich weiter aushole. Ein Prof. hat nach einer Vorlesung gesagt: „Sie 
müssen jetzt in der Lage sein einen 8bit uC im FPGA zu realisieren.“ Ich 
habe mir gedacht, einen FPGA habe ich nicht, aber dafür einen Rechner. 
Bau doch zur Übung einfach einen Emulator, passt schon. C hat man in der 
Uni und einen 8bit uC mit einem „hello world blink hex file“ hat doch 
jeder rumliegen. Implementierung ging eigentlich locker von der Hand 
(Profis würden vom Stuhl fallen, aber egal). Die LED „blinkt“ im 
Emulator fröhlich vor sich hin, jedoch viel zu schnell. Lösungsansatz → 
nanosleep(). Scheinbar der falsche Ansatz. Der emuliert uC sollte 
halbwegs zeitlich das reale Blinken darstellen, mehr nicht. Wie macht 
man soetwas richitg?

von A. S. (Gast)


Lesenswert?

Logisch und am einfachsten wäre es doch, entweder die Taktrate im 
compilierten Programm an die sich ergebende PC-emulator-taktrate 
anzupassen, oder z.b. jede ms 1000Takte abzuarbeiten.

von MaWin (Gast)


Lesenswert?

ich schrieb:
> Wie macht
> man soetwas richitg?

Nicht nach jedem Takt x Mikrosekunden schlafen, sondern alle y Takte z 
Millisekunden.

von bastel_ (Gast)


Lesenswert?

Alternativ nicht schlafen, sondern hart eine echte Nanotimesource pollen 
und so lange abzählen bis 10 Mikrosekunden rum sind. Ist allerdings 
unschön.

von Rolf M. (rmagnus)


Lesenswert?

bastel_ schrieb:
> Alternativ nicht schlafen, sondern hart eine echte Nanotimesource pollen
> und so lange abzählen bis 10 Mikrosekunden rum sind. Ist allerdings
> unschön.

Und hat das Problem, dass das Programm ja trotzdem schlafen gelegt wird, 
weil durch andere Prozesse unterbrochen. Da kommt dann alles 
durcheinander.
Ich würde das da vorschlagen:

Achim S. schrieb:
> oder z.b. jede ms 1000Takte abzuarbeiten.

Und wenn's mal länger als ne Millisekunde gedauert hat, entsprechend 
mehr Takte abarbeiten. Eine Millisekunde ist für ein 
nicht-Echtzeit-Betriebssystem schon eine recht harte Anforderung, die es 
nicht zuverlässig erledigen wird. Auf der anderen Seite kommt's bei ner 
µC-Emulation mit blinkender virtueller LED vielleicht auch nicht auf 
harte Echtzeit an.

von bastel_ (Gast)


Lesenswert?

Rolf M. schrieb:
> bastel_ schrieb:
>> Alternativ nicht schlafen, sondern hart eine echte Nanotimesource pollen
>> und so lange abzählen bis 10 Mikrosekunden rum sind. Ist allerdings
>> unschön.
>
> Und hat das Problem, dass das Programm ja trotzdem schlafen gelegt wird,
> weil durch andere Prozesse unterbrochen. Da kommt dann alles
> durcheinander.

Durcheinander ist etwas zu hoch gegriffen, da man mit der Differenz der 
Timestamps arbeitet, wird durch die Unterbrechung die Verzögerung 
einfach nur länger als 10 µs. Wenn das dann beim nächsten Takt wieder 
einfangen will, kann man ja den Übertrag von den nächsten 10µs abziehen 
(darf natürlich nicht <0 werden). Aber schöner wird's nicht ;)

von Noch einer (Gast)


Lesenswert?

LinuxCNC steuerte Schrittmotoren aus einem User-Prozess über den 
Parallelport an.

Deren Lösung: Alle nicht benötigten Dienste abschalten. Während das 
Programm läuft weder Maus noch Tastatur anfassen. Und beten, dass der 
Jitter klein genug bleibt.

von ich (Gast)


Lesenswert?

Die Lösung mit den 1000 Takten liefert das gewünschte Ergebnis. Danke.

von MaWin (Gast)


Lesenswert?

Noch einer schrieb:
> LinuxCNC steuerte Schrittmotoren aus einem User-Prozess über den
> Parallelport an.

Aber nicht in einem 1µs-Raster.
Auf gut echtzeitfähiger Hardware sind vielleicht knapp unter 10µs 
Perioden möglich.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.