Quelle était la raison de la non-préemption des anciens noyaux Linux?

15

Pourquoi les premiers développeurs Linux ont-ils choisi d'implémenter un noyau non préemptif? Est-ce pour sauvegarder la synchronisation?

Pour autant que je sache, Linux a été développé au début des années 90, lorsque les PC n'avaient qu'un seul processeur. Quel avantage un noyau non préemptif offre-t-il sur de tels PC? Pourquoi, cependant, l'avantage est réduit par les processeurs multicœurs?

Narden
la source

Réponses:

25

Dans le contexte du noyau Linux, lorsque les gens parlent de préemption, ils se réfèrent souvent à la capacité du noyau à s'interrompre - essentiellement, à changer de tâche lors de l'exécution du code du noyau. Permettre que cela se produise est assez complexe, ce qui est probablement la principale raison pour laquelle il a fallu beaucoup de temps pour que le noyau soit rendu préemptif.

Au début, la plupart du code du noyau ne pouvait pas être interrompu de toute façon, car il était protégé par le gros verrou du noyau. Ce verrou a été progressivement éliminé de plus en plus de code du noyau, permettant plusieurs appels simultanés au noyau en parallèle (ce qui est devenu plus important à mesure que les systèmes SMP devenaient plus courants). Mais cela ne rendait toujours pas le noyau lui-même préemptif; cela a pris encore plus de développement, aboutissant à l' PREEMPT_RTensemble de correctifs qui a finalement été fusionné dans le noyau principal (et qui était capable de préempter le BKL de toute façon). De nos jours, le noyau peut être configuré pour être plus ou moins préemptif, selon les caractéristiques de débit et de latence que vous recherchez; voir la configuration du noyau associée pour plus de détails.

Comme vous pouvez le voir dans les explications de la configuration du noyau, la préemption affecte le débit et la latence, pas la concurrence. Sur les systèmes à processeur unique, la préemption est toujours utile car elle permet de traiter les événements avec des temps de réaction plus courts; cependant, il en résulte également un débit inférieur (car le noyau passe du temps à changer de tâche). La préemption permet à tout processeur donné, dans un système à processeur unique ou multiple, de passer à une autre tâche plus rapidement. Le facteur limitant sur les systèmes multi-CPU n'est pas la préemption, c'est les verrous, gros ou autres: n'importe quel code temporel prend un verrou, cela signifie qu'un autre CPU ne peut pas commencer à effectuer la même action.

Stephen Kitt
la source
11

Le noyau préemptif signifie seulement qu'il n'y a pas de Big Kernel Lock .

