Que fait un processus CPU inactif?

73

En regardant la source de stracej'ai trouvé l'utilisation du drapeau de clone CLONE_IDLETASKqui est décrit comme suit:

#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */

Après une analyse plus approfondie, j’ai constaté que, bien que cet indicateur ne soit pas couvert, man cloneil est en fait utilisé par le noyau pendant le processus de démarrage pour créer des processus inactifs (qui doivent tous avoir le PID 0) pour chaque processeur de la machine. c'est-à-dire qu'une machine avec 8 processeurs aura au moins 7 (voir question ci-dessous) de tels processus "en cours d'exécution" (guillemets).

Cela m’amène à poser une ou deux questions sur le fonctionnement réel de ce processus "inactif". Mon hypothèse est qu'il exécute l'opération NOP de manière continue jusqu'à la fin de son délai et que le noyau assigne un processus réel à exécuter ou assigne à nouveau le processus inactif (si la CPU n'est pas utilisée). Pourtant, c'est une supposition complète. Alors:

  1. Par exemple, sur une machine avec 8 CPU, 7 processus inactifs seront-ils créés? (et un processeur sera tenu par le noyau lui-même sans travail utilisateur performant?)

  2. Le processus inactif est-il vraiment juste un flux infini d'opérations NOP? (ou une boucle qui fait la même chose).

  3. Est-ce que l'utilisation du processeur (par exemple uptime) est simplement calculée en fonction de combien de temps le processus inactif était sur le processeur et combien de temps il n'était pas là pendant une certaine période?


PS Il est probable que cette question est en grande partie due au fait que je ne comprends pas tout à fait le fonctionnement d’un processeur. c'est-à-dire que je comprends l'assemblage, les délais et les interruptions mais je ne sais pas comment, par exemple, un processeur peut utiliser plus ou moins d'énergie en fonction de ce qu'il est en train d'exécuter. Je serais reconnaissant si quelqu'un peut m'éclairer là-dessus aussi.

grochmal
la source
17
J'ai dû résister à la tentation de simplement écrire "Rien du tout" quand j'ai vu le titre.
Vality
4
La plupart des processeurs modernes réduisent dynamiquement leur fréquence d'horloge et leur consommation d'énergie lorsqu'ils sont inactifs ou sous faible charge ( mise à l'échelle dynamique des fréquences , par exemple SpeedStep pour les processeurs Intel). Si vous overclockez un processeur, il désactivera généralement ce comportement, ce qui le maintiendra à une fréquence d'horloge maximale même lorsqu'il est inactif.
Nat
2
Voir aussi "États d'alimentation ACPI": un processeur peut arrêter l'exécution des instructions de différentes manières, tout en restant réactif.
pjc50

Réponses:

85

La tâche inactive sert à la comptabilisation des processus et à la réduction de la consommation d'énergie. Sous Linux, une tâche inactive est créée pour chaque processeur et verrouillée à ce processeur. chaque fois qu’aucun autre processus n’est exécuté sur cette CPU, la tâche inactive est planifiée. Le temps passé dans les tâches inactives apparaît comme un temps «inactif» dans des outils tels que top. (La disponibilité est calculée différemment.)

Unix semble avoir toujours eu une boucle d'inactivité (mais pas nécessairement une tâche inactive, voir la réponse de Gilles ), et même en V1, il utilisait une WAITinstruction qui arrêtait le processeur jusqu'à ce qu'une interruption se produise (il valait "attendre interrompre"). Certains autres systèmes d'exploitation utilisaient des boucles occupés, notamment DOS, OS / 2 et les premières versions de Windows. Cela fait longtemps que les processeurs utilisent ce type d’instructions d’attente pour réduire leur consommation d’énergie et leur production de chaleur. Vous pouvez voir diverses implémentations de tâches inactives, par exemple arch/x86/kernel/process.cdans le noyau Linux: celle de base appelle simplementHLT, qui arrête le processeur jusqu’à ce qu’une interruption se produise (et active le mode d’économie d’énergie C1), les autres implémentations traitent divers bugs ou inefficacités ( par exemple, l’ utilisation MWAITau lieu de HLTsur certains CPU).

Tout cela est complètement séparé des états inactifs dans les processus, lorsqu'ils attendent un événement (E / S, etc.).

Stephen Kitt
la source
3
Heh, je le vois maintenant, merci. play_dead()est un nom mnémonique très sympa pour exécuter HALT. N'y aurait-il pas un risque à envoyer HALT à chaque CPU et par conséquent à bloquer? (c.-à-d. atteindre cette situation, HALT tous les processeurs, serait un bogue correct dans le noyau?)
grochmal
30
La CPU sort de HALT via une interruption.
Johan Myréen
1
@ JohanMyréen - Cool, ça a du sens. Dans ce cas, même une interruption IRQ d'un périphérique d'entrée le réveillerait. Merci.
Grochmal
15
Ou plus sûrement, l'interruption de la minuterie ... (La manipulation sans fil est une autre source de problèmes.)
Stephen Kitt
3
@EJP en effet, c'est une instruction assez commune, même si elle a des noms différents dans différentes architectures.
user253751
50

Dans la conception de manuel d'un planificateur de processus, si le planificateur n'a pas de processus à planifier (c'est-à-dire si tous les processus sont bloqués, attend une entrée), il attend une interruption du processeur. L'interruption peut indiquer une entrée provenant d'un périphérique (action de l'utilisateur, paquet réseau, lecture terminée sur un disque, etc.) ou peut être une interruption de la minuterie qui déclenche une minuterie dans un processus.

Le planificateur de Linux n'a pas de code spécial pour un cas rien à faire. Au lieu de cela, il code le cas rien à faire en tant que processus spécial, le processus inactif. Le processus inactif n'est planifié que si aucun autre processus n'est programmable (il a effectivement une priorité infiniment basse). Le processus inactif fait en fait partie du noyau: il s’agit d’un thread de noyau, c’est-à-dire un thread qui exécute le code dans le noyau, plutôt que le code dans un processus. (Plus précisément, il existe un tel thread pour chaque CPU.) Lorsque le processus inactif s'exécute, il effectue l'opération d'attente d'interruption.

Le fonctionnement de l'attente d'interruption dépend des capacités du processeur. Avec la conception de processeur la plus élémentaire, ce n'est qu'une boucle occupée -

nothing:
    goto nothing

Le processeur continue d'exécuter une instruction de branche pour toujours, ce qui n'apporte rien. La plupart des systèmes d'exploitation modernes ne le font que s'ils fonctionnent sur un processeur où rien ne peut être amélioré, et la plupart des processeurs ont quelque chose de mieux. Plutôt que de dépenser de l'énergie à ne rien faire à part chauffer la pièce, idéalement, le processeur devrait être éteint. Ainsi, le noyau exécute un code qui demande au processeur de s’éteindre tout au moins, ou du moins d’éteindre la plus grande partie du processeur. Il doit y avoir au moins une petite partie qui reste allumée, le contrôleur d'interruptions. Lorsqu'un périphérique déclenche une interruption, le contrôleur d'interruption envoie un signal de réveil au processeur principal (ou à une partie de celui-ci).

En pratique, les processeurs modernes tels qu'Intel / AMD et ARM ont de nombreux paramètres de gestion de l'alimentation complexes. Le système d'exploitation peut estimer la durée pendant laquelle le processeur reste en mode veille et choisit différents modes de consommation réduite. Les modes offrent différents compromis entre la consommation d'énergie en mode veille et le temps nécessaire pour entrer en mode veille et en sortir. Sur certains processeurs, le système d'exploitation peut également réduire la fréquence d'horloge du processeur lorsqu'il constate que les processus ne consomment pas beaucoup de temps processeur.

Gilles, arrête de faire le mal
la source
5
Notez que même les processeurs embarqués les plus élémentaires, tels que les microcontrôleurs basés sur AVR, ont une instruction WFI (Wait For Interrupt), même si cette instruction peut être équivalente à NOP selon le modèle exact.
Jonas Schäfer
@JonasWielicki Je pensais que vous alliez généralement dans une boucle serrée si vous n'aviez rien à faire, ou vous pouviez passer à un état de faible consommation et attendre que l'interruption vous assomme (les états de faible puissance exigent habituellement plus " "métal" interrompt).
Nick T
1
@JonasWielicki Les architectures conçues pour les systèmes embarqués se préoccupent de la gestion de l'alimentation; WFI y joue donc un rôle important. Beaucoup d'architectures plus anciennes n'ont pas une telle chose. L'architecture originale 8086 ne l'a pas été, AFAIR. Est-ce que 68k a WFI? Est-ce une fonctionnalité standard sur MIPS? Ma connaissance de la programmation de bas niveau concerne principalement ARM, où une faible consommation d'énergie va de soi et WFI n'est que la partie visible de l'iceberg de la gestion de l'alimentation.
Gilles 'SO- arrête d'être méchant'
1
@Gilles 8086 a eu une instruction d'arrêt. Voir en.m.wikipedia.org/wiki/HLT_(x86_instruction) L'instruction comprenait la fonctionnalité d'économie d'énergie uniquement à partir de 80486 DX4. Retour en arrière dans l'histoire HLT était déjà dans 8080 et dérivés (comme Z80).
Pabouk
1
@pabouk HLTpourrait éteindre les variantes SL des 386 et 486, avant la sortie du DX4 (l'article de Wikipedia est incorrect).
Stephen Kitt
0

Non, une tâche inactive ne gaspille pas les cycles du processeur. Le planificateur ne sélectionne tout simplement pas de processus inactif à exécuter. Un processus inactif attend qu'un événement se produise pour qu'il puisse continuer. Par exemple, il peut être en attente d'une entrée dans un read()appel système.

À propos, le noyau n'est pas un processus séparé. Le code du noyau est toujours exécuté dans le contexte d'un processus (enfin, sauf dans le cas particulier d'un thread de noyau), il n'est donc pas correct de dire "et un processeur sera détenu par le noyau lui-même sans exécution de l'espace utilisateur".

Johan Myréen
la source
3
Hmmm ... Je ne pense pas que ce soit le genre de processus inactif créé par CLONE_IDLETASK. Si cela avait été le cas, il n'aurait pas besoin d'être créé du tout, c'est-à-dire si le planificateur avait ignoré les processus inactifs du noyau sur les CPU, il n'aurait pas besoin de créer de processus pour ceux-ci lors du démarrage. (le DW n'est pas le mien cependant :))
grochmal
Une petite recherche sur Google révèle que CLONE_IDLETASK est un indicateur interne au noyau qui a été introduit autour de la version 2.5.14 du noyau en 2002, puis supprimé en 2004.
Johan Myréen
"un" processus inactif, mais pas " le " processus inactif.
user253751