Cómo funciona el gestor de arranque de Linux y los procesos de arranque e inicio en Linux


gestor de arranque linux

¿Alguna vez se ha preguntado qué se necesita para que su sistema esté listo para ejecutar aplicaciones?. Bueno, en este articulo le explicaremos lo que está pasando bajo el capó.

Comprender los procesos de arranque y de inicio de Linux es importante para poder configurar Linux y resolver los problemas de inicio. Este artículo presenta una visión general de la secuencia de arranque utilizando el gestor de arranque GRUB2 y la secuencia de arranque tal y como se realiza con el sistema de inicialización systemd.

En realidad, hay dos secuencias de eventos que son necesarios para arrancar un ordenador Linux y hacerlo utilizable: arranque e inicio. La secuencia de arranque se inicia cuando se enciende el ordenador y se completa cuando se inicializa el kernel, y despues de que se ejecuta systemd. El proceso de arranque toma el relevo y finaliza la tarea de poner el ordenador Linux en un estado operativo.

En general, el proceso de arranque e inicio de Linux es bastante sencillo de entender. Consta de los siguientes pasos que se describirán con más detalle en las siguientes secciones.

  • BIOS POST
  • Cargador de arranque (GRUB2)
  • Inicialización del núcleo(Kernel)
  • Iniciar systemd, el padre de todos los procesos.
Tenga en cuenta que este artículo cubre GRUB2 y systemd porque son el actual gestor de arranque y software de inicialización para la mayoría de las distribuciones principales. Otras opciones de software se han utilizado históricamente y todavía se encuentran en algunas distribuciones.

El proceso de arranque

El proceso de arranque puede iniciarse de una de las dos maneras siguientes. En primer lugar, si la alimentación está desactivada, al encenderla se iniciará el proceso de arranque. Si el equipo ya está ejecutando un usuario local, incluyendo root o un usuario no privilegiado, el usuario puede iniciar la secuencia de arranque de forma programática utilizando la interfaz gráfica o la línea de comandos para iniciar un reinicio. Un reinicio hará primero un apagado y luego reiniciará el equipo.

BIOS POST

El primer paso del proceso de arranque de Linux realmente no tiene nada que ver con Linux. Esta es la parte del hardware que se encarga del proceso de arranque y es la misma para cualquier sistema operativo. Cuando la alimentación se aplica por primera vez al ordenador, se ejecuta el POST (Power On Self Test) que forma parte de la BIOS (Basic I/O System).

Cuando IBM diseñó el primer PC en 1981, la BIOS fue diseñada para inicializar los componentes de hardware. POST es la parte de la BIOS cuya tarea es asegurar que el hardware de la computadora funcione correctamente. Si el POST falla, el ordenador puede no ser utilizable, por lo que el proceso de arranque no continúa.

BIOS POST comprueba el funcionamiento básico del hardware y luego emite una interrupción de BIOS, INT 13H, que localiza los sectores de arranque en cualquier dispositivo de arranque conectado. El primer sector de arranque encuentra que contiene un registro de arranque válido cargado en la RAM y el control se transfiere al código que se cargó desde el sector de arranque.

El sector de arranque es realmente la primera etapa del gestor de arranque. Hay tres cargadores de arranque utilizados por la mayoría de las distribuciones de Linux, GRUB, GRUB2 y LILO. GRUB2 es el más nuevo y se utiliza con mucha más frecuencia hoy en día que las otras opciones anteriores.

GRUB2

 

GRUB2 significa “GRand Unified Bootloader, versión 2” y ahora es el principal gestor de arranque para la mayoría de las distribuciones de Linux. GRUB2 es el programa que hace que el ordenador sea lo suficientemente inteligente para encontrar el núcleo del sistema operativo y cargarlo en la memoria. Debido a que es más fácil escribir y decir GRUB que GRUB2, nosotros podemos usar el término GRUB en este documento, pero enrealidad se referiré a GRUB2 a menos que se especifique lo contrario.

GRUB ha sido diseñado para ser compatible con la especificación de arranque múltiple que permite a GRUB arrancar muchas versiones de Linux y otros sistemas operativos libres; también puede cargar en cadena el registro de arranque de sistemas operativos propietarios.

