Índice general, Mostrar marcos, Sin marcos

Capítulo 13
El código fuente del núcleo de Linux

En este capítulo trataremos de explicarle cómo buscar ciertas funciones del núcleo en el propio código fuente.

La lectura de este libro no exige un conocimiento profundo de la programación en lenguaje 'C' ni tampoco la disponibilidad de una copia del código fuente de Linux. Sin embargo, será interesante ejercitar los conocimientos adquiridos mirando el código fuente para así comprender mejor cómo funciona internamente Linux. Este capítulo da una visión general del código fuente, en lo que respecta a cómo está organizado y en qué puntos debe mirarse para buscar alguna cosa concreta.

Dónde obtener el código fuente de Linux

Todas las distribuciones conocidas ( Craftworks, Debian, Slackware, Red Hat, etcétera) incluyen como opción las fuentes del núcleo de Linux. Normalmente, el binario que corre en su máquina ha sido construido con esas fuentes. Debido a la naturaleza del propio sistema operativo, esas fuentes estarán seguramente obsoletas, por lo que lo más interesante será obtener la última versión de uno de los servidores de Internet mencionados en el apéndice  www-appendix. El código fuente es mantenido en ftp://ftp.cs.helsinki.fi y en cualquier réplica suya. Esto hace al servidor de Helsinki el más actualizado, pero en otros servidores como el del MIT o el de Sunsite encontraremos seguramente las mismas versiones que en el primero.

Si no dispone de acceso a la Red, aun dispone de muchos CD ROM con copias de lo que esos servidores ofrecen en cada momento, a un precio muy razonable. Algunos fabricantes ofrecen un servicio de suscripción con los que puede obtener actualizaciones cada cierto tiempo (incluso cada mes). Otro lugar interesante para buscar es en su grupo local de usuarios.

Las versiones del código fuente de Linux se numeran de una manera simple. Todo núcleo con un número de versión par (tal como 2.0.30) es un núcleo estable, y si el número de versión es impar (como 2.1.42) se trata de una versión de desarrollo. En este libro nos basamos en el código fuente de la versión estable 2.0.30. Las versiones de desarrollo están a la última en cuanto a características generales y soporte de dispositivos. Aunque pueden ser inestables, y por lo tanto no ser lo que usted necesita, es muy importante que la comunidad de usuarios los prueben. Recuerde, en caso de usar núcleos de desarrollo, hacer siempre copias de respaldo por si fuera necesario recuperarse de alguna catástrofe.

Cuando se publica un cambio en el núcleo, éste se distribuye en forma de parche. La utilidad patch se puede utilizar para aplicar parches que editan ficheros del código fuente. Por ejemplo, si tenemos instalado el núcleo 2.0.29 y queremos pasar a la versión 2.0.30, no tenemos que borrar la antigua y obtener toda la nueva versión (que pueden ser decenas de megabytes). En su lugar, podemos obtener el parche de la 2.0.30, mucho más pequeño, y aplicarlo sobre la 2.0.29 con el comando:


$ cd /usr/src/linux
$ patch -p1 < patch-2.0.30

Esto guarda también, por seguridad, copias de cada fichero modificado. Un buen sitio donde podemos buscar parches (oficiales y no oficiales) es en el servidor http://www.linuxhq.com.

Organización del Código Fuente

En el directorio principal del árbol del código fuente, /usr/src/linux, podemos unos cuantos directorios:

arch
El subdirectorio arch contiene todo el código específico de una arquitectura. Dentro hay más subdirectorios, uno por cada arquitectura soportada. Por ejemplo, i386 o alpha.
include
El directorio include contiene casi todos los ficheros que se necesitan incluir durante la compilación del código. También contiene diversos subdirectorios, incluyendo uno por cada arquitectura soportada. El subdirectorio include/asm es realmente un enlace simbólico al que corresponda para la arquitectura, como include/asm-i386. Para cambiar de arquitectura hay que editar el fichero Makefile del núcleo y volver a ejecutar el programa de configuración del núcleo.
init
Este directorio incluye el código de iniciación del núcleo, y es un buen sitio donde mirar para comenzar a entender cómo funciona el mismo.
mm
Aquí está todo el código de gestión de memoria independiente de la arquitectura. La parte dependiente estará bajo arch/*/mm/, como por ejemplo arch/i386/mm/fault.c.
drivers
Todos los manejadores de dispositivos se encuentran aquí. A su vez se divide en clases de controlador, como block para los dispositivos de bloques.
ipc
Este directorio contiene todo el código para la comunicación entre procesos.
modules
Este directorio se utiliza para montar los módulos cuando sea necesario.
fs
Contiene todo el código para el sistema de ficheros. A su vez se divide en subdirectorios, uno para cada sistema de ficheros soportado, como vfat y ext2.
kernel
Aquí tenemos el código principal del núcleo. Una vez más, aquella parte específica para una arquitectura se encontrará en arch/*/kernel.
net
Código para trabajo con redes.
lib
Aquí se encuentran librerías necesarias para el núcleo. De nuevo, hay librerías que son dependientes de la arquitectura, y se encontrarán en arch/*/lib/.
scripts
En este directorio se encuentran los scripts (tipo awk o tk) que son necesarios para configurar o compilar el núcleo.

Dónde empezar a mirar

Cuando nos enfrentamos a consultar el código de un programa tan grande como el núcleo de Linux, en general no sabremos por dónde empezar. Todo se muestra como una gran cadena de la que no se ve su principio o final. Muchas veces comenzamos a estudiar el código y mirando aquí y allá acabamos olvidando qué estábamos buscando. En los siguientes párrafos le daremos unas ideas sobre los puntos del código fuente donde puede encontrar respuestas a sus dudas.

Arranque e inicialización del sistema

En un sistema basado en Intel, el núcleo comienza a ejecutarse cuando lo carga y le pasa el control un programa como loadlin.exe o LILO. Esta parte puede verse en arch/i386/kernel/head.S. Este programa inicial realiza ciertas preparaciones propias de la arquitectura y a continuación salta a la rutina main() del fichero init/main.c.

Gestión de la Memoria

Esta parte se encuentra principalmente en mm pero la parte más específica de cada arquitectura la encontraremos en arch/*/mm. El código de tratamiento de fallo de página se encuentra en mm/memory.c, y la parte correspondiente al mapeado de la memoria y la cache de páginas se encuentra en mm/filemap.c. La cache de buffer se detalla en mm/buffer.c y la cache del intercambio (swap), en mm/swap_state.c y mm/swapfile.c.

