# [C++]Sleep kleiner als ms?



## Irgendjemand_1 (29. November 2005)

Tach ich bins wieder.

Kann man bei Sleep irgendwie, Mikrosekunden angeben, oder zumindest dieselbe Funktionsweise erzielen?

Ihr fragt euch sicher, wofür ich das brauche ... Ich habe eine Endlosschleife und bei dieser ist 1 ms irgendwie viel zu langsam - merkwürdig langsam (200 Durchläufe pro Sekunde ca.)) und ohne Sleep sinds ca. 4000 Durchläufe pro Sekunde, was wieder um einiges zu schnell ist.

Für meine Zwecke wäre so ein Mittelding recht praktisch, dafür bräuchte ich aber etwas kleineres als Millisekunden.
Hat jemand einen Rat?


----------



## Byteblaster (29. November 2005)

Einfachste Lösung: Mach doch dann noch eine Variable rein die du bei jeden Durchlauf incrementierst und die du dann bei >= 10 wieder auf 0 setzt wird und ein Sleep(1) auslöst. Also das du alle 10 Durchläufe ein Sleep(1) aufrufst. ;-)

Gruß Byteblaster


----------



## anmae (30. November 2005)

ich hab damals unter unix mit Sleep(0) gearbeitet, so wurde nur der Prozessor abgegeben und der Thread sofort wieder in die Warteschlange für den Prozessor eingereiht.
bin mir aber nicht so sicher ob das unter Windows genauso geht.


----------



## Dennis Wronka (30. November 2005)

In PHP gibt es den Befehl time_nanosleep(), wo man die Schlafdauer in Nanosekunden angeben kann.
Da PHP in C geschrieben ist sollte man meinen, dass es auch in C einen entsprechenden Befehl gibt.
Ich werd mal in den Quellcode von PHP schauen und gucken ob ich dort was finde.

So wie es aussieht sollte die entsprechende C-Funktion schlichtweg nanosleep() heissen.


----------



## Irgendjemand_1 (30. November 2005)

Nanosekunden sogar 
Am besten noch Femtosekunden ...  Mikrosekunden hätten ja gereicht, aber im Prinzip ist es ja egal.
Ich probiers mal aus

Edit:
implicit declaration of function `int Nanosleep(...)'
kleingeschrieben geht auch nicht.
Muss man dafür was includieren?


----------



## pking (30. November 2005)

Ich glaube

#include <time.h>


----------



## Dennis Wronka (30. November 2005)

pking hat gesagt.:
			
		

> Ich glaube
> 
> #include <time.h>


Denke ich auch. Die wird auch in der entsprechenden Datei des PHP-Sourcecodes includet.


----------



## jokey2 (30. November 2005)

Also in meiner time.h ist da nichts mit nanosleep oder etwas in der Art. Ich habe auch noch nie davon gehört.
Habe mich mal ein wenig umgesehen. Es sieht so aus, als ob nanosleep nur im POSIX-Standard definiert ist, nicht aber im ANSI-C.


----------



## Tobias K. (30. November 2005)

moin


Hab auch noch nie was von nanosleep gehört, mal ganz davon abgesehen das Windows das wohl garnicht bringen dürfte.
Aber zu dem Thema gab es hier schon einen ausführlichen Thread!


mfg
umbrasaxum


----------



## Irgendjemand_1 (30. November 2005)

Tobias K. hat gesagt.:
			
		

> moin
> 
> 
> Hab auch noch nie was von nanosleep gehört, mal ganz davon abgesehen das Windows das wohl garnicht bringen dürfte.
> ...


Gesucht hab ich: Wohl nicht gründlich genug, wie es scheint.

Weißt du vielleicht noch welchen Thread?


----------



## Dennis Wronka (30. November 2005)

Tobias K. hat gesagt.:
			
		

> ..., mal ganz davon abgesehen das Windows das wohl garnicht bringen dürfte.


Das ist ja fast schon FlameWar-verdaechtig. 

Waere interessant zu wissen ob die Funktion auch in der Windows-Version von PHP enthalten ist und funktioniert.
Nachtrag: Grad in der PHP-Doku zu time_nanosleep() gefunden:


> Note: This function is not implemented on Windows platforms.


----------



## Tobias K. (30. November 2005)

moin




> Nachtrag: Grad in der PHP-Doku zu time_nanosleep() gefunden:
> 
> Zitat:
> Note: This function is not implemented on Windows platforms.


Siehste, Tobias hat Recht! Und nichts mit geflame... ;-) 

Seiehe dazu:
http://www.tutorials.de/tutorials209577.html


mfg
umbrasaxum


----------



## rohrbold (30. November 2005)

Also unter Linux gibt es die POSIX Funktion nanosleep(), die theoretisch eine Granularität bis auf Nanosekunden besitzt. Ob das Dein Rechner schafft, ist eine andere Frage ;-)
Wie schon weiter oben geschrieben wurde, liegt die Funktion in time.h, jedoch ist sie kein Bestandteil der Standardbibliothek (da sehr plattformabhängig), sondern eben eine POSIX Funktion.

Man kann sie beispielsweise wie folgt verwenden:


```
/* interval_size specifies the step size of each measurement interval 
* and corresponds to [milliseconds]. Therefore a value of 100 
* means 100 ms (= 0.1 s) */
int interval_size = 10;
struct  timespec req;
req.tv_sec = 0;
req.tv_nsec = interval_size * 1000 * 1000; /* 0.1 sec */

