Compilación del kernel de linux 3.16.2

14O, septiembre 2014


Antecedentes

Cuando hablamos de Linux es frecuente que nos referamos a una distribución: Debian, Ubuntu, Red Hat, Fedora, SuSe, etc., es decir, al sistema operativo y sus aplicaciones y no al kernel del sistema. La realidad es que Linux es solamente el kernel o núcleo del sistema, el cual es un programa de gran tamaño y complejidad que opera nuestra computadora. Entre las funciones más importantes del kernel:
  • Administración de la memoria, principal y secudaria.
  • Administración de procesos.
  • Establecimiento de la comunicación entre aplicaciones y dispositivos.

Aunque no son las únicas, si son las de más relevancia.

El kernel de Linux se caracteriza por estar en constante desarrollo para corregir algún problema o agregar una nueva característica, generando gran cantidad de actualizaciones en poco tiempo. Dichas actualizaciones comúnmente contienen nuevos módulos, mejoras de seguridad, administración de recursos y muchas otras características.

¿Cómo averiguar que innovaciones incorpora determinado kernel? Observando un archivo incorporado en el mismo llamado ChangLog. Asimismo es factible descargar y observar el archivo de texto plano Changelog desde la página oficial del proyecto.

Muchas veces surgen dudas acerca de la necesidad de compilar el kernel cuando liberan una nueva versión: no debemos dudar, solamente se compila una nueva versión de kernel cuando tenemos dispositivos de hardware muy recientes y nos vemos forzados a migrar hacia una versión que incluya módulos para el soporte de este. Otra razón se basa en que poseemos una versión muy antigua y optamos por actualizarlo para tener mejoras en la administración de memoria, procesos, recursos, etc. Actualmente ocurre esto con la rama 2.4 y 2.6 del kernel Linux; algunos servidores poseen la 2.4 y compilan la versión de la rama (2.6.x) con el objetivo de mejorar la administración de recursos, ya que esta última es más eficaz.

El kernel NO se actualiza, si deseas una nueva versión debes descargar las fuentes de la página oficial del proyecto y compilarla. También puedes buscar un paquete (por ejemplo en los repositorios de Debian) con una versión ya compilada para la arquitectura del CPU; evitando la tarea de compilar y desaprovechando la optimización del sistema.



Objetivo

Construir un kernel que tenga soporte del sistema de archivos ext4 en un sistema GNU/Linux Debian.



Sistema de archivos ext4

El kernel de linux puede soportar varios sistemas de archivos: FAT12, FAT16, FAT32, ext2, ext3, ext4, etc. El sopote de los distintos sistemas de archivos se pueden construir directamente en el kernel o pueden ser enlazados en tiempo de ejecución como módulos. Por defecto el sistema de archivos ext4 es enlazado como módulo:

oskr@kro:~$/sbin/lsmod
Module   size Used by
...
ext4   306996 1       1
..

Compilaremos oskr@kro:$ gunzip linux-3.16.2.tar.gzel kernel de Linux para que el sistema de archivos ext4 sea soportado directamente el kernel.


Fuentes y firma

Las fuentes de todas las versiones del kernel del linux que se han desarrollados se pueden obtener en el sitio oficial del kernel. Podemos obtener el archivo con las fuentes y la firma del mismo utilizado el comando wget:


oskr@kro:~$mkdir kernel

oskr@kro:~$cd kernel

oskr@kro:~/kernel$

oskr@kro:~/kernel$ wget -c https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.2.tar.gz

oskr@kro:~/kernel$ wget -c https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.2.tar.sign


Siempre será necesario comprobar que el archivo que contiene las fuentes no haya sido alterado, para ello comprobamos su firma. La firma se obtiene del archivo sin compresión:


oskr@kro:~/kernel$ gunzip linux-3.16.2.tar.gz


En el mismo directorio de trabajo, utilizamos la herramienta GPG (GNU Privacy Guard) para revisión de firmas:


oskr@kro:~/kernel$ gpg --verify linux-3.16.2.tar.sign
gpg: Signature made Fri 05 Sep 2014 07:05:55 PM CDT using RSA key ID
6092693E
gpg: Can't check signature: public key not found


Necesitamos obtener la llave pública con el ID mostrado:

oskr@kro:~/kernel$ gpg --keyserver hkp://keys.gnupg.net --recv-keys 6092693E
gpg: keyring '/home/oscar/.gnupg/secring.gpg' created
gpg: requesting key 6092693E from hkp server keys.gnupg.net
gpg: /home/oscar/.gnupg/trustdb.gpg: trustdb created
gpg: key 6092693E: public key ``Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>'' imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)



Con la lleve pública, ejecutamos de nuevo el comando:

oskr@kro:~/kernel$ gpg --verify linux-3.16.2.tar.sign
gpg: Signature made Fri 05 Sep 2014 07:05:55 PM CDT using RSA key ID 6092693E
gpg: Good signature from ``Greg Kroah-Hartman (Linux kernel stable release signing key)
<greg@kroah.com>''
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 647F 2865 4894 E3BD 4571 99BE 38DB BDC8 6092 693E


Se puede compilar el kernel como usuario, sin embargo, es recomendable descomprimir y desempaquetar las fuentes en la ruta creada para ese propósito:
/usr/src

oskr@kro:~/kernel$ su -
Passwd: <password de root>

root@kro:~# cp /home/oskr/kernel/linux-3.16.2.tar.gz /usr/src

root@kro:~# cd /usr/src

root@kro:~/usr/src# tar -zxvf linux-3.16.2.tar.gz


Se creará el árbol de directorios del kernel. Debido a que algunas aplicaciones podrían hacer referencia a las fuentes del nuevo kernel, se crea una enlace simbólico:

root@kro:~/usr/src# ln -s linux-3.16.2 linux

root@kro:~/usr/src# cd linux

A partir de este punto las rutas que se presentan son relativas a /usr/src/linux.  



Configuración basada en el kernel que está en ejecución

Se podría configurar totalmente un kernel desde cero, pero es una tarea muy elaborada. Es común partir de una configuración base y hacer solamente los cambios necesarios. Para ello es conveniente basarnos en la configuración del kernel que está en ejecución. Para averiguar qué versión de kernel está en ejecución:

#uname -a
Linux kro 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 GNU/Linux


Dicha configuración se encuentra en el archivo /boot/config-3.2.0-4-686-pae, el cual deberá de ser copiado en con el nombre .config en la ruta donde se encuentran las fuentes:

#cp /boot/config-3.2.0-4-686-pae .config

Si compilaramos las fuentes sin cambiar nada del archivo .config, obtendríamos una copia exacta del  kernel que está en ejecución.

El archivo .config  contiene las directivas para la creación de los archivos construcción del kernel:

CONFIG_x86_32=y
...
CONFIG_MMU=y

Hacer algún cambio en el archivo .config sigue siendo una tarea complicada. Podemos utilizar una herramienta basada en ncurses (libncurses5-dev) para la visualización de todas las opciones de compilación. Es muy probable que la biblioteca no esté instalada:

#apt-get install libncurses5-dev

una vez instalada lanzamos el menú de configuración:

#make menuconfig
 
otra herramienta más cómoda basada en tk 2.4 y libqt en 2.6 es:

$make xmenuconfig

Con la opción "Load" seleccionamos el archivo .config. En la sección de "File Systems" se tiene lo siguiente:

<M> The Extended 4 (ext4) filesystem

lo que indica que el soporte para el ext4 se construirá como módulo. Con la tecla Y cambiamos a:

<*> The Extended 4 (ext4) filesystem

Seleccionando la opción "exit" varias veces salimos al menú principal y guadamos la canfiguración. Se ha creado los archivos de reglas y dependencias para la compilación de códigos: Makefiles. Si editamos el Makefile principal podemos agregar una cadena para reconocer nuestra versión del kernel:

#nano Makefile

...
EXTRAVERSION = -so14O
NAME = Oscar Alvarado
...


Para guardar los cambios: Ctrl-o y enter; para salir del editor: Ctrl-x.



Compilación del kernel y módulos

Actualmente los Makefiles creados realizan varias funciones de forma automática, como resolver dependencias entre códigos y sistemas. Así, solo será necesario ejecutar el siguiente comando para compilar el kernel y los módulos:

#make

Sip, así de fácil!. El tiempo de compilación dependerá de los recursos del sistema en el que se está compilando: Core 2 Duo 2.0Ghz, 2G en RAM toma aproximadamente 100 min, suficiente para ir a tomar un cafecito illy.



Instalación

Los scripts creados también ayudan a la instalación tanto del kernel como  de los módulos dependientes del mismo, bastará con ejecutar los siguientes comandos como super usuario:

#make install

el comando anterior instalará tres archivos al directorio /boot
  • System.map-3.16.2-so14O
  • vmlinuz-3.16.2-so14O
  • config-3.16.2-so14O
Para instalar los módulos en la ruta /lib/modules/3.16.2-so14O, se ejecuta:

#make modules_install



RAM File System

Los sistemas Linux necesitan de un sistema de archivos para funcionar, incluso es necesario tener acceso a un sistema de archivos desde el arranque del sistema. Una vez arrancado el kernel, el sistema necesita acceder a archivos de configuración y archivos binarios para el arranque del sistema. Si el kernel no accede a un sistema de archivos de arranque, se detiene y muestra el error:

"Kernel panic:VFS:Unable to mount root fs..."

