Patrząc na źródło strace
, znalazłem użycie flagi klonowania, CLONE_IDLETASK
która jest tam opisana jako:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
Po głębszym przyjrzeniu się, odkryłem, że chociaż ta flaga nie jest w man clone
niej zakryta , jest faktycznie używana przez jądro podczas procesu rozruchu do tworzenia bezczynnych procesów (wszystkie powinny mieć PID 0) dla każdego procesora na komputerze. tzn. maszyna z 8 procesorami będzie miała co najmniej 7 (patrz pytanie poniżej) takich procesów „działających” (notowania).
To prowadzi mnie do pytania o to, co faktycznie robi ten „bezczynny” proces. Zakładam, że wykonuje on operację NOP w sposób ciągły, aż do upływu czasu, a jądro przypisuje prawdziwy proces do uruchomienia lub ponownie przypisuje proces bezczynności (jeśli procesor nie jest używany). Ale to kompletne przypuszczenie. Więc:
Czy na maszynie z, powiedzmy, 8 procesorami powstanie 7 takich bezczynnych procesów? (a jeden procesor będzie utrzymywany przez samo jądro bez wykonywania pracy w przestrzeni użytkownika?)
Czy proces bezczynności jest tak naprawdę nieskończonym strumieniem operacji NOP? (lub pętla, która robi to samo).
Czy użycie procesora (powiedzmy
uptime
) jest po prostu obliczane na podstawie tego, jak długo proces bezczynności był na procesorze i jak długo go nie było przez określony czas?
PS Prawdopodobnie duża część tego pytania wynika z faktu, że nie do końca rozumiem, jak działa procesor. tzn. rozumiem asembler, ramy czasowe i przerwania, ale nie wiem jak, na przykład, procesor może zużywać mniej lub więcej energii w zależności od tego, co wykonuje. Byłbym wdzięczny, gdyby ktoś też mógł mnie oświecić.
źródło
Odpowiedzi:
Zadanie bezczynności służy do rozliczania procesów, a także do zmniejszenia zużycia energii. W systemie Linux jedno bezczynne zadanie jest tworzone dla każdego procesora i blokowane na tym procesorze; za każdym razem, gdy na tym procesorze nie ma innego procesu do uruchomienia, zadanie bezczynności jest planowane. Czas spędzony na zadaniach bezczynności pojawia się jako czas „bezczynności” w narzędziach takich jak
top
. (Czas przestoju jest obliczany inaczej).Wydaje się, że Unix zawsze miał jakąś pętlę bezczynności (ale niekoniecznie faktyczne zadanie bezczynności, patrz odpowiedź Gillesa ), a nawet w V1 używał
WAIT
instrukcji, która zatrzymywała procesor do momentu wystąpienia przerwania (oznaczało „czekaj na” przerwać"). Niektóre inne systemy operacyjne używały zajętych pętli, DOS, OS / 2 , a zwłaszcza wczesnych wersji Windows. Już od dłuższego czasu procesory używają tego rodzaju instrukcji „czekania”, aby zmniejszyć zużycie energii i produkcję ciepła. Możesz zobaczyć różne implementacje bezczynnych zadań, na przykład warch/x86/kernel/process.c
jądrze Linuksa: podstawowa po prostu wywołujeHLT
, który zatrzymuje procesor do momentu wystąpienia przerwania (i włącza tryb oszczędzania energii C1), inne implementacje obsługują różne błędy lub nieefektywności ( np. używanieMWAIT
zamiastHLT
niektórych procesorów).Wszystko to jest całkowicie oddzielone od stanów bezczynności w procesach, gdy czekają na zdarzenie (We / Wy itp.).
źródło
play_dead()
to bardzo ładna nazwa mnemoniczna do wykonywania HALT. Czy nie byłoby ryzyka wysłania HALT do każdego procesora, a tym samym zawieszenia się? (tj. osiągnięcie takiej sytuacji, HALT każdy procesor, byłby błędem w jądrze, prawda?)W projekcie podręcznika harmonogramu procesów, jeśli harmonogram nie ma żadnego procesu do zaplanowania (tj. Jeśli wszystkie procesy są zablokowane, czekają na dane wejściowe), to harmonogram czeka na przerwanie procesora. Przerwanie może wskazywać wejście z urządzenia peryferyjnego (działanie użytkownika, pakiet sieciowy, ukończony odczyt z dysku itp.) Lub może być przerwaniem licznika czasu, które wyzwala licznik czasu w procesie.
Program planujący Linuksa nie ma specjalnego kodu dla przypadku, w którym nie ma nic do zrobienia. Zamiast tego koduje przypadek bezczynności jako specjalny proces, proces bezczynności. Proces bezczynności jest planowany tylko wtedy, gdy żaden inny proces nie jest planowany (ma efektywnie nieskończenie niski priorytet). Proces bezczynności jest w rzeczywistości częścią jądra: jest to wątek jądra, tzn. Wątek, który wykonuje kod w jądrze, a nie kod w procesie. (Dokładniej, dla każdego procesora jest jeden taki wątek.) Gdy proces bezczynności zostanie uruchomiony, wykonuje operację oczekiwania na przerwanie.
Sposób działania funkcji oczekiwania na przerwanie zależy od możliwości procesora. Dzięki najbardziej podstawowej konstrukcji procesora jest to po prostu zajęta pętla -
Procesor nieprzerwanie uruchamia instrukcję rozgałęzienia, która niczego nie osiąga. Większość współczesnych systemów operacyjnych tego nie robi, chyba że działa na procesorze, na którym nie ma nic lepszego, a większość procesorów ma coś lepszego. Zamiast marnować energię na robienie nic poza ogrzewaniem pomieszczenia, najlepiej procesor powinien być wyłączony. Dlatego jądro uruchamia kod, który instruuje procesor, aby sam się wyłączył, a przynajmniej wyłączyć większość procesora. Musi być przynajmniej jedna mała część, która pozostaje włączona, kontroler przerwań. Kiedy urządzenie peryferyjne wyzwoli przerwanie, kontroler przerwań wyśle sygnał budzenia do głównego (części) procesora.
W praktyce nowoczesne procesory, takie jak Intel / AMD i ARM, mają wiele złożonych ustawień zarządzania energią. System operacyjny może oszacować, jak długo procesor pozostanie w trybie bezczynności i w zależności od tego wybierze różne tryby niskiego zużycia energii. Tryby oferują różne kompromisy między zużyciem energii w trybie bezczynności, a czasem potrzebnym do wejścia i wyjścia z trybu bezczynności. W niektórych procesorach system operacyjny może również obniżyć częstotliwość taktowania procesora, gdy stwierdzi, że procesy nie zużywają dużo czasu procesora.
źródło
HLT
może wyłączyć warianty SL 386 i 486, zanim pojawił się DX4 (artykuł w Wikipedii jest niepoprawny).Nie, bezczynne zadanie nie marnuje cykli procesora. Program planujący po prostu nie wybiera bezczynnego procesu do wykonania. Bezczynny proces czeka na jakieś zdarzenie, aby mógł być kontynuowany. Na przykład może czekać na wejście w
read()
wywołaniu systemowym.Nawiasem mówiąc, jądro nie jest osobnym procesem. Kod jądra jest zawsze wykonywany w kontekście procesu (no cóż, z wyjątkiem specjalnego przypadku wątku jądra), więc nie jest poprawne powiedzenie „i jeden procesor będzie utrzymywany przez samo jądro bez wykonywania pracy w przestrzeni użytkownika”.
źródło