GRUB también puede permitir que el usuario elija arrancar desde varios núcleos diferentes para cualquier distribución de Linux. Esto permite la capacidad de arrancar con una versión anterior del núcleo si una versión actualizada falla de alguna manera o es incompatible con un software importante. GRUB puede ser configurado usando el archivo /boot/grub/grub.conf.

GRUB1 es ahora considerado como legado y ha sido reemplazado en la mayoría de las distribuciones modernas con GRUB2, que es una reescritura de GRUB1. Distros basados en Red Hat actualizados a GRUB2 alrededor de Fedora 15 y CentOS/RHEL 7. GRUB2 proporciona la misma funcionalidad de arranque que GRUB1, pero GRUB2 es también un entorno pre-OS basado en comandos de tipo mainframe y permite más flexibilidad durante la fase previa al arranque. GRUB2 está configurado con /boot/grub2/grub.cfg.

La función principal de GRUB es cargar el kernel de Linux en la memoria y ejecutarlo. Ambas versiones de GRUB funcionan esencialmente de la misma manera y tienen las mismas tres etapas, pero usaremos el termino GRUB2 para esta discusión sobre cómo GRUB hace su trabajo. La configuración de GRUB o GRUB2 y el uso de los comandos de GRUB2 están fuera del alcance de este artículo.

Aunque GRUB2 no utiliza oficialmente la notación de etapa para las tres etapas de GRUB2, es conveniente referirse a ellas de esa manera, así lo haremos en este artículo.

 

Etapa 1

Como se menciona en la sección BIOS POST, al final de POST, la BIOS busca en los discos adjuntos un registro de arranque, normalmente ubicado en el Registro de arranque maestro (MBR), carga el primero que encuentra en la memoria y luego inicia la ejecución del registro de arranque. El código de arranque, es decir, GRUB2 etapa 1, es muy pequeño porque debe encajar en el primer sector de 512 bytes del disco duro junto con la tabla de particiones. La cantidad total de espacio asignado para el código de arranque real en un MBR genérico clásico es de 446 bytes. El archivo de 446 bytes para la etapa 1 se llama boot.img y no contiene la tabla de particiones que se añade al registro de arranque por separado.

Debido a que el registro de arranque debe ser tan pequeño, tampoco es muy inteligente y no entiende las estructuras del sistema de archivos. Por lo tanto, el único propósito de la etapa 1 es localizar y cargar la etapa 1.5. Para lograr esto, la etapa 1.5 de GRUB debe estar ubicada en el espacio entre el propio registro de arranque y la primera partición de la unidad. Después de cargar la etapa 1.5 de GRUB en la RAM, la etapa 1 convierte el control en la etapa 1.5.

Etapa 1.5

Como se mencionó anteriormente, la etapa 1.5 de GRUB debe estar ubicada en el espacio entre el propio registro de arranque y la primera partición de la unidad de disco. Este espacio no se ha utilizado históricamente por razones técnicas. La primera partición en el disco duro comienza en el sector 63 y con el MBR en el sector 0, que deja 62 sectores de 512 bytes -31.744 bytes- en los que almacenar el archivo core.img que es la etapa 1.5 de GRUB. El archivo core.img es de 25.389 bytes, por lo que hay mucho espacio disponible entre el MBR y la primera partición de disco en la que se puede almacenar.

Debido a la mayor cantidad de código que se puede acomodar para la etapa 1.5, puede tener suficiente código para contener algunos controladores de sistemas de archivos comunes, como el EXT estándar y otros sistemas de archivos Linux, FAT y NTFS. El core.img de GRUB2 es mucho más complejo y capaz que el antiguo stage 1.5 de GRUB1. Esto significa que la etapa 2 de GRUB2 puede estar ubicada en un sistema de ficheros EXT estándar pero no en un volumen lógico. Así que la ubicación estándar para los ficheros de la etapa 2 está en el sistema de ficheros /boot, específicamente en /boot/grub2.

Tenga en cuenta que el directorio /boot debe estar ubicado en un sistema de ficheros soportado por GRUB. No todos los sistemas de archivos lo son. La función de la etapa 1.5 es iniciar la ejecución con los controladores de sistema de ficheros necesarios para localizar los ficheros de la etapa 2 en el sistema de ficheros /boot y cargar los controladores necesarios.

Etapa 2

Todos los ficheros de la etapa 2 de GRUB se encuentran en el directorio /boot/grub2 y en varios subdirectorios. GRUB2 no tiene un archivo de imagen como las etapas 1 y 2. En su lugar, consiste principalmente en módulos del núcleo en tiempo de ejecución que se cargan según sea necesario desde el directorio /boot/grub2/i386-pc.

La función de GRUB2 etapa 2 es localizar y cargar un kernel de Linux en la RAM y convertir el control del ordenador en el kernel. El núcleo y sus archivos asociados se encuentran en el directorio /boot. Los archivos del kernel son identificables ya que todos tienen nombre empezando por vmlinuz. Puede listar el contenido del directorio /boot para ver los kernels instalados actualmente en su sistema.

GRUB2, al igual que GRUB1, soporta el arranque desde una las selecciónes de los kernels de Linux. El gestor de paquetes de Red Hat, DNF, soporta el mantenimiento de múltiples versiones del kernel para que, si se produce un problema con el más reciente, se pueda iniciar una versión más antigua del kernel. De forma predeterminada, GRUB proporciona un menú previo al arranque de los núcleos instalados, incluyendo una opción de rescate y, si está configurado, una opción de recuperación.

La etapa 2 de GRUB2 carga el kernel seleccionado en la memoria y convierte el control del ordenador en el kernel.

 

Núcleo/Kernel

Todos los núcleos están en un formato autoextraíble y comprimido para ahorrar espacio. Los núcleos se encuentran en el directorio /boot, junto con una imagen inicial del disco RAM y mapas de dispositivos de los discos duros.

Después de que el kernel seleccionado se carga en la memoria y comienza a ejecutarse, primero debe extraerse de la versión comprimida del archivo antes de poder realizar cualquier trabajo útil. Una vez que el kernel se ha extraído a sí mismo, carga systemd, que es el reemplazo del antiguo programa init de SysV, y le da el control.

Este es el final del proceso de arranque. En este punto, el kernel y systemd de Linux se están ejecutando, pero no pueden realizar ninguna tarea productiva para el usuario final porque no se está ejecutando nada más.

El proceso de inicio

El proceso de inicio sigue al proceso de arranque y lleva al ordenador Linux a un estado operativo en el que puede utilizarse para el trabajo productivo.

systemd

systemd es la madre de todos los procesos y es responsable de llevar el host Linux a un estado en el que se pueda realizar un trabajo productivo. Algunas de sus funciones, que son mucho más extensas que el antiguo programa init, son gestionar muchos aspectos de un host Linux en ejecución, incluyendo el montaje de sistemas de ficheros, y el inicio y la gestión de los servicios de sistema necesarios para disponer de un host Linux productivo. Cualquiera de las tareas de systemd que no estén relacionadas con la secuencia de inicio están fuera del alcance de este artículo.

Primero, systemd monta los sistemas de ficheros tal y como los define /etc/fstab, incluyendo cualquier fichero swap o partición. En este punto, puede acceder a los ficheros de configuración ubicados en /etc, incluyendo los suyos propios. Utiliza su archivo de configuración, /etc/systemd/system/default.target, para determinar qué estado o destino, en el que debe arrancar el host. El archivo default.target es sólo un enlace simbólico al archivo de destino real. En el caso de una estación de trabajo de escritorio, éste suele ser el graphical.target, que equivale al nivel de ejecución 5 en el antiguo SystemV init. Para un servidor, es más probable que el valor por defecto sea el multi-user.target, que es como el nivel de ejecución 3 en SystemV. El objetivo de emergencia es similar al modo de usuario individual.

Tenga en cuenta que los objetivos y servicios son unidades de sistema.

