Co robi proces bezczynnego procesora?

73

Patrząc na źródło strace, znalazłem użycie flagi klonowania, CLONE_IDLETASKktó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 cloneniej 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:

  1. 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?)

  2. Czy proces bezczynności jest tak naprawdę nieskończonym strumieniem operacji NOP? (lub pętla, która robi to samo).

  3. 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ć.

grochmal
źródło
17
Musiałem oprzeć się pokusie, aby po prostu napisać „Nic”, kiedy zobaczyłem tytuł.
Rzeczywistość
4
Większość współczesnych procesorów dynamicznie obniża częstotliwość taktowania i zużycie energii podczas pracy na biegu jałowym lub przy niskim obciążeniu ( dynamiczne skalowanie częstotliwości , np. SpeedStep dla procesorów Intel). Jeśli przetaktujesz procesor, zwykle wyłączy to zachowanie, powodując, że procesor utrzyma maksymalną częstotliwość taktowania, nawet na biegu jałowym.
Nat
2
Zobacz także „Stany zasilania ACPI”: procesor może przerwać wykonywanie instrukcji na różne sposoby, ale nadal może być przebudzony.
pjc50

Odpowiedzi:

85

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ł WAITinstrukcji, 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 w arch/x86/kernel/process.cją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żywanie MWAITzamiast HLTniektórych procesorów).

Wszystko to jest całkowicie oddzielone od stanów bezczynności w procesach, gdy czekają na zdarzenie (We / Wy itp.).

Stephen Kitt
źródło
3
Heh, widzę to teraz, dzięki. 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?)
grochmal,
30
Procesor budzi się z HALT przez przerwanie.
Johan Myréen,
1
@ JohanMyréen - Fajnie, to ma sens. W takim przypadku nawet przerwanie IRQ z urządzenia wejściowego obudziłoby go z powrotem. Dzięki.
grochmal
15
Lub bardziej wiarygodnie, przerwanie timera ... (manipulacja Tickless inna para kaloszy.)
Stephen Kitt
3
@EJP rzeczywiście jest to dość powszechna instrukcja, chociaż ma różne nazwy w różnych architekturach.
immibis
50

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 -

nothing:
    goto nothing

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.

Gilles
źródło
5
Zauważ, że nawet najbardziej podstawowe wbudowane procesory, takie jak mikrokontrolery oparte na AVR, mają instrukcję WFI (Wait For Interrupt), nawet jeśli ta instrukcja może być równoważna NOP w zależności od dokładnego modelu.
Jonas Schäfer
@JonasWielicki Myślałem, że zwykle wpadniesz w ciasną pętlę, jeśli nie masz nic do roboty, lub możesz przejść w stan niskiej mocy i czekać na przerwanie, aby cię z tego wyrzucić (niższe stany mocy zwykle wymagają więcej ” metalowe „przerywa”).
Nick T
1
@JonasWielicki Architektury zaprojektowane dla systemów wbudowanych dbają o zarządzanie energią, dlatego WFI jest tam ważne. Wiele starszych architektur nie ma takich rzeczy. Oryginalna architektura 8086 nie, AFAIR. Czy 68k ma WFI? Czy jest to standardowa funkcja MIPS? Moja znajomość programowania niskopoziomowego dotyczy głównie ARM, gdzie niski pobór mocy jest kwestią oczywistą, a WFI to tylko wierzchołek góry lodowej zarządzania energią.
Gilles
1
@Gilles 8086 miał instrukcję zatrzymania. Zobacz en.m.wikipedia.org/wiki/HLT_(x86_instruction) Instrukcja zawierała funkcję oszczędzania energii dopiero od 80486 DX4. Patrząc wstecz na historię HLT było już w 8080 roku i pochodzi z pochodnych (jak Z80).
pabouk
1
@pabouk HLTmoże wyłączyć warianty SL 386 i 486, zanim pojawił się DX4 (artykuł w Wikipedii jest niepoprawny).
Stephen Kitt
0

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”.

Johan Myréen
źródło
3
Hmmm ... Nie sądzę, że jest to rodzaj bezczynnego procesu, który tworzy CLONE_IDLETASK. Gdyby tak było, nie trzeba by go wcale tworzyć, tzn. Gdyby program planujący zignorował bezczynne procesy jądra na procesorach, nie musiałby tworzyć dla nich żadnych procesów podczas uruchamiania. (DW nie jest mój :))
grochmal
Trochę googlingu ujawnia, że ​​CLONE_IDLETASK jest wewnętrzną flagą jądra, która została wprowadzona wokół wersji jądra 2.5.14 w 2002 r., A następnie usunięta w 2004 r.
Johan Myréen
„an” idle proces, ale nie „ ” Proces bezczynności.
immibis