La mayoría de los sistemas operativos tienen algún método para mostrar la utilización de la CPU. En Windows, se trata del Administrador de Tareas.
El uso de la CPU se representa generalmente como un simple porcentaje del tiempo de la CPU dedicado a tareas no inactivas. Pero esto es una simplificación. En cualquier sistema operativo moderno, la CPU pasa el tiempo en dos modos muy distintos:
- Modo Kernel
En el modo Kernel, el código que se ejecuta 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 está generalmente reservado para las funciones de más bajo nivel y más confiables del sistema operativo. Los fallos en el modo kernel son catastróficos; detendrán todo el PC.
- Modo Usuario
En el modo Usuario, el código que se ejecuta no tiene capacidad para acceder directamente al hardware o referenciar la memoria. El código que se ejecuta en modo usuario debe delegar en las API del sistema para acceder al hardware o a la memoria. Debido a la protección que ofrece este tipo de aislamiento, los fallos en modo usuario son siempre recuperables. La mayor parte del código que se ejecuta en su ordenador lo hace en modo usuario.
Es posible habilitar la visualización del tiempo del Kernel en el Administrador de Tareas, como he hecho en la captura de pantalla anterior. La línea verde es el tiempo total de la CPU; la línea roja es el tiempo del Kernel. El espacio entre los dos es el tiempo de Usuario.
Estos dos modos no son meras etiquetas; son forzados por el hardware de la CPU. Si el código que se ejecuta en el modo de usuario intenta hacer algo fuera de su ámbito -como, por ejemplo, acceder a una instrucción privilegiada de la CPU o modificar la memoria a la que no tiene acceso-, se lanza una excepción que puede ser trapeada. En lugar de que todo el sistema se bloquee, sólo esa aplicación en particular se bloquea. Ese es el valor del modo de usuario.
El hardware de la CPU x86 realmente proporciona cuatro anillos de protección: 0, 1, 2 y 3. Sólo los anillos 0 (Kernel) y 3 (Usuario) se utilizan normalmente.
Si sólo utilizamos dos anillos de aislamiento, no está muy claro dónde deben ir los controladores de dispositivos: el código que nos permite utilizar nuestras tarjetas de vídeo, teclados, ratones, impresoras, etc. ¿Estos controladores se ejecutan en modo Kernel, para obtener el máximo rendimiento, o se ejecutan en modo Usuario, para obtener la máxima estabilidad? Al menos en Windows, la respuesta es que depende. Los controladores de dispositivos pueden ejecutarse en modo usuario o en modo kernel. Hoy en día, la mayoría de los controladores se sitúan en el lado de usuario, con la notable excepción de los controladores de las tarjetas de vídeo, que necesitan un rendimiento total en el modo de núcleo. Pero incluso eso está cambiando; en Windows Vista, los controladores de vídeo están segmentados en secciones de usuario y de núcleo. Quizá por eso los jugadores se quejan de que Vista es un 10 por ciento más lento en los juegos.
La frontera exacta entre estos modos sigue sin estar clara. ¿Qué código debe ejecutarse en el modo Usuario? Qué código debe ejecutarse en modo Kernel? O tal vez simplemente redefinamos el suelo como el sótano–el auge de la virtualización impulsó la creación de un nuevo anillo por debajo de todos los demás, el anillo -1, que ahora conocemos como virtualización de hardware x86.
El modo Usuario es claramente un bien público neto, pero tiene un coste. La transición entre el modo Usuario y el Kernel es cara. Realmente caro. Por eso el software que lanza excepciones es lento, por ejemplo. Las excepciones implican transiciones en modo kernel. Por supuesto, ahora tenemos tanto rendimiento que rara vez tenemos que preocuparnos por el rendimiento de la transición, pero cuando necesitas el máximo rendimiento, definitivamente empiezas a preocuparte por estas cosas.
Probablemente el ejemplo más público de redibujar la línea usuario/núcleo está en los servidores web. El IIS 6 de Microsoft trasladó una parte considerable de su funcionalidad principal al modo Kernel, sobre todo después de que un servidor web de código abierto en particular aprovechara el modo Kernel para crear una enorme victoria de referencia en la industria. En mi opinión, fue una guerra sin sentido, ya que las optimizaciones del núcleo (en ambos campos) sólo se aplican al contenido HTML estático. Pero así son todas las guerras, de benchmarks o de otro tipo.
La estricta segregación del código de la CPU entre el modo Usuario y el Kernel es completamente transparente para la mayoría de nosotros, pero es literalmente la diferencia entre un ordenador que se bloquea todo el tiempo y un ordenador que se bloquea catastróficamente todo el tiempo. Esto es lo que a los programadores que escriben código de forma extravagante nos gusta llamar «progreso». Así que en nombre de todos los programadores de todo el mundo, me gustaría dar las gracias a User mode. Eres genial!