La Tabla 1, a continuación, es una comparación de los objetivos systemd(Targets) con los antiguos niveles de ejecución de inicio de SystemV. Los alias de destino systemd son proporcionados por systemd para la compatibilidad con versiones anteriores. Los alias de destino permiten a los scripts -y a muchos administradores de sistemas como yo- usar comandos SystemV como init 3 para cambiar los niveles de ejecución. Por supuesto, los comandos SystemV se envían a systemd para su interpretación y ejecución.

SystemV Runlevelsystemd targetsystemd alias de destinoDescripción
halt.targetDetiene el sistema sin apagarlo.
0poweroff.targetrunlevel0.targetDetiene el sistema y apaga la alimentación.
Semergency.targetModo de usuario único. No se están ejecutando servicios; los sistemas de archivos no están montados. Este es el nivel más básico de operación con sólo una consola principal de emergencia para que el usuario interactúe con el sistema.
1rescue.targetrunlevel1.targetUn sistema base que incluye el montaje de los sistemas de ficheros con los servicios más básicos en ejecución y un shell de rescate en la consola principal.
2runlevel2.targetMultiusuario, sin NFS pero con todos los demás servicios que no sean GUI en ejecución.
3multi-user.targetrunlevel3.targetTodos los servicios en ejecución excepto la interfaz de línea de comandos (CLI) solamente.
4runlevel4.targetSin usar.
5graphical.targetrunlevel5.targetmultiusuario con una GUI.
6reboot.targetrunlevel6.targetReboot
default.targetEste destino siempre está aliasado con un enlace simbólico a multiusuario.destino o gráfico.destino. systemd siempre utiliza el destino.predeterminado para iniciar el sistema. El objetivo.predeterminado nunca debe ser aliado para detener el objetivo.de.detener, apagar.el.objetivo o reiniciar.el.objetivo.

 

 

Cada target tiene un conjunto de dependencias descritas en su archivo de configuración. systemd inicia las dependencias necesarias. Estas dependencias son los servicios necesarios para ejecutar el host Linux con un nivel específico de funcionalidad. Cuando se cargan y ejecutan todas las dependencias enumeradas en los archivos de configuración de destino, el sistema se ejecuta en ese nivel de destino.

systemd también revisa los directorios de inicio de SystemV para ver si existe algún archivo de inicio allí. Si es así, systemd los usó como archivos de configuración para iniciar los servicios descritos por los archivos. El servicio de red obsoleto es un buen ejemplo de uno de los que todavía utilizan archivos de inicio de SystemV en Fedora.

La figura 1, abajo, se copia directamente de la página de manual de arranque. Muestra la secuencia general de eventos durante el inicio del sistema y los requisitos básicos de pedido para asegurar un inicio exitoso.

Los objetivos sysinit.target y basic.target pueden ser considerados como puntos de comprobación en el proceso de inicio. Aunque systemd tiene como uno de sus objetivos de diseño iniciar servicios de sistema en paralelo, todavía hay ciertos servicios y objetivos funcionales que deben ser iniciados antes de que otros servicios y objetivos puedan ser iniciados. Estos puntos de control no podrán ser superados hasta que se hayan cumplido todos los servicios y objetivos exigidos por dicho punto de control.

De este modo, el objetivo sysinit.target se alcanza cuando se completan todas las unidades de las que depende. Todas esas unidades, montando sistemas de archivos, configurando archivos swap, iniciando udev, configurando la semilla del generador aleatorio, iniciando servicios de bajo nivel, y configurando servicios criptográficos si uno o más sistemas de archivos están encriptados, deben ser completados, pero dentro del sysinit.target esas tareas pueden ser realizadas en paralelo.

El sysinit.target pone en marcha todos los servicios y unidades de bajo nivel necesarios para que el sistema sea marginalmente funcional y que son necesarios para permitir el paso al target básico.

 local-fs-pre.target
                    |
                    v
           (diversos servicios  (varios dispositivos (varios dispositivos  
            de montaje y fsck...)     swap...)      de configuración     (Varios servicios   (varios montajes de 
                    |                  |              de cifrado...)    de bajo nivel: udevd, bajo nivel de API VFS:
                    v                  v                  v             tmpfiles, random     mqueue, configfs,
             local-fs.target      swap.target     cryptsetup.target    seed, sysctl, ...)      debugfs, ...)
                    |                  |                  |                    |                    |
                    \__________________|_________________ | ___________________|____________________/
                                                         \|/
                                                          v
                                                   sysinit.target
                                                          |
                     ____________________________________/|\________________________________________
                    /                  |                  |                    |                    \
                    |                  |                  |                    |                    |
                    v                  v                  |                    v                    v
                (varios             (varios               |                (varios           rescue.service
        temporizadores...)       caminos...)              |               sockets...)               |
                    |                  |                  |                    |                    v
                    v                  v                  |                    v              rescue.target
              timers.target      paths.target             |             sockets.target
                    |                  |                  |                    |
                    v                  \_________________ | ___________________/
                                                         \|/
                                                          v
                                                    basic.target
                                                          |
                     ____________________________________/|                                 emergency.service
                    /                  |                  |                                         |
                    |                  |                  |                                         v
                    v                  v                  v                                 emergency.target
                display-       (varios servicios    (varios servicios 
            manager.service       de sistema           del sistema)
                    |          necesarios para la         |
                    |         interfaz grafica UIs)       v
                    |                  |           multi-user.target
                    |                  |                  |
                    \_________________ | _________________/
                                      \|/
                                       v
                             graphical.target

 

 

Una vez que se cumple el objetivo sysinit.target, systemd inicia el objetivo básico basic-target, iniciando todas las unidades necesarias para cumplirlo. El objetivo básico proporciona alguna funcionalidad adicional al iniciar unidades que son necesarias para el siguiente objetivo. Esto incluye la configuración de cosas como rutas a varios directorios ejecutables, sockets de comunicación y temporizadores.

Finalmente, se pueden inicializar los objetivos a nivel de usuario, multiuser.target o graphical.target. Tenga en cuenta que el objetivo multiusuario debe alcanzarse antes de que se puedan cumplir las dependencias gráficas del objetivo.

Los objetivos subrayados en la Figura 1 son los objetivos habituales de inicio. Cuando se alcanza uno de estos objetivos, la puesta en marcha ha finalizado. Si el destino multiusuario es el predeterminado, debería ver un inicio de sesión en modo texto en la consola. Si graphical.target es el predeterminado, debería ver un inicio de sesión gráfico; la pantalla de inicio de sesión de GUI específica que verá dependerá del administrador de pantalla predeterminado que utilice.

Problemas

Recientemente tuvimos la necesidad de cambiar el kernel de arranque predeterminado en un ordenador Linux que utilizaba GRUB2. Descubrímos que algunos de los comandos no parecían funcionar correctamente para nosotros, o que no los estabamos usando correctamente. Todavía no estamos seguros de cuál fue el caso, y necesitamos investigar más.

El comando grub2-set-default no estableció correctamente el índice predeterminado del kernel para nosotros en el archivo /etc/default/grub de modo que el kernel alternativo deseado no arrancó. Así que cambiamos manualmente /etc/default/grub GRUB_DEFAULT=saved a GRUB_DEFAULT=2 donde 2 es el índice del kernel instalado que quería arrancar. Luego ejecutamos el comando grub2-mkconfig > /boot/grub2/grub.cfg para crear el nuevo archivo de configuración de grub. Este truco funcionó como se esperaba y arrancó con el kernel alternativo.

Conclusiones

GRUB2 y el sistema systemd init son los componentes clave en las fases de arranque e inicio de la mayoría de las distribuciones modernas de Linux. A pesar del hecho de que ha habido controversia en torno a systemd especialmente, estos dos componentes trabajan juntos sin problemas primero para cargar el núcleo y luego para poner en marcha todos los servicios del sistema necesarios para producir un sistema Linux funcional.

Aunque tanto GRUB2 como systemd nos parecen más complejos que sus predecesores, también son fáciles de aprender y gestionar. Las páginas de manual tienen mucha información sobre systemd, y freedesktop.org tiene el conjunto completo de páginas de manual systemd en línea.

Comentar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *