Índice general,
Mostrar marcos,
Sin marcos
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.