El núcleo

La parte común a todas las arquitecturas está en kernel, y la parte específica de cada una de ellas, en arch/*/kernel. El planificador lo encontramos en kernel/sched.c y el código para creación de procesos, en kernel/fork.c. La parte de bajo nivel de los manejadores se encuentra en include/linux/interrupt.h. La estructura de datos task_struct se localiza en include/linux/sched.h.

PCI

El pseudo-controlador de PCI se encuentra en drivers/pci/pci.c, con las definiciones especificadas en include/linux/pci.h. Cada arquitectura tiene una parte específica al correspondiente BIOS de PCI: los Alpha AXP se tratan en arch/alpha/kernel/bios32.c.

Comunicación entre procesos

Todo ello está en ipc. Los objetos del IPC de Unix Sistema V tienen una estructura ipc_perm y puede encontrarse en include/linux/ipc.h. Los mensajes de Sistema V se implementan en ipc/msg.c, la memoria compartida en ipc/shm.c y los semáforos en ipc/sem.c. Las tuberías se implementan en ipc/pipe.c.

Tratamiento de interrupciones

El código de tratamiento de interrupciones es en su mayor parte propio de cada microprocesador (y prácticamente distinto en cada plataforma). El código correspondiente a Intel (en un PC) está en arch/i386/kernel/irq.c y las definiciones necesarias se declaran en include/asm-i386/irq.h.

Controladores de dispositivo

El grueso del código fuente de Linux lo forman los controladores de dispositivos. Todos ellos se encuentran bajo el directorio drivers, a su vez organizados según su tipo, en otros subdirectorios:

/block
Aquí están los dispositivos de bloque, como los discos IDE (en ide.c). Si queremos ver cómo los dispositivos pueden contener sistemas de ficheros e inicializarse, miraremos en la función device_setup() de drivers/block/genhd.c. Aquí, no solo se preparan discos: también la red si es necesario (por ejemplo, cuando queremos montar sistemas de ficheros nfs). Los dispositivos de bloques incluyen a los discos IDE y SCSI.

/char
En este directorio se pueden encontrar los dispositivos de carácter tales como los ttys, los puertos serie o el ratón.

/cdrom
Aquí se encuentra todo el código referente a CDROMs especiales (como la interfaz con CD de SoundBlaster). Nótese que el controlador del CD tipo IDE/ATAPI se encuentra junto a los demás controladores IDE (drivers/block/ide-cd.c) y que el encargado de los CD SCSI se encuentra en el fichero scsi.c de drivers/scsi.

/pci
Aquí encontraremos el código fuente del pseudo-controlador de PCI. Es un buen sitio para ver cómo el subsistema PCI es mapeado e iniciado. El código específico para el PCI de Alpha AXP se encuentra en arch/alpha/kernel/bios32.c.

/scsi
Este es el lugar donde encontraremos todo lo referente al SCSI así como los diferentes controladores SCSI existentes y soportados en Linux.

/net
En este directorio debemos mirar para buscar los controladores de tarjetas de red. Por ejemplo, el controlador de la tarjeta de red DECChip 21040 (PCI) se encuentra en tulip.c.

/sound
Aquí se implementa todo lo relacionado con las diferentes tarjetas de sonido.

Sistemas de Ficheros

Las fuentes para el sistema EXT2 están en el directorio fs/ext2/, residiendo las definiciones necesarias en include/linux/ext2_fs.h, ext2_fs_i.h y ext2_fs_sb.h. Las estructuras de datos correspondientes al Sistema de Ficheros Virtual (VFS) se declaran en include/linux/fs.h y el código está en fs/*. La implementación de la cache de buffer se reparte entre el archivo fs/buffer.c y el demonio update.

Redes

El código para el tema de las redes se encuentra en net y los ficheros de inclusión correspondientes en include/net principalmente. El código para los sockets BSD está en net/socket.c y el correspondiente a los sockets de IP versión 4, en net/ipv4/af_inet.c. El código de soporte de protocolo genérico (incluyendo las rutinas de manejo de sk_buff) está en net/core y la parte correspondiente a TCP/IP en net/ipv4. Los controladores de las tarjetas de red están en drivers/net.

Módulos

Para usar módulos, parte del código va incluido en el núcleo, y parte en el paquete de los módulos. El código del núcleo va todo él en kernel/modules.c, declarándose las estructuras y los mensajes del demonio kerneld en include/linux/module.h e include/linux/kerneld.h, respectivamente. Si desea conocer la estructura de un fichero objeto ELF, deberá mirar en include/linux/elf.h.


File translated from TEX by TTH, version 1.0.
Inicio del capítulo, Índice general, Mostrar marcos, Sin marcos
© 1996-1998 David A Rusling derechos de autor.