Linux avait des tâches multitâches préemptives (c'est-à-dire que le code utilisateur était préemptif) depuis son premier moment (pour autant que je sache, le tout premier Linux 0.0.1 téléchargé par Linus sur le serveur ftp funet était déjà multitâche préemptif). Si vous avez exécuté, par exemple, plusieurs processus de compression ou de compilation, ils ont été exécutés en parallèle dès le premier instant.

Contrairement à - à l'époque - largement utilisé Win31. Sur Win31, si une tâche a obtenu le CPU du "noyau", par défaut, il lui appartenait de déterminer quand redonner le contrôle à l'OS (ou à d'autres tâches). Si un processus n'avait pas de support spécial pour cette fonctionnalité (qui nécessitait un travail de programmation supplémentaire), alors pendant son exécution, toutes les autres tâches étaient suspendues. Même la plupart des applications de base intégrées au Win31 fonctionnaient ainsi.

Le multitâche préemptif signifie que les tâches n'ont aucun moyen d'allouer le processeur comme elles le souhaitent. Au lieu de cela, si leur intervalle de temps expire, le noyau les éloigne du processeur. Ainsi, dans les systèmes d'exploitation préemptifs, un processus mal écrit ou fonctionnant mal ne peut pas geler le système d'exploitation ou empêcher l'exécution d'autres processus. Linux a toujours été préemptif pour les processus d'espace utilisateur.

Le Big Kernel Lock signifie que dans certains cas, à l' intérieur de l'espace du noyau , il pourrait toujours y avoir des verrous, empêchant d'autres processus d'exécuter le code protégé. Par exemple, vous ne pouviez pas monter plusieurs systèmes de fichiers simultanément - si vous donniez plusieurs commandes de montage, elles étaient toujours exécutées consécutivement, car le montage des éléments requis pour allouer le Big Kernel Lock.

Pour rendre le noyau préemptif, il fallait éliminer ce gros verrou du noyau, c'est-à-dire rendre le montage et toutes les autres tâches pouvoir s'exécuter simultanément. C'était un gros travail.

Historiquement, cela était rendu vraiment urgent par le support croissant de SMP (support multi-CPU). Dans un premier temps, il y avait vraiment des cartes mères multi-CPU. Plus tard, plusieurs CPU ("cores") ont été intégrés dans une seule puce, aujourd'hui les cartes mères vraiment multi-CPU sont déjà rares (elles sont généralement dans des systèmes de serveurs coûteux). De plus, les systèmes vraiment monocœurs (où il n'y a qu'un seul processeur, avec un seul cœur) sont rares.

Ainsi, la réponse à votre question n'est pas "quelle était la raison de la non-préemption", car elle a toujours été préemptive. La vraie question est de savoir ce qui rendait l'exécution préemptive du noyau vraiment nécessaire . La réponse est pour cela: le rapport croissant des systèmes à plusieurs processeurs et à plusieurs cœurs.

peterh - Réintégrer Monica
la source
Je n'ai pas vraiment compris :( Jusqu'à la version 2.4 du noyau, seuls les processus utilisateur étaient préemptifs et le noyau n'était pas préemptif. Comme je l'ai déjà répondu, je pense que la raison était de sauver le travail sur les blocages de synchronisation qui pouvaient se produire avec préemptif l'implémentation sur le processus single-core Que pensez-vous?
Narden
@Narden Je ne sais pas si tu l'as lu. Jusqu'à la version 1.3 ou 2.0, un seul processus pouvait se trouver dans l'espace du noyau, même si plusieurs processus étaient en cours d'exécution. Cette limitation a été éliminée à peu près avec 2.0. Jusqu'à environ 2.4, il y avait un Big Kernel Lock (c'est-à-dire que le montage simultané de plusieurs systèmes de fichiers ne fonctionnait pas).
peterh
@Narden Mais ce n'est pas un multitâche coopératif, aucun processus n'a jamais été nécessaire pour rendre intentionnellement le CPU au planificateur de tâches. Oui, la raison pour laquelle le BKL était probable que faire cela correctement est beaucoup de travail: 1) les verrous doivent être divisés 2) des structures de données sans verrou doivent être utilisées si cela est possible 3) les verrous divisés conduisent à des blocages / livelocks, ce sont généralement des bogues particulièrement sales et difficiles à corriger, tous doivent être trouvés et corrigés 4) tous les pilotes doivent être portés sur les modifications de l'API du noyau.
peterh
Je l'ai lu pendant que je cherchais une réponse, et elle est également donnée à titre d'information dans un cours que je prends, intitulé Systèmes d'exploitation.
Narden
1
Le Big Kernel Lock a empêché d'autres threads d'entrer dans le noyau lorsque l'un s'exécutait dans le noyau. Un seul thread a été autorisé, car le noyau n'a pas été conçu dès le départ en pensant au multitraitement symétrique. Un noyau préemptif signifie cependant quelque chose de différent. Traditionnellement, le contexte d'exécution n'était modifié que lorsque le noyau revenait dans l'espace utilisateur. Dans un noyau préemptif, un thread peut être préempté au milieu de l'exécution du code du noyau.
Johan Myréen
3

Ce n'est pas une réponse technique mais une réponse historique à la question spécifique posée par l'OP: "Quelle était la raison de la non-préemption des noyaux Linux plus anciens?"

(Je suppose, comme expliqué par @peterh dans sa réponse et ses commentaires, que par "non-préemption", l'OP fait référence à l'un ou aux deux du fait qu'un seul processus utilisateur pourrait être à l'intérieur du noyau (dans une API) à un l'heure et / ou le Big Kernel Lock.)

Linus Torvalds souhaitait savoir comment fonctionnaient les systèmes d'exploitation et comment il avait appris à en écrire un. Son modèle, sa base et son environnement de développement initial étaient Minix, un système d'exploitation existant à des fins éducatives (c'est-à-dire pas un système d'exploitation de production) qui n'était pas gratuit (comme en open source, à l'époque - ce n'était pas gratuit comme dans la bière, Soit).

Il a donc écrit un noyau sans préemption (le Big Kernel Lock mentionné dans d'autres réponses) parce que c'est la façon dont vous le faites si vous voulez que votre nouveau système d'exploitation soit rapidement opérationnel à des fins éducatives: c'est beaucoup beaucoup plus simple de cette façon. Un noyau pour prendre en charge la multiprogrammation simultanée de programmes utilisateur et de périphériques est déjà assez difficile - il est extrêmement difficile de rendre le noyau lui-même simultané.

S'il avait su à quel point Linux deviendrait populaire / utile / important ... il l'aurait probablement fait de la même manière. (OMI seulement, je n'ai aucune idée de ce qu'il pense réellement.) Parce que tu dois marcher avant de pouvoir courir.

Et cela est resté longtemps ainsi car a) il y avait beaucoup d'autres travaux à faire pour faire de Linux ce qu'il est aujourd'hui (ou même ce qu'il était alors) et b) le changer serait une entreprise difficile et majeure (comme expliqué dans d'autres réponses).

davidbak
la source