¿Cuál es la diferencia entre los modos de usuario y kernel en los sistemas operativos?

105

¿Cuáles son las diferencias entre el modo de usuario y el modo de kernel, por qué y cómo se activa alguno de ellos y cuáles son sus casos de uso?

Alex
fuente
1
Posible duplicado de ¿Cuál es la diferencia entre el espacio del kernel y el espacio del usuario?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@ CiroSantilli709 大 抓捕 六四 事件 法轮功 una pregunta que se hizo hace 7 años no puede ser cerrada como un duplicado de una pregunta hecha hace 6 años. Si son realmente duplicados, el cierre debería ser al revés.
Salvador Dali
2
@SalvadorDali hola, el consenso actual es cerrar por "calidad": meta.stackexchange.com/questions/147643/… Dado que la "calidad" no se puede medir, simplemente me baso en los votos positivos. ;-) Lo más probable es que se deba a qué pregunta dio en el título a las mejores palabras clave nuevas de Google. Le animo a que simplemente copie su respuesta allí con un descargo de responsabilidad agregado en la parte inferior y un enlace de este, en caso de que se cierre.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

144
  1. Modo kernel

    En el modo Kernel, el código de ejecución tiene acceso completo y sin restricciones al hardware subyacente. Puede ejecutar cualquier instrucción de la CPU y hacer referencia a cualquier dirección de memoria. El modo kernel generalmente se reserva para las funciones de nivel más bajo y más confiables del sistema operativo. Los bloqueos en el modo kernel son catastróficos; detendrán toda la PC.

  2. Modo de usuario

    En el modo de usuario, el código de ejecución no tiene la capacidad de acceder directamente al hardware o la memoria de referencia. El código que se ejecuta en modo de usuario debe delegarse en las API del sistema para acceder al hardware o la memoria. Debido a la protección que brinda este tipo de aislamiento, los bloqueos en el modo de usuario siempre son recuperables. La mayor parte del código que se ejecuta en su computadora se ejecutará en modo de usuario.

Lee mas

Comprensión del modo de usuario y kernel

rahul
fuente
Me pregunto cuándo la CPU está ejecutando el código del sistema operativo, ¿en qué modo está el procesador?
JackieLam
2
@JackieLam: Debería estar en modo kernel.
kadina
Entonces, per se, para ejecutar un proceso de espacio de usuario , ¿debe asignarse al espacio del kernel ?
roottraveller
@rahul Dudo que la memoria de referencia se pueda obtener mediante el modo de usuario o que la manipulación de datos más simple resulte en un cambio de modo costoso en un lenguaje como Java.
maki XIE
48

Estos son dos modos diferentes en los que puede funcionar su computadora. Antes de esto, cuando las computadoras eran como una gran sala, si algo fallaba, paraba toda la computadora. Entonces, los arquitectos informáticos deciden cambiarlo. Los microprocesadores modernos implementan en hardware al menos 2 estados diferentes.

Modo de usuario:

  • modo donde se ejecutan todos los programas de usuario. No tiene acceso a RAM ni hardware. La razón de esto es que si todos los programas se ejecutaran en modo kernel, podrían sobrescribir la memoria de los demás. Si necesita acceder a alguna de estas funciones, realiza una llamada a la API subyacente. Cada proceso iniciado por Windows, excepto el proceso del sistema, se ejecuta en modo de usuario.

Modo kernel:

  • modo donde se ejecutan todos los programas del kernel (diferentes controladores). Tiene acceso a todos los recursos y hardware subyacente. Se puede ejecutar cualquier instrucción de CPU y se puede acceder a todas las direcciones de memoria. Este modo está reservado para los conductores que operan en el nivel más bajo.

Cómo ocurre el cambio.

La CPU no realiza automáticamente el cambio del modo de usuario al modo de núcleo. La CPU es interrumpida por interrupciones (temporizadores, teclado, E / S). Cuando ocurre una interrupción, la CPU deja de ejecutar el programa en ejecución actual, cambia al modo kernel y ejecuta el controlador de interrupciones. Este controlador guarda el estado de la CPU, realiza sus operaciones, restaura el estado y regresa al modo de usuario.

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

