Quelle est la différence entre les modes utilisateur et noyau dans les systèmes d'exploitation?


105

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?



1
@ CiroSantilli709 大 抓捕 六四 事件 法轮功 une question qui a été posée il y a 7 ans ne peut pas être fermée comme duplicata pour une question posée il y a 6 ans. S'il s'agit vraiment de doublons, la fermeture devrait être inversée.
Salvador Dali

2
@SalvadorDali salut, le consensus actuel est de fermer par "qualité": meta.stackexchange.com/questions/147643 / ... Puisque la "qualité" n'est pas mesurable, je me contente de voter pour. ;-) Cela dépend probablement de la question qui a frappé les meilleurs mots-clés Google newb sur le titre. Je vous encourage à simplement y copier votre réponse avec un avertissement ajouté en bas, et un lien à partir de celui-ci, au cas où il se ferme.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Réponses:


144
  1. 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.

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

Comprendre le mode utilisateur et noyau


Je me demande quand le processeur exécute le code du système d'exploitation, dans quel mode se trouve le processeur?
JackieLam

2
@JackieLam: Il devrait être en mode noyau.
kadina

Donc, en soi, pour exécuter un processus d' espace utilisateur , il doit être mappé à l' espace noyau ?
roottraveller

@rahul Je doute que la mémoire de référence puisse être obtenue en mode utilisateur ou que la manipulation la plus simple des données entraînera un changement de mode coûteux dans un langage comme java.
maki XIE

48

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 dans lequel tous les programmes utilisateur s'exécutent. Il n'a pas accès à la RAM et au matériel. La raison en est que si tous les programmes s'exécutaient en mode noyau, ils seraient capables d'écraser la mémoire de l'autre. S'il a besoin d'accéder à l'une de ces fonctionnalités, il effectue un appel à l'API sous-jacente. Chaque processus démarré par Windows, à l'exception du processus système, s'exécute en mode utilisateur.

Mode noyau:

  • mode où tous les programmes du noyau s'exécutent (différents pilotes). Il a accès à toutes les ressources et au matériel sous-jacent. Toute instruction CPU peut être exécutée et chaque adresse mémoire est accessible. Ce mode est réservé aux conducteurs qui opèrent au niveau le plus bas

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

http://en.wikipedia.org/wiki/Direct_memory_access

http://en.wikipedia.org/wiki/Interrupt_request


Je me demande quand le processeur exécute le code du système d'exploitation, dans quel mode se trouve le processeur?
JackieLam

1
@JackieLam: mode noyau
Apurv Nerlekar

10

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.

Communication entre le mode utilisateur et le mode noyau


6

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:

  • 0 pour le noyau
  • 3 pour les utilisateurs

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 Privlqui 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 = 0signifie 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 inet 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 0x80ousyscall 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
    

    GitHub en amont .

    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' execappel 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:

  • il est plus facile de créer des programmes car vous êtes plus certain que l'un n'interférera pas avec l'autre. Par exemple, un processus utilisateur n'a pas à se soucier d'écraser la mémoire d'un autre programme à cause de la pagination, ni de mettre le matériel dans un état invalide pour un autre processus.
  • c'est plus sûr. Par exemple, les autorisations de fichiers et la séparation de la mémoire peuvent empêcher une application de piratage de lire vos données bancaires. Cela suppose, bien sûr, que vous fassiez confiance au noyau.

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' svcinstruction (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
    

    GitHub en amont .

    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' hvcinstruction (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' smcinstruction (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:

entrez la description de l'image ici

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:

entrez la description de l'image ici

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' MRSinstruction: 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.


1
Étant donné que cette question n'est spécifique à aucun système d'exploitation inet qu'elle outest 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.
Michael Petch

Bien sûr, vous définissez les bits IOPL sur la valeur 3, le programme ring 3 a un accès complet au port et les autorisations TSS IO ne s'appliquent pas.
Michael Petch

@MichaelPetch merci, je ne savais pas ça. J'ai mis à jour la réponse.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

5

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 .


2
Ceci est important pour vous en tant que programmeur car les bogues du noyau ont tendance à faire des ravages bien pires que ceux auxquels vous êtes habitué. Une des raisons de la distinction noyau / utilisateur est que le noyau peut surveiller / contrôler les ressources système critiques et protéger chaque utilisateur des autres. C'est un peu trop simplifié, mais toujours utile, de se rappeler que les bogues des utilisateurs sont souvent ennuyeux, mais les bogues du noyau ont tendance à faire tomber la machine entière.
Adam Liss

3

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.


2

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:

  • Protéger les programmes utilisateurs de l'accès à toute la mémoire, pour ne pas laisser les programmes écraser l'OS par exemple,
  • empêcher les programmes utilisateur d'exécuter des instructions sensibles telles que celles qui modifient les limites du pointeur de la mémoire du processeur, pour ne pas laisser les programmes briser leurs limites de mémoire, par exemple.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.