[...]

for(i = 0; i < (time * 1000 / interval_size); ++i) {
    /* do something */
    nanosleep(&req, NULL);
}
```

Falls man strikt standardkonform arbeiten möchte (gcc -W -Wall -pedantic -std=c99 -o foo foo.c), muss man seinem Compiler mitteilen, dass die »richtige« time.h eingebunden wird. Das geht entweder über Compilerflags, oder indem man in der ersten Zeile POSIX freischaltet, z.B.:

```
#define _POSIX_C_SOURCE 199309L
```
Es gibt aber einige mehr dieser Optionen. Man kann diese bei Linux unter /usr/include/features.h nachlesen. 

HTH,
Martin


----------



## Dennis Wronka (30. November 2005)

Tobias K. hat gesagt.:
			
		

> Siehste, Tobias hat Recht!


Der Tobi hat auch ein klein wenig mehr Ahnung von C als der Dennis. 
Ich hab ja schon ewig nichts mehr mit C gemacht. Hatte mich nur erinnert, dass es da bei PHP was gab.
Und da PHP ja OpenSource ist kann man da ja wunderbar mal in den Source-Code schauen.

Nur dumm, dass Windows das nicht kann.


----------



## Irgendjemand_1 (30. November 2005)

Naja mich würds freuen, wenn das ganze mit C++ realisierbar wäre und man keine Chips und Schaltungen und weiß ich was braucht


----------



## Dennis Wronka (30. November 2005)

Irgendjemand_1 hat gesagt.:
			
		

> Naja mich würds freuen, wenn das ganze mit C++ realisierbar wäre und man keine Chips und Schaltungen und weiß ich was braucht


Wenn Du's unter Linux machst, dann kannst Du es mit C machen.


----------



## Ives (30. November 2005)

Es gibt glaub ich eine Funktion gettickcount, oder ähnlich damit lässt sich in kleinen Zeitbereichen einiges machen, einfach mal danach suchen.


----------



## Tobias K. (30. November 2005)

moin


Das kann auch nichts kleineres als Millisekunden.


mfg
umbrasaxum


----------



## Lemiras (1. Dezember 2005)

Was ist denn mit der Funktion usleep die löst in mikrosekunden auf, existiert diese unter Win? Und Linux gehts

Gruß Lemi


----------



## jokey2 (1. Dezember 2005)

Vergiß es unter Windows
Du kannst immer nur auf Timer zugreifen, die Dir das OS zur Verfügung stellt. Unter Windows ist die minimale Timergranularität 1ms! Wer mehr will, sollte sich ein OS holen, welches das macht. Da Windows kein Echtzeit-OS ist, sind auch diese Timer nicht allzu genau.


----------



## DerSensenmann (1. Dezember 2005)

ich hätte eine etwas unelegante lösung.
bau in die schleife einfach irgentwelche datenmüll ein.
des müsste die schleife auch ausbremsen,
so wie : 
x = 3 * 3,14674739479497397379239 ( ok pi sieht anderst aus aber egal......)
 musst halt merhere so sachen machen möglichst mit den gleichen variabelen , damit es nicht so viel speicherplatzt kostet.


----------



## Irgendjemand_1 (1. Dezember 2005)

Echt unelegant 
Das Problem ist, dass ich nicht weiß, was das wieviel abbremst.

Ansonsten aber eine gute Idee.


----------



## DerSensenmann (1. Dezember 2005)

musst du ausprobieren ^^.
einfach mal was kleines einfügen , und wenns net reicht was größeres.....


----------



## jsendrow (1. Dezember 2005)

Linux hat bei Zeiträumen kleiner 2ms das gleiche Problem wie das Sleep unter Windows. Die Zeitdauer um einen Task aus dem suspended mode aufzuwecken kostet bei so kleinen Zeiträumen zuviel Zeit. Deswegen benutzt nanosleep bei Zeiten <= 2ms eine busyloop anstatt den task zu suspenden. (Zumindest unter Linux)

Das kann man unter Windows (in der Regel) auch machen mit Hilfe des Performance-Timers  (Wobei es von der Hardware des Recheners abhängt ob ein solcher Timer zur Verfügung steht. Aktuelle Prozessoren haben das aber soweit ich weis)


```
LARGE_INTEGER start;
	LARGE_INTEGER stop;
	LARGE_INTEGER freq;
	
	if( QueryPerformanceFrequency(&freq) { // freq ist die anzahl der tics pro Sekunde
	      LARGE_INTEGER ms;
	      ms.QuadPart = freq.QuadPart / 2000;  // delay für eine halbe ms 

	      QueryPerformanceCounter(&start);
	      QueryPerformanceCounter(&stop);

	      // Die Schleife läuft solange bis der gewünschte Delay verstrichen ist
                      // Im gegebenen Beispiel eine halbe ms.
  	      while(start.QuadPart + ms.QuadPart > stop.QuadPart ) {
		QueryPerformanceCounter(&stop);
                      }
                }
                else {
                      // Kein Counter vorhanden
                }
```


----------



## rohrbold (2. Dezember 2005)

Lemiras hat gesagt.:
			
		

> Was ist denn mit der Funktion usleep die löst in mikrosekunden auf, existiert diese unter Win? Und Linux gehts



Siehe Manpage zu usleep (man 3 usleep):


> This function is obsolete. Use nanosleep(2) or setitimer(2) instead.



Martin


----------



## jokey2 (5. Dezember 2005)

Das Beispiel mit QueryPerformanceCounter sieht sehr gut aus! Allerdings muß man bei sowas immer im Hinterkopf haben, das die Schleife *mindestens* die eingestellte Zeit läuft, also auch etwas länger laufen kann. Harte Echtzeitanforderungen kannst du damit nicht erfüllen. Ebenfalls ist es möglich, daß der Task bzw. der Prozeß, in welchem die Schleife läuft, zwischendurch angehalten wird. Wenn er dann erst nach längerer Zeit wieder aktiviert wird, ist Dein Timer wahrscheinlich übergelaufen.


----------



## Lemiras (6. Dezember 2005)

Stimmt usleep wurde ja ersetzt. 

Eine weitere Möglichkeit die es gäbe, auch ohne den Prozess anzuhalten, währe den Pentium Zyklus Zähler zu nutzen und in einer Schleife abzufragen. Es ist zwar ein wenig Assambler dafür nötig aber es sollte gehn so sehr kleine Zeiten zu bekommen. Wenn man dann noch die Ausführungsdauer der umgebenen Schleife mit ein berechnet ginge es sogar relativ genau. Man müßte nur verhindern das der Prozess vom Scheduler unterbrochen wird. Auch hier kann ich leider nur aus Erfahrungen mit QNX zurückgreifen, dprt währe es möglich den Prozess als Fifo zu deklariehren und somit einen Rauswurf zu verhindern. So weit ich weiß ist dies unter Win jedoch nicht mögich da kein Echtzeitfähiges Scheduling existiert.

Ein weiterer Nachteil ist natürlich das man die Frequenz des Prozessors kennen muß, diese könnte man sich mehr oder weniger genau mit einem referenz Timer besorgen.

Das Auslesen müßte ich mal wieder raussuchen.
Gruß Lemiras


----------



## jokey2 (6. Dezember 2005)

QNX ist aber auch ein Echtzeit-OS.
Windows garantiert nicht! ;-)


----------



## Lemiras (6. Dezember 2005)

Nicht wirklich, gibt es denn keine möglichkeit das suspendiren zu verhindern für eine gewisse Zeit?


----------



## jokey2 (6. Dezember 2005)

Du könntest versuchen, mit SetThreadPriority die Threadpriorität auf THREAD_PRIORITY_TIME_CRITICAL zu setzen. Damit habe ich aber noch keine Erfahrung, also ohne Gewähr!


----------



## frfrehghej76 (1. Oktober 2010)

> Du könntest versuchen, mit SetThreadPriority die Threadpriorität auf THREAD_PRIORITY_TIME_CRITICAL



Ohgott mach das BLOSS NICHT! Threads oder Prozesse auf der höchsten Prio können u.U. HARDWARE BESCHÄDIGEN weil damit sogar der Kernel selbst übergangen wird - Microsoft rät überall wo entspr. Prios erklärt werden davon ab, höher als "high" zu gehen - und das mit gutem Grund. Wer Echtzeitanforderungen an ein Programm hat darf kein Windows benutzen, so einfach ist das. 1ms ist das Limit, kleiner kann man nicht werden - zudem macht es in fast allen Fällen keinen Sinn im Mikrosekundenbereich zu arbeiten; solche Programme sind entweder fehlerhaft oder höchst speziell und komplex, ganz einfach.

Den Schwachsinn da oben mit "Datenmüll in der Schleife produzieren" kommentiere ich mal lieber nicht .... das ist weder "unelegant" noch "unschön" - das ist einfach nur ein Programmierfehler


----------



## ComFreek (1. Oktober 2010)

@Gast frfrehghej76:

So schlimm ist das gar nicht!
Ich selber setze manchmal im Taskmanager die Priorität höher - auch schonmal auf Echtzeit (=TIME_CRITICAL) und bis jetzt ist nichts passiert außer dass andere Prozesse (wie Explorer) langsamer liefen - mehr nicht!​


----------



## merano (4. Oktober 2010)

RICHTIGE Echtzeit geht prinzipiell mit normaler PC-Hardware nicht. Das liegt auch nicht nur an nicht maskierbaren Hardware-Interrupts. Wenn es "etwas" ungenau sein darf reicht ein handelsüblicher PC natürlich.

Unter Windows würde ich den Multimedia-Timern diese Aufgabe am ehesten zutrauen. Damit es reproduzierbar ist sollte die Base und Thread-Prio etwas hochgesetzt werden und das ganze in einem separaten Thread laufen. 

Würde die höchsten Prio-Stufen eher meiden, es ei denn man hat genügend freie Cores und Adminrechte


----------



## 3Cyb3r (6. Oktober 2010)

Ob Echtzeit oder nicht liegt nicht an dem Betriebssystem! Sondern an der Hardware und ich bezweifel sehr stark, dass mit aktueller Desktop- (Notebook-) Hardware eine Genauigkeit für nicht industrielle Zwecke erreicht wird (und für diese im Normalfall auch). 
Ansonsten muss mir schon mal jemand erzählen wie ungenau der Prozessortakt doch ist. Ihr habt in jedem Prozessor Heutzutage genügen Prescaler und Timer ...
Dann muss man sich eben selber ein Interface schreiben um diese Genauigkeit nutzen zu können (einen Treiber). 
Nehmen wir mal einen 2000MHz Takt an:
Nun setzen wir für einen Timer den Eigangstakt auf die CPU-Frequenz. Wenn der Timer nun läuft, wird er mit diser Frequenz inkrementiert. Nun nehmen wir z.B. einen 8-bit Timer und wir haben dann eine Auflösung von 256 (2^8). Dies ergibt dann:

2000000000/256 Hz = 7812500 Hz
bzw.
1/78125005 s = 11.28 µs

Soweit ich weiß gibt es in dem CPUs Bausteine die auch wesentlich höhere genaue Taktfrequenzen erzeugen können. Naja diese Genauhigkeit müsste doch eigl reichen oder?^^
Man brauch dann natürlich auch immer sehr kleine (nicht rechenaufwändige Codeblöcke z.B. bei Rechnungen immer nur mit +-1 rechnen ...)

MFG


----------



## ComFreek (6. Oktober 2010)

Ich bezog mich mit "Echtzeit" auf den Menüeintrag im TaskManager.
Mir ist schon klar, das Echtzeit nicht Echtzeit ist. Es heißt eben nur so im TaskManger


----------



## 3Cyb3r (6. Oktober 2010)

War auch nicht auf dich sondern merano bezogen und es gibt NMIs, welche man  auch nutzen kann und wer genügend Maßnahmen unternimmt kann diese dann auch ohne Gefahr bei einem multicore Prozessoren nutzen.


----------



## merano (6. Oktober 2010)

@3Cyb3r:  Nanu? Ich habe doch fast das gleiche angemerkt wie Du ? Ich sagte das es z.B. NMIs gibt und noch einiges andere was gegen "richtige" Echtzeit mit PC-Hardware spricht ...
Das NMIs (nicht deaktivierbar!) auftreten können und  "richtige" Echtzeit zerstören war die Aussage.  
Tastatur, Maus, Festplattencontroller lösen ebenfalls Hardwareinterrupts aus - wenn man die abschaltet hat man wohl neue Probleme ...

Entweder man lebt mit diesen Dingen, oder man braucht andere Hardware - das war das Statement.

Ansonsten würde ich direkte Register oder Kernelprogrammierung eher als Experiment ansehen. Wenn es auf beliebigen Rechnern laufen soll ist das eher keine gute Idee.

Unterschiede oder Eignung verschiedener Betriebssysteme war garnicht MEIN Thema. Sondern der Hinweis auf Timer - was auch bei Dir das Thema war, oder?  (Windows nur als Beispiel ..)


----------