Uno de los archivos a los que necesita acceder el kernel de manera incial es el /etc/inittab,  en el cual se encuentran los parámetros para iniciar el único proceso que crea el kernel, el init. Si el archivo se encuentra en algún dispositivo de almacenamiento, el sistema se hace dependiente del mismo para su arranque. Para evitar dicha dependiencia se puede crear un sistema de archivos pequeño el cual será parte de la imagen de arranque, evitando la dependencia con el dispositivo. Además de los archivos de arranque, se agregan un shell para poder ejecutar los comandos de los scripts de arranque /etc/rc.NIVEL, para realizar un arranque más complejo.

Para crear un sistema de archivos en RAM para el inicio del sistema, ejecutamos el siguiente comando:

#mkinitramfs -k -o /boot/initramfs-3.16.2-so14O 3.16.2-so14O



Configuración del grub2

En el directorio /boot se encuentra todo lo relativo al arranque de Linux. En ese mismo directorio encontramos el directorio /boot/grub, el cual contiene los archivos para que el GRUB v2 (GRand Unified Bootloader) funcione. El archivo /boot/grub/grub.cfg, es en realidad un script que se ejecuta en el momento de inicio del sistema. Cuando lo editas con vi o vim, la primera línea te advierte que no lo edites, es decir, que no cambies nada, ya que este archivo es generado de manera automática por herramientas del mismo GRUB. Puedes leerlo y verás que está todo lo realtivo a la selección y arranque de los sistemas operativos que tiene tu chompu. 

Con el
GRUB v2 agregar un nuevo kernel al menú de arranque es muy sencillo y se puede hacer de dos formas. En ambas es necesario copiar el nuevo kernel al directorio /boot, lo cual es muy probable que ya se haya realizado con el comando de la sección anterior make install. En la primera forma ejecutamos el comando:

#grub-mkconfig > grub.config.NEW

el comando anterior explorará los dispositivos, particiones y el sistemas de archivos en busca de sistemas, creando una configuración y almacenándola en el archivo
grub.config.NEW, el nuevo archivo deberá suplantar al archivo de configuración:

#mv /boot/grub/grub.config /boot/grub/grub.config.OLD
#cp /boot/grub/grub.config.NEW /boot/grub/

Para el segundo método que es mucho más sencillo pues realiza lo anterior, basta con ejecutar el comando:

#update-grub
Found linux image /boot/vmlinuz-3.16.2-so14O
Found initrd image /boot/initrd.img-3.16.2-so14O
Found linux image /boot/vmlinuz-3.2.0-4-686-pae
Found initrd image /boot/initrd-3.2.0-4-686-pae



Configuración del kernel por defecto

Cuando hemos compilado y probado varios kernels, el menú de inicio puede extenderse de manera no muy adecuada. Si deseamos eliminar algún kernel del menú de inicio, basta con eliminarlo del directorio /boot y ejecutar de nuevo el comando update-grub.

#rm /boot/vmlinuz-3.2.0-4-686-pae /boot/initrd.img-3.2.0-4-686-pae
#update-grub

Si lo que deseamos es solamente cambiar el kernel que es seleccionado por defecto, editamos el archivo de configuración de grub.

#vim /etc/default/grub

modificamos la variable GRUB_DEFAULT, la cual originalmente tiene el valor de 0. El 0 indica que la primera entrada en la lista del menú será la que se carge por defecto. Así, será necesario ubicar en la lista del menú, el número de entrada del kernel que deseamos que se carge, por ejemplo, si de la siguiente lista deseamos que el kernel versión 2.6.32-5-686 sea el kernel que arranque por defecto, hacemos:

Debian GNU/Linux, with Linux 3.2.3
Debian GNU/Linux, with Linux 3.2.3 (recovery mode)
Debian GNU/Linux, with Linux 3.16.2-so14O
Debian GNU/Linux, with Linux 3.16.2-so14O (recovery mode)
Debian GNU/Linux, with Linux 3.7.1-som12Ihack
Debian GNU/Linux, with Linux 3.7.1-som12Ihack (recovery mode)
Debian GNU/Linux, with Linux 2.6.32-5-686
Debian GNU/Linux, with Linux 2.6.32-5-686 (recovery mode)
Microsoft Windows XP Profesional (on /dev/sda1)
Windows Recovery Environment (loader) (on /dev/sda2)

cambiamos el valor de la variable de la siguiente forma:

GRUB_DEFAULT=6

finalmente ejecuatmos de nuevo el comando:

#update-grub


Verificación

Reiniciamos el sistema:

#reboot


Evidentemente si hubo algún error, el mismo sistema de arranque nos lo hará saber no iniciando la chompu =-)

Si inició normalmente el sistema entonces la compilación funcionó adecuadamente. Podemos verificar que el kernel que creamos realmente está en ejecución:

#uname -a
Linux kro 3.16.2-so14O #1 SMP Fri Sep 16 07:12:85 i686 GNU/Linux


Finalmente comprobamos que el sistema de archivos ext4 ya se encuentra construido en el kernel, por lo cual NO deberá listarse en los módulos enlazados.

$/sbin/lsmod
Module   size Used by
...
...