Salvador Dalí
fuente
Me pregunto cuándo la CPU está ejecutando el código del sistema operativo, ¿en qué modo está el procesador?
JackieLam
1
@JackieLam: modo kernel
Apurv Nerlekar
10

Un procesador en una computadora que ejecuta Windows tiene dos modos diferentes: modo de usuario y modo de kernel. El procesador cambia entre los dos modos según el tipo de código que se esté ejecutando en el procesador. Las aplicaciones se ejecutan en modo de usuario y los componentes centrales del sistema operativo se ejecutan en modo kernel. Si bien muchos controladores se ejecutan en modo kernel, algunos controladores pueden ejecutarse en modo de usuario.

Cuando inicia una aplicación en modo de usuario, Windows crea un proceso para la aplicación. El proceso proporciona a la aplicación un espacio de direcciones virtuales privadas y una tabla de identificadores privados. Debido a que el espacio de direcciones virtuales de una aplicación es privado, una aplicación no puede alterar los datos que pertenecen a otra aplicación. Cada aplicación se ejecuta de forma aislada y, si una aplicación falla, la falla se limita a esa aplicación. Otras aplicaciones y el sistema operativo no se ven afectados por el bloqueo.

Además de ser privado, el espacio de direcciones virtuales de una aplicación en modo usuario es limitado. Un procesador que se ejecuta en modo de usuario no puede acceder a direcciones virtuales reservadas para el sistema operativo. Limitar el espacio de direcciones virtuales de una aplicación en modo de usuario evita que la aplicación altere, y posiblemente dañe, datos críticos del sistema operativo.

Todo el código que se ejecuta en modo kernel comparte un único espacio de direcciones virtuales. Esto significa que un controlador en modo kernel no está aislado de otros controladores y del sistema operativo en sí. Si un controlador en modo kernel escribe accidentalmente en la dirección virtual incorrecta, los datos que pertenecen al sistema operativo oa otro controlador podrían verse comprometidos. Si un controlador en modo kernel falla, todo el sistema operativo falla.

Si es usuario de Windows, una vez que ingrese a este enlace obtendrá más.

Comunicación entre el modo de usuario y el modo de kernel

Sangeen
fuente
6

Los anillos de CPU son la distinción más clara

En el modo protegido x86, la CPU siempre está en uno de los 4 anillos. El kernel de Linux solo usa 0 y 3:

  • 0 para kernel
  • 3 para usuarios

Esta es la definición más dura y rápida de kernel vs userland.

Por qué Linux no usa los anillos 1 y 2: anillos de privilegios de la CPU: ¿ Por qué no se usan los anillos 1 y 2 ?

¿Cómo se determina el anillo actual?

El anillo actual se selecciona mediante una combinación de:

  • tabla de descriptor global: una tabla en memoria de entradas GDT, y cada entrada tiene un campo Privlque codifica el anillo.

    La instrucción LGDT establece la dirección en la tabla de descriptores actual.

    Véase también: http://wiki.osdev.org/Global_Descriptor_Table

  • el segmento registra CS, DS, etc., que apuntan al índice de una entrada en el GDT.

    Por ejemplo, CS = 0significa que la primera entrada del GDT está actualmente activa para el código de ejecución.

¿Qué puede hacer cada anillo?

El chip de la CPU está construido físicamente para que:

  • ring 0 puede hacer cualquier cosa

  • el anillo 3 no puede ejecutar varias instrucciones y escribir en varios registros, en particular:

    • no puede cambiar su propio anillo! De lo contrario, podría establecerse en 0 y los anillos serían inútiles.

      En otras palabras, no se puede modificar el descriptor de segmento actual , que determina el anillo actual.

    • no se pueden modificar las tablas de páginas: ¿Cómo funciona la paginación x86?

      En otras palabras, no se puede modificar el registro CR3 y la propia paginación evita la modificación de las tablas de la página.

      Esto evita que un proceso vea la memoria de otros procesos por razones de seguridad / facilidad de programación.

    • no se pueden registrar manejadores de interrupciones. Estos se configuran escribiendo en ubicaciones de memoria, lo que también se evita mediante la paginación.

      Los controladores se ejecutan en el anillo 0 y romperían el modelo de seguridad.

      En otras palabras, no puede utilizar las instrucciones LGDT y LIDT.

    • no puede ejecutar instrucciones IO como iny out, y por tanto tener accesos arbitrarios al hardware.

      De lo contrario, por ejemplo, los permisos de archivo serían inútiles si cualquier programa pudiera leer directamente desde el disco.

      Más precisamente gracias a Michael Petch : en realidad es posible que el sistema operativo permita instrucciones IO en el anillo 3, esto en realidad está controlado por el segmento de estado de la tarea .

      Lo que no es posible es que el anillo 3 se dé permiso para hacerlo si no lo tenía en primer lugar.

      Linux siempre lo rechaza. Consulte también: ¿Por qué Linux no usa el cambio de contexto de hardware a través del TSS?

¿Cómo cambian los programas y los sistemas operativos entre anillos?

  • cuando la CPU está encendida, comienza a ejecutar el programa inicial en el anillo 0 (bueno, pero es una buena aproximación). Puede pensar que este programa inicial es el kernel (pero normalmente es un cargador de arranque que luego llama al kernel aún en el anillo 0 ).

  • cuando un proceso de espacio de usuario quiere que el kernel haga algo por él, como escribir en un archivo, usa una instrucción que genera una interrupción como int 0x80osyscall para señalar al kernel. x86-64 Linux syscall hello world ejemplo:

    .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
    

    compilar y ejecutar:

    as -o hello_world.o hello_world.S
    ld -o hello_world.out hello_world.o
    ./hello_world.out
    

    GitHub aguas arriba .

    Cuando esto sucede, la CPU llama a un controlador de devolución de llamada de interrupción que el núcleo registró en el momento del arranque. Aquí hay un ejemplo concreto de baremetal que registra un controlador y lo usa .

    Este controlador se ejecuta en el anillo 0, que decide si el kernel permitirá esta acción, realizará la acción y reiniciará el programa de usuario en el anillo 3. x86_64

  • cuando execse usa la llamada al sistema (o cuando se inicia/init el kernel ), el kernel prepara los registros y la memoria del nuevo proceso de área de usuario, luego salta al punto de entrada y cambia la CPU al anillo 3

  • Si el programa intenta hacer algo malo como escribir en un registro prohibido o en una dirección de memoria (debido a la paginación), la CPU también llama a algún controlador de devolución de llamada del kernel en el anillo 0.

    Pero dado que el espacio de usuario era malo, el kernel podría matar el proceso esta vez o darle una advertencia con una señal.

  • Cuando el kernel arranca, configura un reloj de hardware con una frecuencia fija, lo que genera interrupciones periódicamente.

    Este reloj de hardware genera interrupciones que ejecutan el anillo 0 y le permiten programar qué procesos de usuario deben despertarse.

    De esta manera, la programación puede ocurrir incluso si los procesos no están realizando ninguna llamada al sistema.

¿Cuál es el punto de tener múltiples anillos?

Hay dos ventajas principales de separar kernel y userland:

  • Es más fácil crear programas porque está más seguro de que uno no interferirá con el otro. Por ejemplo, un proceso de área de usuario no tiene que preocuparse por sobrescribir la memoria de otro programa debido a la paginación, ni por poner hardware en un estado no válido para otro proceso.
  • es más seguro. Por ejemplo, los permisos de archivos y la separación de la memoria podrían evitar que una aplicación de piratería lea sus datos bancarios. Esto supone, por supuesto, que confía en el kernel.

¿Cómo jugar con él?

He creado una configuración básica que debería ser una buena forma de manipular anillos directamente: https://github.com/cirosantilli/x86-bare-metal-examples

Desafortunadamente, no tuve la paciencia para hacer un ejemplo de la zona de usuario, pero fui tan lejos como la configuración de la paginación, por lo que la zona de usuario debería ser factible. Me encantaría ver una solicitud de extracción.

Alternativamente, los módulos del kernel de Linux se ejecutan en el anillo 0, por lo que puede usarlos para probar operaciones privilegiadas, por ejemplo, leer los registros de control: ¿Cómo acceder a los registros de control cr0, cr2, cr3 desde un programa? Obteniendo falla de segmentación

Aquí hay una configuración conveniente de QEMU + Buildroot para probarlo sin matar a su host.

La desventaja de los módulos del kernel es que se están ejecutando otros kthreads y podrían interferir con sus experimentos. Pero, en teoría, puede hacerse cargo de todos los controladores de interrupciones con su módulo del kernel y ser dueño del sistema, ese sería un proyecto interesante en realidad.

Anillos negativos

Si bien no se hace referencia a los anillos negativos en el manual de Intel, en realidad hay modos de CPU que tienen más capacidades que el anillo 0 en sí, por lo que se ajustan bien al nombre de "anillo negativo".

Un ejemplo es el modo de hipervisor utilizado en la virtualización.

Para más detalles, consulte:

BRAZO

En ARM, los anillos se denominan niveles de excepción, pero las ideas principales siguen siendo las mismas.

Existen 4 niveles de excepción en ARMv8, comúnmente usados ​​como:

  • EL0: tierra de usuarios

  • EL1: kernel ("supervisor" en terminología ARM).

    Se ingresa con la svcinstrucción (SuperVisor Call), anteriormente conocida como swi antes del ensamblaje unificado , que es la instrucción utilizada para realizar llamadas al sistema Linux. Ejemplo de Hello World ARMv8:

    hola. S

    .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 aguas arriba .

    Pruébelo con QEMU en 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
    

    Aquí hay un ejemplo concreto de baremetal que registra un controlador SVC y realiza una llamada SVC .

  • EL2: hipervisores , por ejemplo Xen .

    Ingresado con la hvcinstrucción (HyperVisor Call).

    Un hipervisor es para un sistema operativo, lo que un sistema operativo es para el espacio de usuario.

    Por ejemplo, Xen le permite ejecutar varios sistemas operativos, como Linux o Windows, en el mismo sistema al mismo tiempo, y aísla los sistemas operativos entre sí para mayor seguridad y facilidad de depuración, tal como lo hace Linux para los programas de usuario.

    Los hipervisores son una parte clave de la infraestructura de la nube actual: permiten que varios servidores se ejecuten en un solo hardware, manteniendo el uso del hardware siempre cerca del 100% y ahorrando mucho dinero.

    AWS, por ejemplo, usó Xen hasta 2017, cuando su cambio a KVM fue noticia .

  • EL3: otro nivel más. Ejemplo de TODO.

    Ingresado con la smcinstrucción (llamada en modo seguro)

El modelo de referencia de arquitectura ARMv8 DDI 0487C.a - Capítulo D1 - Modelo del programador a nivel de sistema AArch64 - La figura D1-1 ilustra esto de manera hermosa:

ingrese la descripción de la imagen aquí

La situación de ARM cambió un poco con la llegada de ARMv8.1 Virtualization Host Extensions (VHE) . Esta extensión permite que el kernel se ejecute en EL2 de manera eficiente:

ingrese la descripción de la imagen aquí

VHE se creó porque las soluciones de virtualización en el kernel de Linux, como KVM, han ganado terreno sobre Xen (consulte, por ejemplo, el cambio de AWS a KVM mencionado anteriormente), porque la mayoría de los clientes solo necesitan máquinas virtuales de Linux y, como puede imaginar, están todos en una sola proyecto, KVM es más simple y potencialmente más eficiente que Xen. Así que ahora el kernel de Linux del host actúa como hipervisor en esos casos.

Observe cómo ARM, quizás debido al beneficio de la retrospectiva, tiene una mejor convención de nomenclatura para los niveles de privilegios que x86, sin la necesidad de niveles negativos: 0 es el más bajo y 3 el más alto. Los niveles superiores tienden a crearse con más frecuencia que los inferiores.

El EL actual se puede consultar con la MRSinstrucción: ¿cuál es el modo de ejecución / nivel de excepción actual, etc.?

ARM no requiere que estén presentes todos los niveles de excepción para permitir implementaciones que no necesitan la función para ahorrar área de chip. ARMv8 "Niveles de excepción" dice:

Es posible que una implementación no incluya todos los niveles de excepción. Todas las implementaciones deben incluir EL0 y EL1. EL2 y EL3 son opcionales.

QEMU, por ejemplo, tiene como valor predeterminado EL1, pero EL2 y EL3 se pueden habilitar con opciones de línea de comando: qemu-system-aarch64 ingresando el1 al emular el encendido de a53

Fragmentos de código probados en Ubuntu 18.10.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
1
Dado que esta pregunta no es específica de ningún sistema operativo iny outestán disponibles para el timbre 3. El TSS puede apuntar a una tabla de permisos de E / S en la tarea actual que otorga acceso de lectura / escritura a todos o puertos específicos.
Michael Petch
Por supuesto, establece los bits de IOPL en el valor 3, luego el programa del anillo 3 tiene acceso completo al puerto y los permisos TSS IO no se aplican.
Michael Petch
@MichaelPetch gracias, no sabía esto. He actualizado la respuesta.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

Voy a intentarlo en la oscuridad y supongo que estás hablando de Windows. En pocas palabras, el modo kernel tiene acceso completo al hardware, pero el modo de usuario no. Por ejemplo, muchos, si no la mayoría, de los controladores de dispositivos están escritos en modo kernel porque necesitan controlar detalles más finos de su hardware.

Consulte también este wikilibro .

Mark Rushakoff
fuente
2
Esto es importante para usted como programador porque los errores del kernel tienden a causar más estragos de los que está acostumbrado. Una razón para la distinción entre el kernel y el usuario es que el kernel puede monitorear / controlar los recursos críticos del sistema y proteger a cada usuario de los demás. Es un poco simplificado, pero útil, para recordarse a sí mismo que los errores de usuario a menudo son molestos, pero los errores del kernel tienden a hacer caer toda la máquina.
Adam Liss
3

Otras respuestas ya explicaron la diferencia entre el modo de usuario y el kernel. Si realmente desea entrar en detalles, debe obtener una copia de Windows Internals , un excelente libro escrito por Mark Russinovich y David Solomon que describe la arquitectura y los detalles internos de los distintos sistemas operativos de Windows.

Dirk Vollmar
fuente
2

Qué

Básicamente, la diferencia entre los modos kernel y de usuario no depende del sistema operativo y se logra solo restringiendo algunas instrucciones para que se ejecuten solo en modo kernel mediante el diseño del hardware. Todos los demás propósitos, como la protección de la memoria, solo se pueden realizar mediante esa restricción.

Cómo

Significa que el procesador vive en modo kernel o en modo usuario. Usando algunos mecanismos, la arquitectura puede garantizar que siempre que se cambie al modo kernel, el código del sistema operativo se obtenga para su ejecución.

Por qué

Con esta infraestructura de hardware, estos se podrían lograr en sistemas operativos comunes:

  • Proteger a los programas de usuario para que no accedan a toda la memoria, para no permitir que los programas sobrescriban el sistema operativo, por ejemplo,
  • evitar que los programas de usuario realicen instrucciones sensibles como las que cambian los límites del puntero de la memoria de la CPU, para no permitir que los programas rompan sus límites de memoria, por ejemplo.
Ali Asgari
fuente