Quelles sont les différences entre le mode utilisateur et le mode noyau, pourquoi et comment activez-vous l'un ou l'autre, et quels sont leurs cas d'utilisation?
Quelles sont les différences entre le mode utilisateur et le mode noyau, pourquoi et comment activez-vous l'un ou l'autre, et quels sont leurs cas d'utilisation?
Réponses:
Mode noyau
En mode noyau, le code en cours d'exécution dispose d'un accès complet et illimité au matériel sous-jacent. Il peut exécuter n'importe quelle instruction CPU et référencer n'importe quelle adresse mémoire. Le mode noyau est généralement réservé aux fonctions les plus fiables et les plus fiables du système d'exploitation. Les plantages en mode noyau sont catastrophiques; ils arrêteront tout le PC.
Mode utilisateur
En mode utilisateur, le code en cours d'exécution n'a pas la capacité d'accéder directement au matériel ou à la mémoire de référence. Le code exécuté en mode utilisateur doit déléguer aux API système pour accéder au matériel ou à la mémoire. En raison de la protection offerte par ce type d'isolement, les plantages en mode utilisateur sont toujours récupérables. La plupart du code exécuté sur votre ordinateur s'exécutera en mode utilisateur.
Lire la suite
Ce sont deux modes différents dans lesquels votre ordinateur peut fonctionner. Avant cela, lorsque les ordinateurs étaient comme une grande pièce, si quelque chose se bloque, tout l'ordinateur s'arrête. Les architectes informatiques décident donc de le changer. Les microprocesseurs modernes implémentent dans le matériel au moins 2 états différents.
Mode utilisateur:
Mode noyau:
Comment le changement se produit.
Le passage du mode utilisateur au mode noyau ne se fait pas automatiquement par le CPU. Le CPU est interrompu par des interruptions (minuteries, clavier, E / S). Lorsqu'une interruption se produit, le processeur arrête d'exécuter le programme en cours d'exécution, passe en mode noyau, exécute le gestionnaire d'interruption. Ce gestionnaire enregistre l'état du CPU, effectue ses opérations, restaure l'état et revient en mode utilisateur.
http://en.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
http://tldp.org/HOWTO/KernelAnalysis-HOWTO-3.html
Un processeur dans un ordinateur exécutant Windows a deux modes différents: le mode utilisateur et le mode noyau. Le processeur bascule entre les deux modes en fonction du type de code exécuté sur le processeur. Les applications s'exécutent en mode utilisateur et les principaux composants du système d'exploitation s'exécutent en mode noyau. Alors que de nombreux pilotes fonctionnent en mode noyau, certains pilotes peuvent s'exécuter en mode utilisateur.
Lorsque vous démarrez une application en mode utilisateur, Windows crée un processus pour l'application. Le processus fournit à l'application un espace d'adressage virtuel privé et une table de descripteurs privés. Étant donné que l'espace d'adressage virtuel d'une application est privé, une application ne peut pas modifier les données appartenant à une autre application. Chaque application s'exécute de manière isolée et si une application se bloque, le plantage est limité à cette seule application. Les autres applications et le système d'exploitation ne sont pas affectés par le plantage.
En plus d'être privé, l'espace d'adressage virtuel d'une application en mode utilisateur est limité. Un processeur fonctionnant en mode utilisateur ne peut pas accéder aux adresses virtuelles réservées au système d'exploitation. La limitation de l'espace d'adressage virtuel d'une application en mode utilisateur empêche l'application d'altérer, voire d'endommager, les données critiques du système d'exploitation.
Tout le code qui s'exécute en mode noyau partage un seul espace d'adressage virtuel. Cela signifie qu'un pilote en mode noyau n'est pas isolé des autres pilotes et du système d'exploitation lui-même. Si un pilote en mode noyau écrit accidentellement à la mauvaise adresse virtuelle, les données appartenant au système d'exploitation ou à un autre pilote peuvent être compromises. Si un pilote en mode noyau tombe en panne, tout le système d'exploitation se bloque.
Si vous êtes un utilisateur Windows, passez une fois par ce lien, vous en aurez plus.
Les anneaux CPU sont la distinction la plus claire
En mode protégé x86, le CPU est toujours dans l'un des 4 anneaux. Le noyau Linux n'utilise que 0 et 3:
C'est la définition la plus dure et la plus rapide du noyau par rapport à l'utilisateur.
Pourquoi Linux n'utilise pas les anneaux 1 et 2: Anneaux de privilèges CPU: Pourquoi les anneaux 1 et 2 ne sont pas utilisés?
Comment la sonnerie actuelle est-elle déterminée?
La sonnerie actuelle est sélectionnée par une combinaison de:
table de descripteur global: une table en mémoire des entrées GDT, et chaque entrée a un champ Privl
qui code l'anneau.
L'instruction LGDT définit l'adresse sur la table de descripteurs actuelle.
Voir aussi: http://wiki.osdev.org/Global_Descriptor_Table
les registres de segments CS, DS, etc., qui pointent vers l'index d'une entrée dans le GDT.
Par exemple, CS = 0
signifie que la première entrée du GDT est actuellement active pour le code en cours d'exécution.
Que peut faire chaque anneau?
La puce CPU est construite physiquement de telle sorte que:
la sonnerie 0 peut tout faire
ring 3 ne peut pas exécuter plusieurs instructions et écrire dans plusieurs registres, notamment:
ne peut pas changer sa propre bague! Sinon, il pourrait se mettre à sonner 0 et les sonneries seraient inutiles.
En d'autres termes, impossible de modifier le descripteur de segment actuel , qui détermine la sonnerie actuelle.
impossible de modifier les tables de pages: comment fonctionne la pagination x86?
En d'autres termes, ne peut pas modifier le registre CR3 et la pagination elle-même empêche la modification des tables de pages.
Cela empêche un processus de voir la mémoire d'autres processus pour des raisons de sécurité / facilité de programmation.
impossible d'enregistrer les gestionnaires d'interruption. Ceux-ci sont configurés en écrivant dans des emplacements de mémoire, ce qui est également empêché par la pagination.
Les gestionnaires s'exécutent dans l'anneau 0 et briseraient le modèle de sécurité.
En d'autres termes, ne peut pas utiliser les instructions LGDT et LIDT.
ne peut pas faire d'instructions IO comme in
et out
, et donc avoir des accès matériels arbitraires.
Sinon, par exemple, les autorisations sur les fichiers seraient inutiles si un programme pouvait lire directement à partir du disque.
Plus précisément grâce à Michael Petch : il est en fait possible pour l'OS d'autoriser les instructions IO sur l'anneau 3, ceci est en fait contrôlé par le segment d'état de la tâche .
Ce qui n'est pas possible, c'est que l'anneau 3 se donne la permission de le faire s'il ne l'avait pas en premier lieu.
Linux le refuse toujours. Voir aussi: Pourquoi Linux n'utilise-t-il pas le changement de contexte matériel via le TSS?
Comment les programmes et les systèmes d'exploitation font-ils la transition entre les anneaux?
lorsque le processeur est allumé, il commence à exécuter le programme initial dans l'anneau 0 (en quelque sorte, mais c'est une bonne approximation). Vous pouvez penser que ce programme initial est le noyau (mais c'est normalement un bootloader qui appelle alors le noyau toujours dans l'anneau 0 ).
quand un processus utilisateur veut que le noyau fasse quelque chose pour lui comme écrire dans un fichier, il utilise une instruction qui génère une interruption telle que int 0x80
ousyscall
pour signaler le noyau. x86-64 Linux syscall bonjour exemple du monde:
.data
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
.text
.global _start
_start:
/* write */
mov $1, %rax
mov $1, %rdi
mov $hello_world, %rsi
mov $hello_world_len, %rdx
syscall
/* exit */
mov $60, %rax
mov $0, %rdi
syscall
compilez et exécutez:
as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out
Lorsque cela se produit, le CPU appelle un gestionnaire de rappel d'interruption que le noyau a enregistré au moment du démarrage. Voici un exemple concret de baremetal qui enregistre un gestionnaire et l'utilise .
Ce gestionnaire s'exécute dans l'anneau 0, qui décide si le noyau autorisera cette action, exécutera l'action et redémarrera le programme userland dans l'anneau 3. x86_64
lorsque l' exec
appel système est utilisé (ou lorsque le noyau démarrera/init
), le noyau prépare les registres et la mémoire du nouveau processus userland, puis il saute au point d'entrée et fait passer le CPU en sonnerie 3
Si le programme essaie de faire quelque chose de vilain comme écrire dans un registre ou une adresse mémoire interdits (à cause de la pagination), le CPU appelle également un gestionnaire de rappel du noyau dans l'anneau 0.
Mais comme le userland était vilain, le noyau pourrait tuer le processus cette fois, ou lui donner un avertissement avec un signal.
Lorsque le noyau démarre, il configure une horloge matérielle avec une fréquence fixe, qui génère périodiquement des interruptions.
Cette horloge matérielle génère des interruptions qui exécutent l'anneau 0 et lui permettent de planifier les processus utilisateur à réveiller.
De cette façon, la planification peut se produire même si les processus n'effectuent aucun appel système.
Quel est l'intérêt d'avoir plusieurs anneaux?
Il y a deux avantages majeurs à séparer le noyau et le userland:
Comment jouer avec?
J'ai créé une configuration bare metal qui devrait être un bon moyen de manipuler les anneaux directement: https://github.com/cirosantilli/x86-bare-metal-examples
Je n'ai malheureusement pas eu la patience de faire un exemple de userland, mais je suis allé aussi loin que la configuration de la pagination, donc userland devrait être faisable. J'adorerais voir une demande de tirage.
Alternativement, les modules du noyau Linux s'exécutent dans l'anneau 0, vous pouvez donc les utiliser pour essayer des opérations privilégiées, par exemple lire les registres de contrôle: Comment accéder aux registres de contrôle cr0, cr2, cr3 depuis un programme? Obtenir une erreur de segmentation
Voici une configuration pratique de QEMU + Buildroot pour l'essayer sans tuer votre hôte.
L'inconvénient des modules du noyau est que d'autres kthreads sont en cours d'exécution et pourraient interférer avec vos expériences. Mais en théorie, vous pouvez prendre en charge tous les gestionnaires d'interruptions avec votre module de noyau et posséder le système, ce serait un projet intéressant en fait.
Anneaux négatifs
Bien que les anneaux négatifs ne soient pas réellement référencés dans le manuel d'Intel, il existe en fait des modes CPU qui ont d'autres capacités que l'anneau 0 lui-même, et sont donc un bon choix pour le nom «anneau négatif».
Un exemple est le mode hyperviseur utilisé dans la virtualisation.
Pour plus de détails, voir:
BRAS
Dans ARM, les anneaux sont appelés Niveaux d'exception à la place, mais les idées principales restent les mêmes.
Il existe 4 niveaux d'exception dans ARMv8, couramment utilisés comme:
EL0: userland
EL1: noyau ("superviseur" dans la terminologie ARM).
Saisie avec l' svc
instruction (SuperVisor Call), précédemment connue sous le nom de swi
before unified assembly , qui est l'instruction utilisée pour effectuer des appels système Linux. Exemple Hello world ARMv8:
bonjour.
.text
.global _start
_start:
/* write */
mov x0, 1
ldr x1, =msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
Testez-le avec QEMU sur Ubuntu 16.04:
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-as -o hello.o hello.S
arm-linux-gnueabihf-ld -o hello hello.o
qemu-arm hello
Voici un exemple concret de baremetal qui enregistre un gestionnaire SVC et effectue un appel SVC .
EL2: hyperviseurs , par exemple Xen .
Entré avec l' hvc
instruction (Appel HyperVisor).
Un hyperviseur est à un OS, ce qu'un OS est à un espace utilisateur.
Par exemple, Xen vous permet d'exécuter plusieurs systèmes d'exploitation tels que Linux ou Windows sur le même système en même temps, et il isole les systèmes d'exploitation les uns des autres pour la sécurité et la facilité de débogage, tout comme Linux le fait pour les programmes utilisateur.
Les hyperviseurs sont un élément clé de l'infrastructure cloud d'aujourd'hui: ils permettent à plusieurs serveurs de fonctionner sur un seul matériel, en maintenant l'utilisation du matériel toujours proche de 100% et en économisant beaucoup d'argent.
AWS, par exemple, a utilisé Xen jusqu'en 2017, date à laquelle son passage au KVM a fait l'actualité .
EL3: encore un autre niveau. Exemple TODO.
Entré avec l' smc
instruction (appel en mode sécurisé)
Le modèle de référence d'architecture ARMv8 DDI 0487C.a - Chapitre D1 - Le modèle du programmeur de niveau système AArch64 - La figure D1-1 illustre cela magnifiquement:
La situation ARM a un peu changé avec l'avènement des extensions d'hôte de virtualisation ARMv8.1 (VHE) . Cette extension permet au noyau de fonctionner efficacement dans EL2:
VHE a été créé parce que les solutions de virtualisation dans le noyau Linux telles que KVM ont gagné du terrain par rapport à Xen (voir par exemple le passage d'AWS au KVM mentionné ci-dessus), car la plupart des clients n'ont besoin que de machines virtuelles Linux, et comme vous pouvez l'imaginer, être tous dans un seul projet, KVM est plus simple et potentiellement plus efficace que Xen. Alors maintenant, le noyau Linux hôte joue le rôle d'hyperviseur dans ces cas.
Notez comment ARM, peut-être en raison du recul, a une meilleure convention de dénomination pour les niveaux de privilège que x86, sans avoir besoin de niveaux négatifs: 0 étant le plus bas et 3 le plus élevé. Les niveaux supérieurs ont tendance à être créés plus souvent que les niveaux inférieurs.
Le EL actuel peut être interrogé avec l' MRS
instruction: quel est le mode d'exécution actuel / niveau d'exception, etc.?
ARM n'exige pas que tous les niveaux d'exception soient présents pour permettre des implémentations qui n'ont pas besoin de la fonction pour enregistrer la zone de puce. ARMv8 "Niveaux d'exception" dit:
Une implémentation peut ne pas inclure tous les niveaux d'exception. Toutes les implémentations doivent inclure EL0 et EL1. EL2 et EL3 sont facultatifs.
QEMU, par exemple, utilise par défaut EL1, mais EL2 et EL3 peuvent être activés avec les options de ligne de commande: qemu-system-aarch64 entrant el1 lors de l'émulation de la mise sous tension de a53
Extraits de code testés sur Ubuntu 18.10.
in
et qu'elle out
est disponible pour sonner 3. Le TSS peut pointer vers une table d'autorisations d'E / S dans la tâche en cours accordant un accès en lecture / écriture à tous ou à des ports spécifiques.
Je vais essayer dans le noir et deviner que vous parlez de Windows. En un mot, le mode noyau a un accès complet au matériel, mais pas le mode utilisateur. Par exemple, de nombreux pilotes de périphériques, sinon la plupart, sont écrits en mode noyau car ils doivent contrôler les détails plus fins de leur matériel.
Voir aussi ce wikibook .
D'autres réponses expliquaient déjà la différence entre le mode utilisateur et le mode noyau. Si vous voulez vraiment entrer dans les détails, vous devriez obtenir une copie de Windows Internals , un excellent livre écrit par Mark Russinovich et David Solomon décrivant l'architecture et les détails internes des différents systèmes d'exploitation Windows.
Quoi
Fondamentalement, la différence entre les modes noyau et utilisateur ne dépend pas du système d'exploitation et n'est obtenue qu'en limitant certaines instructions à exécuter uniquement en mode noyau au moyen de la conception matérielle. Toutes les autres fins telles que la protection de la mémoire ne peuvent être effectuées que par cette restriction.
Comment
Cela signifie que le processeur vit soit en mode noyau, soit en mode utilisateur. En utilisant certains mécanismes, l'architecture peut garantir que chaque fois qu'elle passe en mode noyau, le code du système d'exploitation est récupéré pour être exécuté.
Pourquoi
Ayant cette infrastructure matérielle, ceux-ci pourraient être réalisés dans les systèmes d'exploitation courants: