9.11.2010

Compilando un Kernel a lo CentOS

Compilar un kernel siempre puede ser una tarea larga y complicada si se desconocen ciertas herramientas que hacen de esta tarea en cambio algo fluido y hasta divertido ;)

En esta ocación compilaremos un kernel en una distro CentOS la cual está basada en RedHat. No he tenido la oportunidad de probar en otras distros similares como Fedora, pero creo que no debe haber mayor diferencia, con el tiempo iré publicando compilaciones rápidas de otras distros para señalar las diferencias entre ellas.



Para empezar descargo las fuentes del kernel de www.kernel.org, en este ejemplo usare la versión 2.6.27.53

wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.53.tar.bz2
Recordar que esto descargará el archivo en nuestra ubicación actual. Por lo que se recomienda hacer esto desde /usr/src.

Ahora lo descomprimimos:
tar xvjf linux-2.6.27.53.tar.bz2
Un paso opcional es el aplicar posibles parches al kernel, las X significan la version del parche y el comando --dry-run ejecuta el comando sin realizar cambios, si todo sale bien ejecutamos el siguiente:
bzip2 -dc patch.X.X.bz2 | patch -p1 --dry-run
bzip2 -dc patch.X.X.bz2 | patch -p1
gunzip -c patch.X.X.gz | patch -p1 --dry-run
gunzip -c patch.X.X.gz | patch -p1
Verificamos tener las dependencias nescesarias, estas son: gcc, ncurses-devel, rpm-build.

Vemos si tenemos instalado:
rpm -qa gcc ncurses-devel rpm-build
Si sale como resultado el nombre del paquete es que está instalado, si no sale nada no está instalado. De ser este el caso, los instalamos com yum:
yum install gcc ncurses-devel rpm-build
Entramos al directorio que se descomprimió anteriormente las fuentes del kernel:
cd linux.2.6.27.53
Ejecutamos un par de comandos que nos aseguran tener preparado todo para la compilación:
make clean && make mrproper
Podemos copiar la configuración actual de nuestro kernel si está funcionando correctamente, donde X.X.X es la numeración del kernel:
cp /boot/config-X.X.X ./.config
Si no hacemos esto, el siguiente comando cargará la configuración por defecto del kernel actual sobre el que está corriendo el sistema. Entonces ahora se ejecuta la aplicación para configurar el kernel:
make menuconfig
Primero se carga el archivo .config con la opción "Load an alternative configuración file" si se guardó el .config anteriormente.

Recorrer los menus que se nos presentan puede llevarnos un buen tiempo, siempre podemos acceder a la ayuda del menu o de la opción correspondiente (recomendado). Con la barra espaciadora activamos o desactivamos una opción.

Para un equipo de escritorio por ejemplo, generalmente podemos desactivar lo que es virtualización, también podemos seleccionar el tipo de procesador acorde a nuestra máquina para optimizar sus funciones. Y si ya queremos ir mejorando las cosas, se puede desactivar todo tipo de hardware que no tenemos en nuestro equipo y que no vamos a usar en un futuro, por ejemplo drivers de video/sonido que no necesitamos, hardware de radiofrecuencia, etc.

Una vez completada la configuración se graba el .config con la última opción del menu principal "Save configuration to an alternative file". 


Ahora viene la magia del programa rpm-build que se instaló anteriormente, manualmente compilar el kernel, primero que no nos genera un .rpm lo cual nos dificultaría mucho la administración si se mantienen actualizaciones locales del kernel por ejemplo, la segunda ventaja es que nos evita estar ejecutando los pasos de compilación uno a uno, ya que debemos compilar el kernel, luego los módulos e instalar cada uno de estos, entre otras cosas más.

Ejecutamos lo siguiente:
make rpm
Nada más que eso, esto hará todos los pasos necesarios y terminaremos con los rpms de la fuente del kernel y del kernel como tal. Esto puede llevar varios minutos hasta horas dependiendo de la cantidad de opciones que hayamos elejido en la configuración y de la capacidad de la máquina.

Una vez finalizado se harán creado dos archivos:
- kernel_VERSION.src.rpm dentro de /usr/src/redhat/SRPMS (fuentes)
- kernel_VERSION.i386.rpm dentro de /usr/src/redhat/RPMS/i386

El primero como se indica, es el código fuente del kernel, el segundo es el que nos interesa y su ubicación variará si usamos una arquitectura diferente.

Ahora se instala el rpm del kernel:
cd /usr/src/redhat/RPMS/i386/
rpm -ivh --nodeps kernel_VERSION.i386.rpm
Donde: -i  install ; -v verbose ; -h signos de progreso ; --nodeps se recomienda para evitar conflictos con ciertas librerias.

Como penúltimo paso se crea la imagen de ram inicial initrd dentro de /boot:
cd /boot
mkinitrd initrd-VERSION.img VERSION
Donde VERSION tiene que ser la misma numeración del kernel que se compiló, en este ejemplo sería 2.6.27.53

Solo queda añadir la entrada al grub del nuevo kernel. Para esto editamos el archivo menu.lst del grub:
vi /boot/grub/menu.lst
Lo más facil sería copiar la entrada actual y modificar su nombre de entrada y sus nombres de archivos del kernel y del initrd. Es decir, supongamos que solo teníamos una entrada en el grub que es la que creó la instalación:

title CentOS (2.6.18-194.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-194.el5 ro root=/dev/dsk/root rhgb quiet
        initrd /initrd-2.6.18-194.el5.img
Entonces, copiamos esta entrada y cambiamos la numeración de VERSION acorde al kernel que compilamos, lo que nos dejaría:
title CentOS (2.6.18-194.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-194.el5 ro root=/dev/dsk/root rhgb quiet
        initrd /initrd-2.6.18-194.el5.img
title CentOS (2.6.27.53-custom1)
        root (hd0,0)
        kernel /vmlinuz-2.6.27.53-custom1 ro root=/dev/dsk/root rhgb quiet
        initrd /initrd-2.6.27.53-custom1.img

Guardamos los cambios con :wq (si lo abrimos con vi)

Y listo! Reiniciamos la máquina y en el grub elegimos el nuevo kernel.

Se lo puede comprobar con el comando:
uname -r
Y debería dar la version del kernel que compilamos.

Eso es todo!!
Saludos y como siempre, espero que sea de utilidad a alguien.
No duden en comentar!!