Problem - C nanosleep()

Gast #4907539
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?
Gast #4908051
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.
#4908073
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.
Gast #4910021
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.
Gast #4910060
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.
#4910193
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?
Gast #4912220
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?
#4912612
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.
Gast #4912902
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 ;)
Gast #4914339
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren