7. Operación del sistema operativo
Mecanismos de protección del hardware y de control de la propia ejecución en un sistema operativo, desde las interrupciones y el modo dual hasta la virtualización.
Dado que el sistema operativo y los procesos de usuarios comparten los recursos del sistema informático, necesitamos estar seguros de que un error en un programa solo afecte al proceso que lo ejecuta —por ejemplo, que un proceso no puede modificar la memoria de otro proceso o la del núcleo del sistema—. Por eso es necesario establecer mecanismos de protección frente a los errores en los programas que se ejecutan en el sistema.
Software dirigido mediante interrupciones
Sección titulada «Software dirigido mediante interrupciones»El núcleo del sistemas operativo es un programa de ordenador, similar a cualquier otro, con la salvedad de que no puede apoyarse en ninguna librería estándar ni de sistema ni en ningún otro programa, por lo que cualquier funcionalidad que necesite la debe implementarla el mismo. Además, el diseño de un núcleo de sistema operativo suele seguir un paradigma denominado programación dirigida por interrupciones. Esto significa que el núcleo del sistema operativo no se ejecuta de forma continua en la CPU, sino que permanece inactivo en la memoria hasta que ocurre un suceso que requiere su atención. Esos sucesos se indican mediante interrupciones o excepciones, que son señales que envían los dispositivos de E/S o la CPU para avisar de que algo ha ocurrido y requiere atención.
Algunos ejemplos de sucesos que requieren la atención del sistema operativo son los siguientes:
-
Cuando un proceso comete un error —como una división por cero o un acceso a memoria no válido— lo que se genera es una excepción en la CPU. Esta excepción despierta al núcleo del sistema operativo para que haga lo que sea más conveniente.
-
Cuando un proceso necesita un servicio lo que hace es lanzar una llamada al sistema, que no es más que ejecutar una instrucción que lanza una excepción en la CPU. Esta excepción despierta al núcleo del sistema operativo para que atienda la petición.
-
Cuando los dispositivos de E/S requieren la atención del sistema operativo —por ejemplo, porque se ha completado una transferencia de datos— envían una señal que genera una interrupción en la CPU, lo que despierta al núcleo del sistema operativo.
Esto funciona así porque el sistema operativo configura la CPU durante el arranque para que si ocurre cualquier interrupción o excepción la ejecución salte a rutinas en el código del núcleo, con el objeto de darles el tratamiento adecuado. Si ningún proceso realiza una acción ilegal o pide un servicio, ni ningún dispositivo de E/S pide la atención del sistema, el sistema operativo permanece inactivo esperando a que ocurra algún suceso.
Operación en modo dual
Sección titulada «Operación en modo dual»Para proteger el sistema de programas con errores es necesario poder distinguir entre la ejecución del código del sistema operativo y del código de los programas de usuario, de tal forma que el código de los programas de usuario esté más limitado en lo que puede hacer que el del sistema operativo.
El método que utilizan la mayor parte de los sistemas operativos consiste en utilizar algún tipo de soporte en la CPU que permita diferenciar entre varios modos de ejecución y restringir la utilización de las instrucciones peligrosas —llamadas instrucciones privilegiadas— para que solo puedan ser utilizadas en el modo en el que se ejecuta el código del sistema operativo.
Modos de operación
Sección titulada «Modos de operación»Así que como mínimo son necesarios dos modos de operación diferentes:
-
En el modo usuario se ejecuta el código de los procesos de los usuarios. Si se hace un intento de ejecutar una instrucción privilegiada en este modo, el hardware la trata como ilegal y genera una excepción que es interceptada por el sistema operativo, en lugar de ejecutar la instrucción.
-
En el modo privilegiado —también denominado modo supervisor, modo del sistema o modo kernel— se ejecuta el código de las tareas del sistema operativo. La CPU es la encargada de garantizar que las instrucciones privilegiadas solo pueden ser ejecutadas en este modo.
El modo actual de operación puede venir indicado por un bit de modo en alguno de los registros de configuración de la CPU, de tal forma que, si por ejemplo, el bit está a 0, la CPU considera que el código en ejecución opera en modo privilegiado, mientras que si el bit está a 1, el código en ejecución opera en modo usuario.
Comúnmente en el grupo de las instrucciones privilegiadas se suelen incluir:
- La instrucción para conmutar al modo usuario desde el modo privilegiado.
- Las instrucciones para acceder a dispositivos de E/S.
- Las instrucciones necesarias para la gestión de las interrupciones. Por ejemplo, para desactivarlas —evitando que se lancen— activarlas y configurarlas.
Extra Niveles de privilegio en procesadores x86
Sección titulada « Niveles de privilegio en procesadores x86»Aunque para operar en modo dual solo se necesita que la CPU admita los dos modos descritos, existen procesadores que soportan modos adicionales con la idea de ofrecer mayor control sobre el nivel de privilegio en el que se ejecuta cada componente del sistema.
Es el caso de la arquitectura Intel x86, que soporta 4 modos de operación1. El modo 0 es para el software más confiable y el que necesita más privilegios, que generalmente es el núcleo del sistema operativo. Mientras que el modo 3 se utiliza para el software menos confiable y que necesita más supervisión, que normalmente son los procesos de usuario. La idea detrás de tener los modos 1 y 2 es usarlos para controladores de dispositivo o procesos que dan servicio al resto del sistema. Así estos componentes pueden tener mayores privilegios que los procesos de usuario —por ejemplo, los controladores de dispositivo necesitan acceso directo al hardware— pero al mismo tiempo son supervisados y no pueden afectar al núcleo, que se ejecuta en el modo 0.
Sin embargo, los sistemas operativos con mayor cuota de mercado —incluyendo Microsoft Windows, macOS, Linux y Android— solo utilizan los modos 0 y 3. Los motivos son que los desarrolladores de sistemas no encuentran realmente ninguna ventaja en utilizar más modos y que complica portar el sistema operativo a procesadores donde solo se soporten dos.
Por otro lado, los procesadores x86 recientes vienen con instrucciones específicas para facilitar la ejecución de máquinas virtuales. Para ello incorporan un modo -1, de forma que el núcleo del sistema operativo virtualizado se ejecuta en el modo 0 mientras es supervisado desde el modo -1 por el núcleo del sistema operativo anfitrión.
Extra Modo de operación dual vs. modo real / protegido en x86
Sección titulada « Modo de operación dual vs. modo real / protegido en x86»En los procesadores x86 es importante no confundir los modos real y protegido con el modo dual y los niveles de privilegio de los que estamos hablando. Por compatibilidad hacia atrás, los procesadores x86 se inician en modo real, donde se comportan como una CPU Intel. En este modo, por ejemplo, solo tienen acceso al primer mega de memoria RAM —ya que los procesadores Intel solo tenían 20 bits para direcciones de memoria—.
Cuando un sistema operativo moderno arranca, lo primero que hace es iniciar el modo protegido, en el que se activan todas las características de la CPU. Entre otras, el direccionamiento de 32 o 64 bits —según el procesador que sea— y la posibilidad de usar los 4 niveles de privilegio, de los que hemos hablado, para que el núcleo pueda supervisar al resto de componentes.
Ejecución de instrucciones
Sección titulada «Ejecución de instrucciones»A continuación podemos ver el ciclo de vida de la ejecución de instrucciones en un sistema con modo dual de operación:
-
Inicialmente, al arrancar el ordenador, la CPU se inicia en el modo privilegiado —es decir, en nuestro ejemplo, con el bit de modo a 0—. En este modo se carga el núcleo del sistema operativo e inicia su ejecución.
-
El núcleo del sistema operativo debe cambiar al modo usuario —poniendo el bit de modo a 1— antes de ceder la CPU a un proceso de usuario. Esto ocurre cuando es necesario que un proceso de usuario continúe o inicie su ejecución (ver el apartado «El asignador»). Así se asegura que el código de los procesos de usuario siempre se ejecuten en modo usuario, con menos privilegios.
-
La CPU conmuta a modo privilegiado siempre que ocurre una interrupción o una excepción —poniendo el bit de modo a 0— antes de comenzar el código del sistema operativo que se encargará de tratarlas. Por ejemplo, cuando un proceso de usuario comete un error o solicita un servicio mediante una llamada al sistema.
Esto último es muy importante. Como ya hemos comentado, los sistemas operativos están controlados mediante interrupciones. Al activarse el modo privilegiado cada vez que ocurre una interrupción, podemos estar seguros de que las tareas del sistema operativo se ejecutarán siempre en modo privilegiado.
Cuando se dispone de la protección del modo dual, el hardware se encarga de detectar los errores de ejecución y de notificarlo al sistema operativo mediante excepciones, siendo responsabilidad de este último realizar un tratamiento adecuado de los mismos. Por lo general, si un programa falla de alguna forma —como por ejemplo, intentando utilizar una instrucción ilegal o de acceder a una zona de memoria inválida— el sistema operativo lo termina inmediatamente.
Protección de la memoria
Sección titulada «Protección de la memoria»La memoria principal debe acomodar tanto el sistema operativo como a los diferentes procesos de los usuarios. Por eso, como se puede ver en el lado memoria física de la siguiente figura, la memoria normalmente se divide en dos partes o espacios:
-
La primera parte es el espacio del núcleo. Sirve para albergar el núcleo del sistema operativo.
El sistema operativo puede estar localizado tanto en la parte baja como en la parte alta de la memoria. El factor determinante es dónde define la arquitectura del procesador la ubicación de la dirección de memoria a la que salta la CPU cuando ocurre una interrupción o la dirección del vector de interrupciones —que es una tabla en la memoria donde se definen las direcciones a las que saltará la CPU en caso de que ocurra una interrupción o una excepción—.
-
La segunda parte es el espacio de usuario y alberga los procesos de usuario.
En los sistemas operativos modernos, los procesos no tienen acceso libre a toda memoria física, con el objeto de proteger a los procesos en ejecución y al sistema operativo de posibles errores en cualquiera de ellos:
-
El sistema operativo proporciona a cada proceso una «vista» privada de la memoria RAM; de tal forma que el espacio de usuario que ve cada proceso es similar al que vería cada uno de ellos si se estuviera ejecutando en solitario (ver la figura anterior).
-
A esa «vista» que tiene cada proceso de la memoria es a lo que se denomina espacio de direcciones virtual del proceso. Está formada por el conjunto de todas las direcciones que puede generar la CPU para un proceso dado. Por ejemplo, en una CPU de 32 bits el espacio de direcciones virtual tiene 4 GiB, desde la dirección 0x00000000 a 0xFFFFFFFF.
-
En los accesos a la memoria principal durante la ejecución del proceso, estas direcciones virtuales son convertidas por la CPU en direcciones físicas, antes de ser enviadas a la memoria principal. Por tanto las direcciones físicas son las direcciones reales de la memoria memoria. Mientras que el espacio de direcciones físico es el conjunto de direcciones físicas que corresponden a todas las direcciones virtuales de un espacio de direcciones virtual dado.
La conversión de una dirección virtual en una física, la realiza en tiempo de ejecución un componente de la CPU denominado MMU (Memory-Management Unit).
Las ventajas de usar esta técnica, desde el punto de vista de la protección de la memoria son:
-
Permite marcar modos de acceso autorizados en las diferentes regiones de la memoria —como por ejemplo lectura, escritura y ejecución— evitando que el código ejecutado en modo usuario tenga acceso a zonas a las que no debería tenerlo. El acceso a la memoria en un modo no autorizado se considera una instrucción privilegiada, por lo que ese tipo de acceso desde el modo usuario siempre genera una excepción. Por ejemplo, si se intenta ejecutar instrucciones en una zona de memoria no marcada con el permiso de ejecución.
-
Permite el aislamiento de los procesos, creando para cada uno la ilusión de que toda la memoria es para él y evitando que un proceso pueda «ver» a la memoria de otros procesos.
El temporizador
Sección titulada «El temporizador»El temporizador se utiliza para asegurar que ningún proceso acapara la CPU indefinidamente. Por ejemplo, para evitar que un programa mal desarrollado que entra en un bucle infinito, afecte el funcionamiento del sistema.
El temporizador se configura por el sistema operativo durante el arranque del sistema para interrumpir a la CPU a intervalos regulares. Así, cuando el temporizador interrumpe, el control se transfiere automáticamente al núcleo del sistema. Entonces este puede:
- Conceder más tiempo al proceso en ejecución.
- Detenerlo y darle más tiempo de CPU en el futuro.
- Tratar la interrupción como un error y terminar el programa.
Obviamente, las instrucciones que pueden modificar el contenido del temporizador son instrucciones privilegiadas.
Máquinas virtuales
Sección titulada «Máquinas virtuales»Utilizando las técnicas comentadas anteriormente, el sistema operativo crea a los procesos la ilusión de que se ejecutan en su propio procesador y memoria principal, aunque realmente los estén compartiendo con otros procesos. Un proceso normal siempre sabe que hay un sistema operativo que lo supervisa, porque no puede acceder directamente al hardware, sino que debe solicitar los distintos recursos a través de las llamadas al sistema. Si intentase ejecutar una instrucción privilegiada, el sistema operativo interceptaría el intento y lo trataría como un error del programa, terminando su ejecución.
Sin embargo, en algunos casos puede interesar ejecutar un sistema operativo completo —con su propio núcleo— dentro de otro sistema operativo, de forma que el núcleo del sistema operativo virtualizado acceda a los recursos a través de una interfaz de hardware virtual, en lugar de hacerlo mediante llamadas al sistema operativo anfitrión. Por ejemplo, el núcleo del sistema operativo virtualizado, en lugar de solicitar al sistema operativo anfitrión que lea cierto bloque de datos del disco duro, ejecuta directamente las instrucciones de E/S necesarias para pedir a la controladora de disco que lea el bloque que le interesa y lo deposite en la memoria.
Obviamente, el sistema operativo virtualizado no tiene acceso a la controladora real, sino que en el sistema anfitrión hay un componente de software que ejecuta una simulación de algún modelo de controladora de disco al que llegan sus peticiones. Como las instrucciones de E/S necesarias para acceder al hardware son instrucciones privilegiadas, el sistema operativo anfitrión las intercepta —gracias al apoyo del modo dual—. Esta es la diferencia clave con un proceso normal: en lugar de interpretar la situación como un defecto del programa y terminarlo, el sistema operativo anfitrión traslada la operación solicitada a los componentes de hardware virtual y continúa la ejecución del código virtualizado en la siguiente instrucción, como si nunca hubiera sido interrumpido. El resultado es que el sistema operativo virtualizado tiene la ilusión de que se ejecuta solo en una máquina vacía, con cierto hardware al que puede acceder directamente, aunque este hardware realmente está siendo simulado.
Los componentes de hardware virtual simulan el comportamiento de modelos concretos de dispositivos hardware reales, implementando la funcionalidad del hardware simulado con ayuda de otros componentes del sistema operativo anfitrión. Por ejemplo, una tarjeta de sonido virtualizada, en última instancia usará los servicios del sistema operativo anfitrión para reproducir o grabar sonido usando el dispositivo real, mientras que el controlador de disco virtualizado probablemente simulará las operaciones de lectura y escritura trasladándolas a un archivo del sistema de archivos real que hará de imagen del disco duro virtual.
Este entorno de ejecución es lo que se conoce como máquina virtual. El software responsable de crearlo y gestionarlo se denomina hipervisor o monitor de máquinas virtuales y es quien implementa los componentes de hardware virtual y recibe del sistema operativo anfitrión los intentos de ejecutar instrucciones privilegiadas por parte del código que se ejecuta dentro de la máquina virtual. Por tanto, la operación en modo dual y las técnicas comentadas anteriormente en este tema son fundamentales para implementar el soporte de máquinas virtuales en los sistemas operativos modernos. Al mismo tiempo, los procesadores modernos incorporan instrucciones específicas para facilitar la ejecución de máquinas virtuales, como por ejemplo las extensiones Intel VT-x y AMD-V de los procesadores.
Arranque del sistema
Sección titulada «Arranque del sistema»Desde el momento en que el ordenador se pone en marcha hasta que el sistema operativo inicia su ejecución se realizan una serie de operaciones. Estos son los pasos más comunes en el arranque de un sistema:
-
Llega a la CPU una señal de RESET motivada por el encendido del sistema o por un reinicio.
-
La CPU inicializa el contador de programa a una dirección predefinida de la memoria. En esa dirección está el bootstrap inicial.
El bootstrap es el programa que se encarga en primera instancia del arranque. Debe estar almacenado en una memoria no volátil —ROM o Flash— porque la RAM está en un estado indeterminado en el momento del arranque.
En los PC el bootstrap forma parte del firmware2 —sea BIOS o UEFI— de las placas madres.
Tareas del bootstrap
Sección titulada «Tareas del bootstrap»El bootstrap debe realizar diversas tareas:
-
Diagnóstico de la máquina —o Power-on Self-Test (POST)—. El bootstrap se detiene en este punto si el sistema no supera el diagnóstico.
-
Inicializar el sistema. Por ejemplo, configurar los registros de la CPU, inicializar los dispositivos y contenido de la memoria, etc.
-
Iniciar el sistema operativo.
Al iniciar el sistema operativo hay que considerar que puede estar en diferentes ubicaciones según el tipo de dispositivo:
-
En consolas de videojuegos, móviles y otros dispositivos empotrados se almacena el sistema operativo en alguna forma de memoria de solo lectura —ROM o Flash—. Como la ejecución en esas memorias es más lenta que en la RAM, muchas veces el bootstrap suele copiar el sistema a la RAM durante el arranque, antes de iniciarlo.
-
En el resto de sistemas —equipos de escritorio, servidores y otros de propósito general— el sistema generalmente se almacena en disco.
Cuando el sistema se almacena en disco, el bootstrap necesita localizar el gestor de arranque, y para ello existen dos estrategias generales:
-
Leer el gestor de arranque de una posición fija y predefinida del disco —generalmente el primer bloque—, copiarlo en memoria y ejecutarlo. Esta es una estrategia simple porque no requiere que el bootstrap entienda el sistema de archivos, pero limita mucho el tamaño del código que puede cargar, ya que debe caber en ese único bloque —que generalmente tiene solo 512 bytes—. Por eso es común que ese bloque no contenga el gestor de arranque completo, sino solo el código necesario para localizar y cargar el resto del gestor desde otra parte del disco. Por ejemplo, los PC con BIOS y particiones MBR3 leen de esta forma el primer bloque del disco, llamado también MBR.
-
Que el propio bootstrap sepa leer el sistema de archivos de las particiones del disco, para localizar directamente los archivos del gestor de arranque completo. Por ejemplo, los PC con UEFI y particiones GPT funcionan así. La UEFI entiende el sistema de archivos de la partición de arranque y localiza en ella los archivos del gestor de arranque.
En cualquier caso, una vez el bootstrap localiza y ejecuta el gestor de arranque completo, es este quien sabe cómo iniciar el sistema operativo: explora el sistema de archivos en busca del núcleo del sistema, lo carga e inicia su ejecución.
A partir de este punto, cada sistema operativo prosigue de forma diferente. A modo de ejemplo, veremos cómo prosigue el arranque en sistemas UNIX en modo texto —es decir, autenticando al usuario en una terminal en lugar de mediante un gestor de sesiones gráfico, como hacen la mayoría de los sistemas de escritorio actuales—.
Arranque de sistemas UNIX
Sección titulada «Arranque de sistemas UNIX»Al iniciarse el núcleo del sistema, este realiza una serie de tareas:
-
Configura el sistema para crear un entorno adecuado para la ejecución de los procesos: configuración de interrupciones, configuración de los modos de ejecución —privilegiado y usuario— y de la gestión de la memoria; inicialización de dispositivos y controladores; montaje del sistema de archivos raíz; creación del proceso inactivo —que se ejecutará cuando no haya nada que hacer— etc.
-
Crea el proceso init —que por ser el primero tiene PID 1— a partir de la carga del programa
initalmacenado en el sistema de archivos raíz. En los sistemas GNU/Linux actuales el proceso init más común es . -
El planificador de la CPU toma el control de la gestión de la CPU y el núcleo se queda dormido. Puesto que la función del planificador es asignar procesos a la CPU y solo hay uno, el proceso init, este es escogido y comienza su ejecución.
-
El proceso init lanza los scripts encargados de configurar los servicios —también llamados demonios— del sistema. Por ejemplo, para el registro de eventos del sistema, gestión de dispositivos, particiones, impresoras, entre otros.
El proceso init también configura el entorno de usuario. Configura las terminales del sistema e inicia, para cada una, un proceso getty —de get tty—, que espera a que el usuario introduzca su nombre y entonces se sustituye a sí mismo por el proceso login, encargado de solicitar la contraseña y completar la autenticación. Estos procesos son monitorizados por init, que los reinicia si terminan. Aunque, por lo general, un sistema de escritorio tiene una única pareja de teclado y monitor y, por lo tanto, una única terminal real; el sistema puede estar configurado para crear varios terminales virtuales entre los que el usuario puede conmutar usando las combinaciones de teclas adecuadas.
Los procesos login se encargan de autenticar a los usuarios y de iniciar y configurar su sesión:
-
Solicitan al usuario su contraseña —el nombre de usuario lo reciben de getty como un argumento—.
-
Autentican al usuario comprobando las credenciales proporcionadas por el mismo.
-
Si la autenticación es positiva, el proceso login cambia su identidad actual —generalmente de root o administrador del sistema— por la del usuario autenticado, configura la sesión y sustituye su programa actual por el del intérprete de comandos que tiene configurado ese usuario (ver el apartado «Ejemplos de operaciones con procesos»).
El intérprete de comandos completa la configuración del entorno basándose en sus archivos de configuración, muestra el prompt4 y queda a la espera del primer comando del usuario.
Notas al pie
Sección titulada «Notas al pie»-
Wikipedia, s.v. «Anillo (seguridad», última modificación el 9 de enero de 2025. ↩
-
El término firmware viene de que por sus características se sitúa en algún lugar entre el hardware y el software. Concretamente es un componente de software instalado en un dispositivo hardware para encargarse de su control a bajo nivel. ↩
-
MBR son las siglas de Master Boot Record o registro de arranque. También se llama así al propio bloque del disco donde se aloja. ↩
-
El prompt es un texto que muestra el intérprete de comandos para indicar que está listo para recibir órdenes del usuario. Por ejemplo, en algunos sistemas el prompt por defecto es el nombre del usuario seguido del símbolo
$y un espacio. ↩