Bienvenido a la wiki dedicada a los usuarios nuevos en GNU/Linux, este sitio esta orientado a ayudar a los usuarios nuevos... Si deseas contribuir, por favor crate una cuenta.
Compilar el Kernel de Linux
De PUFs Wiki
Es bien sabido que las distribuciones "binarias" como es el caso de la gran mayoria, instalan un kernel por defecto muy generico, esto es, sin optimizaciones para un tipo de procesador en especial, no aprovechando asi las prestaciones de los mas nuevos, manteniendo todo lo posible como como módulo, lo cual relentiza un poco la carga de este, encontrandose en la necesidad de ubicar y cargar los módulos que va necesitando, pero a su vez tiene el beneficio de que este kernel podrá sin mayores problemas, detectar el hardware de la mayoría de los usuarios. La discución sobre si es mejor un kernel monolítico (con todo dentro de la imagen principal) o modular es algo que aún hoy sigue, sea como sea, es claro que el kernel por defecto que viene con las mayoría de las distribuciones no es para nada óptimo, y esta es la principal motivación para tener nuestro kernel compilado, con las opciones que necesitamos y optimizado lo mejor posible para nuestro hardware y, porque no, nuestros gustos. Claro que además de estas razones tambien se encuentran las de aplicar parches para agregar nuevas funciones, soporte para nuevo hardware u otras cosas.
Nota: Esta guía es en "modo consola", ya que si bien se puede utilizar el entorno gráfico este no siempre está disponible.
Tabla de contenidos |
[editar] Requisitos
- Conociemiento de tu PC (Hardware)
- Uso basico de la consola/terminal (cp, ls, mv, etc...)
- Herramientas de compilacion (gcc, ld, make, etc...)
- Los fuentes del kernel
- Acceso como root para algunas cosas
- Tiempo :)
[editar] Identificación del Hardware
Principalmente necesitamos saber que dispositivos tenemos, marca y modelo, esto lo hacemos con el comando lspci:
# lspci 00:02.0 USB Controller: nVidia Corporation MCP61 USB Controller (rev a2) 00:04.0 PCI bridge: nVidia Corporation MCP61 PCI bridge (rev a1) 00:05.0 Audio device: nVidia Corporation MCP61 High Definition Audio (rev a2) 00:07.0 Bridge: nVidia Corporation MCP61 Ethernet (rev a2) 00:08.0 IDE interface: nVidia Corporation MCP61 SATA Controller (rev a2) 00:0d.0 VGA compatible controller: nVidia Corporation GeForce 6100 nForce 405 (rev a2) 01:0a.0 Multimedia controller: Philips Semiconductors SAA7130 Video Broadcast Decoder (rev 01) ...
También puede resultarnos útil el comando lsmod, el cual nos muestra los módulos que hay cargados en memoria y si se están usando o no.
# lsmod snd_pcm_oss 19040 0 snd_mixer_oss 12096 1 snd_pcm_oss snd_seq_oss 23552 0 snd_seq_midi_event 4288 1 snd_seq_oss snd_seq 38400 4 snd_seq_oss,snd_seq_midi_event snd_seq_device 4116 2 snd_seq_oss,snd_seq nvidia 7240216 22 i2c_nforce2 3520 0 i2c_core 12544 2 nvidia,i2c_nforce2 k8temp 3200 0 hwmon 1288 1 k8temp snd_hda_intel 10848 2 snd_hda_codec 168064 1 snd_hda_intel snd_pcm 52744 3 snd_pcm_oss,snd_hda_intel,snd_hda_codec snd_timer 14408 2 snd_seq,snd_pcm snd 37672 13 snd_pcm_oss,snd_mixer_oss,... soundcore 4128 1 snd snd_page_alloc 4880 2 snd_hda_intel,snd_pcm ...
Como se puede apreciar en la salida de estos comandos, estamos ante un chipset nVidia ( un nForce 405 ), disponemos de una placa de video integrada GeForce 6100, de un micro K8 ( AMD64 ) y tenemos una placa de sonido "High Definition Audio". Recomiendo que juegen con estos comandos ya que es importante aprender a interpretar su salida.
- Nota 1: Salida recortada por motivos de espacio
- Nota 2: Si no encuentra el comando lspci asegúrate de ejecutarlo como root
- Nota 3: Se le puede agregar la opción -v o -vv al comando lspci para que sea más detallado
[editar] Obteniendo
La manera "neutral" de obtener el kernel es de la página oficial, www.kernel.org. Ni bien entramos a la página nos encontraremos con una tabla ofreciéndonos distintas versiones del kernel de Linux. A nosotros nos interesa la última versión estable, y esa es la primera entrada en la tabla. Una vez localizada la versión que queremos debemos decidir si queremos bajarla completa o solamente un parche, en nuestro caso queremos el kernel entero, por lo cual debemos hacer un click en la F de Full ( Completa en inglés ), si quisieramos el parche haríamos click en la V. En definitiva, la primera entrada se vería algo como esto:
The latest stable version of the Linux kernel is: 2.6.XX ....F V C Changelog
Simplemente un click en la F :)
También podemos usar el método preferido de nuestra distribución para bajar el código fuente del kernel, por ej:
Sin embargo debemos tener en cuenta que por lo general las distintas distribuciones le aplican parches diferentes a los kernels que dan a bajar, de modo que no es el kernel original que se encuentra en www.kernel.org sino una modificación.
[editar] Descomprimiendo
Una vez descargado nos encontramos ante un archivo .tar.bz2 que debemos descomprimir. Ahora, la pregunta es ¿dónde lo descomprimo? Uno lo puede hacer en muchos lugares, realmente muchos, pero lo normal es hacerlo dentro de /usr/src, ya que ahí es donde se guarda el código fuente de las distintas partes del sistema, incluyendo el kernel. Luego deberemos también crear un enlace simbólico hacia el directorio donde están los fuentes del kernel llamado /usr/src/linux, ¿por qué? porque varios programas que dependen del kernel para compilar buscarán los fuentes en ese directorio, y si no lo encuentran se negarán a ser compilados. Para realizar todo esto ejecutaremos una serie de comandos similar a la siguiente ( debemos ser el usuario root para poder escribir en /usr/src ):
# cd /usr/src # mv ~/Descargas/linux-2.6.XX.tar.bz2 . # tar xjfv linux-2.6.XX.tar.bz2 # ln -s linux-2.6.XX linux
La descripción detallada de estos comandos es la siguiente:
- Entramos al directorio /usr/src donde descomprimiremos el kernel
- Movemos el kernel desde el lugar donde lo descargamos hacia /usr/src, desde luego hay que reemplazar ~/Descargas/linux... por la ubicación y el archivo adecuado.
- Descomprimimos el kernel, las opciones del comando tar son las siguientes:
- x: Extraer
- j: Descomprimir con bz2
- f: Usar el archivo que le pasamos en la línea de comandos
- v: Ser "Verbose", es decir, detallado. Lo que hace es mostrar la lista de archivos a medida que los extrae, de lo contrario no muestra nada.
- Creamos el enlace simbólico para que /usr/src/linux apunte hacia la carpeta verdadera donde está nuestro kernel
[editar] Configurando
El kernel de Linux viene con algunas herramientas para configurarlo, las cuales simplemente crean el archivo oculto .config, sabiendo esto, hay unas cuantas maneras de hacerlo:
- Editar el archivo .config a mano: Evidentemente no lo vamos a hacer
- make config: Nos realiza preguntas y nostros respondemos Si/No/Módulo, horrible, pero sirve en casos extremos
- make menuconfig: Nos presenta un lindo menú en modo texto para configurar el kernel
- make xconfig: Nos presenta un lindo menú gráfico utilizando las librerías QT
- make gconfig: Nos presenta un lindo menú gráfico utilizando las librerías GTK+
Para poder utilizar el menú en modo texto necesitamos de las librerías ncurses y sus encabezados, lo mismo sucede si queremos utilizar la configuración gráfica, necesitaremos o QT o GTK+ y sus encabezados. Una vez terminamos de configurar el kernel se creará una archivo llamado .config en el directorio actual ( /usr/src/linux ), lo cual nos obliga a compilar el kernel como root. ¿No podemos compilarlo como otro usuario? Si, si podemos, para ello agregaremos una opción al comando make, la opción O=directorio/de/salida, de esta forma el kernel guardará los archivos .config y los archivos objeto producto de la compilación en ese directorio, el cual obviamente está bajo el control de nuestro usuario :) Nosotros eligiremos menuconfig para configurar nuestro kernel, por lo cual los comandos a ejecutar serían:
# cd /usr/src/linux # make menuconfig
pero debemos ser root, en caso de que queramos compilar el kernel con nuestro usuario preferido ejecutaríamos el comando así:
# cd /usr/src/linux # make O=/home/mi_usuario/mi_carpeta menuconfig
Obviamente debemos hacer el enlace simbólico en /usr/src/linux como mencionamos anteriormente. En caso de fallar recuerden que necesitamos los encabezados y las librerías adecuadas. En algunos sistemas descendientes de Debian ( como Ubuntu ) necesitaremos instalar ncurses-dev, libncurses-dev o algun paquete de nombre similar, además desde luego de los compiladores y enlazadores. Luego de ejecutar el comando anterior y esperar un poquito a que termine la compilación aparecerá una pantalla similar a la siguiente:
Las teclas para configurar el kernel en este modo son pocas:
- Con las flechas nos movemos ariba y abajo por las opciones, y derecha e izquiera elijen los botones que hay disponibles en la parte de abajo de la pantalla
- Enter/Entrar/Intro para entrar en un submenu, nótese que el botón "select" está preseleccionado :)
- Y para que dicho soporte sea includo dentro del kernel
- M para que la opción de ser posible sea compilada como un módulo
- N para deshabilitarla
- ? para ayuda sobre la opcion elejida
Por ejemplo en el siguiente caso tenemos la primer opción como módulo, la segunda incluída dentro del kernel, la tercera deshabilitada y la última, que es un sub-menu de varias opciones tiene seleccionado lo que dice entre parentesis
Luego de recorrer todos los menús y habilitar las opciones que nos sean necesarias, salimos del menuconfig y guardamos los cambios. Esto se logra regresando al menu principal y seleccionando el botón "exit", lo que hará que se nos pregunte si deseamos guardar dichas configuraciones. No se pregunta ningún nombre de archivo ya que es por defecto el .config en el directorio actual ( o el directorio elegido con la opción O=... ). En caso de que queramos guardar las opciones en una archivo a parte debemos ir con las flechitas hacia abajo en el menú principal hasta que lleguemos a una opción que dice "Save an Alternate Configuration File" o similar, entramos como si de un submenú se tratara, y ahí podemos guardarlo en el archivo que queramos. Hay que tener en cuenta que los cambios guardados en ese archivo no se verán reflejados sobre el .config y por ende no nos sirve para compilar el kernel.
[editar] Compilando
Para compilar el kernel basta con ejecutar un comando, pero recuerden que para ejecutarlo como un usuario distinto de root debemos agregar la opción O=algun_directorio.
# make
Luego de ejecutar el comando una serie de mensajes comenzarán a aparecer en la pantalla, esto es normal e indica que archivos se está compilando/enlazando. Si todo va bien, esta operacion puede demorar entre 10 minutos y media hora, dependiendo del poder de nuestra PC y las opciones que hallamos elegido.
[editar] Instalando
Una vez compilado tendremos que copiarlo a algún lado y además debemos decirle que instale los módulos, para eso realizamos lo siguiente:
# make modules_install # cp arch/ARQUITECTURA/boot/bzImage /boot/NOMBRE-KERNEL
ARQUITECTURA debemos reemplazarlo por la arquitectura para la cual estamos compilando el kernel, generalmente es i386 para 32 bits y x86_64 para 64 bits, y NOMBRE-KERNEL por el nombre de archivo que queremos darle al kernel. > Ejemplo: cp arch/i386/boot/bzImage /boot/kernel-nuevo No es necesario que lo copiemos en el directorio /boot, pero es el lugar más usual ( y esto se remonta a hace mucho tiempo atrás... es una historia a parte ).
El primer comando lo que hace es instalar los módulos del kernel, para que el mismo sepa donde buscarlos, y el directorio destino es /lib/modules/2.6.XX ( dependiendo del kernel ). El segundo comando simplemente copia el kernel al directorio /boot. Hay que tener en cuenta que si le pasamos la opción O=... cuando compilamos con make, entonces habrá que ir a buscar el kernel a ese directorio.
Nota: Evidentemente estos dos comandos deben ser ejecutados como root, de lo contrario no podrá copiar los archivos necesarios.
[editar] Configurando el Gestor de Arranque
Una vez completado todos los pasos anteriores debemos decirle a nuestro gestor de arranque ( usualmente LILO o GRUB ) dónde encontrar el kernel para que lo pueda cargar en memoria y hacerlo arrancar.
[editar] GRUB
GRUB es mi gestor de arranque preferido, es más potente que LILO ya que no está diseñado entorno a Linux, pero para nuestro problema nos basta cualquiera de los dos, después de todo estamos con Linux :)
Lo primero que debemos hacer es editar el archivo /boot/grub/menu.lst para agregar nuestro kernel a la lista de kernels disponibles para arrancar. Podemos editarlo con cualquier editor de texto, ya sea vi, vim, nano, kwrite, gedit o lo que sea. Es común que las distribuciones de Linux vengan con nano o vi/vim, pero hay otros sistemas Unix que solamente vienen con "vi", por lo cual aprender a usar el mismo es aprender a editar texto en cualquier Unix, ya que es el común denominador. Nosotros usaremos nano:
# nano /boot/grub/menu.lst
Una vez que nos encontramos editando el archivo debemos agregar las siguientes líneas, lo podemos hacer al final del mismo:
title Mi Kernel root (hd0,2) kernel /boot/mi-kernel ro root=/dev/particion
- title: Es el nombre que tiene nuestro kernel en la lista de arranque
- root: Le dice a GRUB a que disco/partición debe ir a buscar el kernel
- kernel: Es la ruta completa y el nombre de archivo del kernel que deseamos bootear. Además del nombre de archivo, separado por un espacio, se encuentran las opciones de arranque que le pasamos al kernel, en este caso son:
- ro: Le dice que monte la partición inicalmente como "sólo lectura", lo cual permite que trabajen herramientas como fsck y otras de manera sencilla y segura. Durante el arranque nuestros scripts se encargán de remontar la partición como "lectura/escritura".
- root: Le indica a nuestro kernel cual es la partición raíz, ya que el mismo no tiene la más remota idea desde que disco/partición lo cargaron en memoria, el único que sabe esto es GRUB... y nosotros :)
Tengan en cuenta que grub cuenta desde cero los discos/particiones siendo el primer número el disco y el segunda la partición, por ej: Lo que para Linux es /dev/sda2, para GRUB es (hd0,1). Y lo que para Linux es /dev/hdc3 para GRUB es (hd2,2). Además hay que tener en cuenta que si tenemos un disco rígido IDE y uno SATA Linux nos presentará con particiones como: /dev/hda1, /dev/sda1, sin embargo para GRUB el disco IDE viene primero, por lo cual /dev/sda1 sería (hd1,0), mientras que /dev/hda1 sería (hd0,0). También tengan en cuenta que no hace falta que la opción root=... del kernel y la opción root (hd...) de GRUB sean iguales, ya que por ej. podemos tener el kernel guardado en la partición /dev/sda1, pero el disco principal ( raíz ) puede ser /dev/sda2.
Una vez realizado los cambios guardamos el archivo y reiniciamos, si todo salió bien podremos elegir nuestro kernel de la lista y si tenemos más suerte todavía booteará correctamente. En caso de que no bootee correctamente o no funcione algún dispositivo no desesperen, seguro configuraron algo mal en el kernel, simplemente reinicien, elijan el kernel anterior y luego configuren, compilen e instalen el kernel de nuevo :)
[editar] LILO
Bueno, esto es sencillo, primero editamos lilo.conf que es el archivo de configuración.
nano /etc/lilo.conf
Este se arma así:
# Tenemos una primera parte en la que se especifica donde y como va a arrancar el selector.
# Consiste en lo siguiente:
boot=/dev/hda #Esto es para instalar LILO en el MBR, reemplazen /dev/hda por el disco con el que booteen
prompt #Esto nos posibilita elegir entre distintas opciones, sin esto LILO va a arrancar automaticamente el default
timeout=50 #Timer para la opcion default. En este caso si no se presiona ninguna tecla en 5 segundos, bootea el default.
default=pepito #Opcion "por defecto" con la cual arranca una vez pasado el "timeout" o sin el "prompt"
#Ahora entramos en la parte donde ponemos cada una de las entradas que van a aparecer en el menu
#y que es lo que bootea cada una (mas algunas opciones...)
image=/boot/kernel-2.6.18-pepito1 #¿Les suena familiar? Aca va la ruta a la imagen de kernel que crearon
label=pepito # Esto es el nombre que le damos a la entrada
read-only # Esto es para que al cargar el kernel, el root sea solo lectura. Hasta donde yo se es necesario.
root=/dev/hda1 #Aca se especifica donde se encuentra la particion root. Reemplazar por la que uds tengan.
#Eso es todo para la 1er opcion! Ahora mostramos un ejemplo de "modo rescate"
image=/boot/kernel-2.6.18-pepito1
label=pepito.rescue #No estoy seguro si se pueden agregar espacios en los labels...
read-only
root=/dev/hda1
append="init=/bin/bb" #Con esto lanzamos la consola de recuperacion estatica (no se si esto cambiara de acuerdo a
#la distribucion).
#Finalmente si compartimos la PC con un windows agregamso la siguiente entrada:
other=/dev/hda5 #Aca ponemos la particion desde donde bootea windows
label=windows #De nuevo un label...
Y guardamos los cambios.
Ahora solo es cuestion de correr lilo, para esto tipeamos
lilo
Y listo, ya queda todo guardado en la MBR. Tengan en cuenta que tienen que volver a usar el comando CADA VEZ que le hacen cambios al menu o instalan un nuevo kernel.
[editar] Errores Comunes
- Un error muy común es no incluir soporte para el sistema de archivos y tipo de disco rígido que estamos usando, incluso si lo compilan como módulo no sirve, ya que para cargar un módulo primero se necesita acceso al disco :) Lo que debemos hacer es SIEMPRE incluir soporte para nuestro sistema de archivos ( ej: ext3 ) y nuestro controlador de disco rígido ( ej: SATA nForce 430 ) compilado en el kernel, con Y, y jamás pero jamás con M.
- Algún programa se queja de la falta de System.map: Este archivo puede ser necesitado por algunos programas específicos, en este caso lo podemos copiar como mencionamos en la FAQ a continuación, pero al día de hoy todos los programas deberían ser capaces de buscarlo en /usr/src/linux/System.map y tener que copiarlo a /boot debería ser cosa del pasado.
[editar] Notas sobre Debian
Debian necesita initrd para bootear. Si intentamos arrancar el sistema con el nuevo kernel, pero no con una imagen initrd tendremos un kernel panic. Deberemos inclir RAM disk support en la configuración del kernel a compilar Para crear el initrd necesitamos instalar initrd-tools
# apt-get install initrd-tools # cd /boot/ # mkinitrd -o /boot/initrd.img-2.6.xx.x (nombre destino) 2.6.xx.x (versión de kernel a generar,o sea la que bajamos)
Tendremos que agregar lo siguiente al archivo /boot/grub/menu.lst
title Mi Kernel root (hd0,2) kernel /boot/mi-kernel ro root=/dev/particion initrd /boot/initrd-img-2.6.xx.x
[editar] Tips
- Si deseamos usar la configuración del kernel que estamos usando actualmente para configurar los fuentes de uno nuevo podemos ejecutar el siguiente comando ( sólo es posible si el kernel se compiló con soporte para el archivo de configuración embebido en la imágen ):
# zcat /proc/config.gz > /usr/src/linux/.config
- Algunas distribuciones binarias como Ubuntu tienen junto con el kernel en /boot el archivo de configuración del kernel, con un nombre similar a config-loquesea, podemos usar ese archivo como base para nuestra configuración
- En caso de que estemos actualizando a una nueva versión del kernel, existe una manera sencilla de utilizar la configuración anterior y que el sistema nos pregunte que hacer con respecto a las nuevas opciones introducidas en la nueva versión. Para ello debemos copiar la configuración del kernel anterior (el que estamos corriendo ahora) dentro del directorio donde se encuentra el código fuente del nuevo kernel a compilar (ver el primer tip). Una vez hecho esto, ejecutamos el comando:
# make oldconfig
Con esto, el sistema se fijará que opciones nuevas hay con respecto a la vieja configuración y nos preguntará una por una que hacer. Luego, podemos proceder con el método de compilación habitual.


