Typowym sposobem implementacji sleep()
i nanosleep()
jest przekonwertowanie argumentu na dowolną skalę używaną przez program planujący systemu operacyjnego (podczas zaokrąglania w górę) i dodanie do niej bieżącego czasu w celu utworzenia "absolutnego czasu budzenia"; następnie powiedz programowi planującemu, aby nie podawał czasu procesora wątku, dopóki nie zostanie osiągnięty "absolutny czas budzenia". Nie wymaga to intensywnego oczekiwania.
Należy pamiętać, że niezależnie od skali, której używa program planujący systemu operacyjnego, zazwyczaj zależy od tego, jaki sprzęt jest dostępny i/lub używany do przechowywania danych. Może być mniejsza niż nanosekunda (np. Lokalny APIC w 80x86 używany w "trybie terminowym TSC") lub w zasięgu 100 ms.
Należy również pamiętać, że system operacyjny gwarantuje, że opóźnienie nie będzie mniejsze niż wymagane; ale zwykle nie ma gwarancji, że nie będzie dłuższy i w niektórych przypadkach (np. wątek o niskim priorytecie w mocno obciążonym systemie) opóźnienie może być o wiele większe niż wymagane. Na przykład, jeśli poprosisz o sen przez 123 nanosekundy, możesz spać przez 2 ms, zanim program planujący zdecyduje, że może dać ci czas procesora, a potem może to być kolejne 500 ms zanim planista faktycznie da ci czas procesora (np. wątki używają procesora).
Niektóre systemy operacyjne mogą próbować zmniejszyć problem "spać o wiele dłużej niż zażądano", a niektóre systemy operacyjne (np. Zaprojektowane do pracy w czasie rzeczywistym) mogą stanowić pewnego rodzaju gwarancję (z ograniczeniami - np. Z zastrzeżeniem priorytetu wątku) dla minimalny czas między wygaśnięciem opóźnienia a ponownym pobraniem procesora. Aby to zrobić, system operacyjny/jądro przekonwertowałby argument na dowolną skalę używaną przez program planujący systemu operacyjnego (podczas zaokrąglania w dół i nie zaokrąglając w górę) i może odjąć niewielką ilość "na wszelki wypadek"; tak aby program szeregujący budził wątek w górę tuż przed upływem żądanego opóźnienia (a nie po); a następnie, gdy wątek otrzymuje czas procesora (po koszcie przejścia kontekstu do wątku i ewentualnie po wstępnym pobraniu różnych linii pamięci podręcznej, z których wątek jest gwarantowany) jądro będzie zajęte przez chwilę, aż upłynie czas opóźnienia. Dzięki temu jądro może przekazać kontrolę z powrotem do wątku bardzo blisko opóźnienia wygaśnięcia.
Na przykład, jeśli poprosisz o sen przez 123 nanosekundy, program planujący może nie dać czasu procesora przez 100 nanosekund, to może poświęcić 10 nanosekund na przełączenie się do wątku, a następnie może być zajęty oczekiwaniem na pozostałe 13 nanosekund. Nawet w tym przypadku (w przypadku gdy oczekiwanie jest zakończone) zwykle nie będzie czekał na pełny czas opóźnienia.Jeśli jednak opóźnienie jest bardzo krótkie, jądro wykona tylko ostatnie, zajęte, oczekiwanie.
Wreszcie istnieje specjalny przypadek, o którym warto wspomnieć. W systemach POSIX sleep(0);
jest zazwyczaj nadużywany jako yield()
. Nie jestem zbyt pewny, jak uzasadniona jest ta praktyka - niemożliwe jest, aby program planujący obsługiwał coś w rodzaju yield()
, chyba że planista jest skłonny tracić czas procesora, wykonując nieistotną pracę, podczas gdy ważniejsza praca czeka.
Co jest nie tak z pytaniem? – Kam
_ "Co jest nie tak z pytaniem?" _ Zbyt szeroko. Specyficzne dla systemu operacyjnego, specyficzne dla wdrożenia. –
POSIX nie określa sposobu jego implementacji. – StenSoft