Presentación
Bienvenidos a una nueva serie de artículos sobre los secretos del
kernel. Tal vez, más de uno de Uds. Ha echado un ojo sobre los fuentes
del kernel. El kernel de Linux pasó de ser un par de archivos
compactados de 100k a más de 300 archivos en más de 9 Megabytes
compactados con más de 2 millones de líneas de código.
Estos artículos están preparados para programadores y no para usuarios
inexpertos. Obviamente que todo el mundo es libre de leer este
artículo y que cualquier duda que les quede respecto al mismo pueden
consultarme vía email.
Todos los días se descubren bugs nuevos y todos los días se escriben
nuevos patchs. Es casi imposible comprender en su totalidad el código
fuente del kernel hoy día. Está escrito por muchos
programadores, que aunque trataron de mantener el mismo estilo de
programación éste mucha veces difiere.
Linux: El Sistema Operativo de la Internet
Linux es un sistema de libre distribución para PCs. Es compatible con
el estándar POSIX 1003.1 e incluye grandes áreas de funciones de Unix
System V y BSD 4.3. Muchas partes substanciales del kernel de Linux
sobre los cuales concierne esta serie de artículos fueron escritas por
Linus Torvalds, un estudiante de ciencia de la computación en Finlandia.
La primera versión del kernel de Linux vió la luz en Noviembre de
1991.
Características Principales
Linux satisface casi todas las demandas de un
sistema operativo Unix actual:
- Multitarea
Linux soporta multitarea verdadera, todos los procesos corren de
manera independiente unos de otros. Ninguno de ellos necesita ceder el
procesador para la ejecución de otros procesos.
- Accesibilidad Multiusuario
Linux no sólo es un sistema operativo multiusuario. Sino que posee
acceso multiusuario. Linux permite tener terminales conectadas al
sistema utilizando los mismos recursos.
- Ejecutables cargados en demanda
Solo aquellas partes del programa que son necesarias para la ejecución
del mismo son cargadas en memoria.
- Paginación
Puede ocurrir que la memoria esté totalmente ocupada. Linux entonces
busca por páginas de memoria de 4k que puedan ser liberadas. Las
páginas son almacenadas en disco y la memoria es liberada. Si
alguna de estas páginas es requerida, Linux la toma del disco y la
pone en su lugar original. A diferencia de lo que comúnmente se
llama swapping (o archivo de intercambio para los usuarios de
Microsoft Windows) sólo algunas paginas se guardan en disco. Los
viejos sistemas Unix o inclusive los flamantes nuevos Windows 95 o
NT escriben en disco todas las paginas de un proceso, lo cual es
mucho menos eficiente.
- Cache de disco dinámico
Los usuarios de MSDOS estarán familiarizados con SmartDrive
(SMARTDRV). Este programa reserva una determinada zona de memoria
fijo para el cache del disco. Linux trabaja el cache del disco de
una forma mucho más dinámica. La memoria de reserva para el disco
se agranda cuando es necesario o se achica cuando hay escasez de
memoria disponible.
- Librerías compartidas
Las librerías son un conjunto de rutinas utilizadas por los programas
para procesar datos. Hay un numero de librerías estandares
utilizadas por más de un proceso a la vez. En los viejos tiempos
las librerías se incluían en el código ejecutable del programa.
Así es que si uno o más programas utilizaban las misma librería
esta era cargada más de una vez utilizando espacio en memoria
innecesario. Aquí es donde las librerías compartidas entran en
juego. Los ejecutables solo poseen un vinculo con la librería
compartida. De esta manera si uno o más programas utilizan las
misma librería ésta es cargada sólo una vez.
- Soporte para el estándar POSIX 1003.1 y en parte System V y BSD
POSIX 1003.1 define una interfaces mínima para un sistema operativo
tipo Unix. Esta interface está descripta en declaración de
funciones C. Este estardard es actualmente soportado por todos los
recientes y relativamente sofisticados sistemas operativos.
Microsoft Windows NT posee soporte para POSIX 1003.1.
Linux 1.2 soporta POSIX en su totalidad. Algunas interfaces
adicionales fueron y están siendo desarrolladas para
compatibilidad con System V y BSD.
- Diferentes formatos para archivos ejecutables
¿Quien no desea poder correr cualquier aplicación en Linux? Ya sea de
DOS, Windows 95, FreeBSD o OS/2. Por esta razón emuladores de DOS
y Windows95 están en actual desarrollo. Linux puede ejecutar
binarios de otras plataformas Unix basadas en Intel que conformen
con el estándar iBCS2,(intel Binary Compatibility standard).
- Sistemas de archivos diferentes
Linux soporta una gran variedad de sistemas de archivos. El más usado
actualmente es el Second Extended File System (Ext2). Otro sistema
de archivos implementeado de la File Allocation Table (FAT). Las
restricciones de acceso a este sistema de archivos están dado para
todo el disco ya que la FAT no está preparada para seguridad o
acceso multiusuario.
- Redes
Linux puede ser integrado en un sistema de redes Unix local. En
principio todos los servicios de red son soportado, Network File
System (NFS) y Remote Login (rlogin). SLIP y PPP ambos son
soportados.
- System V IPC
Linux usa esta tecnología para proveer de colas de mensajes, semáforos
y memoria compartida. Estas son variantes clásicas de la
comunicación entre-procesos (inter-process communication).
Compilando el Kernel
Antes de estudiar el corazón del kernel le vamos a pegar un vistazo al
código fuente del mismo.
Estructura del árbol de los fuentes:
En un sistema Linux, las fuentes se ubican normalmente bajo el
directorio /usr/src/linux. En el siguiente texto los directorios están
dados en forma relativa a este. La portacion a otras arquitecturas
No-Intel resulto en una modificación comparado con la versión 1.0 del
kernel. El código dependiente de la arquitectura está bajo arch/.
Hasta el presente este contiene arch/i386/ para los procesadores 386,
486 y Pentium de Intel, arch/mips/ para la arquitectura MIPS y
arch/sparc/ para el SPARC de Sun Microssystems. Como Linux es
bastante usado sobre PCs, nosotros nos concentraremos en esta
arquitectura.
El kernel de Linux no es más que un programa C estándar. Hay solamente
solo dos grandes diferencias. La función de entrada para los programas
escritos en C es normalmente main(int argc,char **argv). En Linux
ésta es start_kernel(void). El entorno del programa no existe todavía
(hablamos del momento de boot cuando la maquina arranca y esta por
correr el kernel de Linux). Esto significa que hay que hacer un par de
maniobras antes de que la primera función en C sea llamada. Los
códigos en ensamblador que se encargan de esta labor están contenidos
en el directorio arch/i386/asm/.
La rutina en ensamblador apropiada carga el kernel en la dirección
absoluta 0x100000 (1 Mbyte). Entonces instala las rutinas de servicio
de interrupción, las tablas descriptoras globales y las tablas
descriptoras de interrupciones, que son utilizadas únicamente durante
el proceso de inicialización. En este punto el procesador se pasa a
modo protegido. El directorio init/ contiene todo lo necesario para
inicializar el kernel. Además de otras funciones aquí está
start_kernel(). Su tarea es la de inicializar el kernel de manera
correcta, tomando en cuenta los parámetros de boot que se le fueron
pasados. El primer proceso es creado sin el uso de las llamadas al
sistema (todavía no tenemos al sistema cargado), es decir, a mano.
Este proceso es el famoso idle, es el que usa el tiempo del procesador
cuando ninguna tarea lo requiere.
Los directorios kernel/ y arch/i386/kernel/ contienen, como sus
nombres sugieren, las partes centrales del kernel. Aquí es donde las
principales llamadas al sistema (system calls) son alojadas. Aquí
también se encuentran implementadas otras áreas como ser el manejo del
tiempo, el planificador (scheduler), la DMA, el controlador de
interrupciones y el controlador de señales.
El código que maneja la memoria está almacenado en los directorios mm/
y arch/i386/mm/. Esta parte del código es la encargada de asignar y
liberar memoria a los procesos. Aquí también se aloja todo el código
que se encarga de la Paginación.
El sistema de archivos virtual (virtual file system) está en el
directorio fs/. Los diferentes sistemas de archivos soportas se
encuentran en subdirectorios a este. Los dos sistemas de archivos más
importantes y que estudiaremos en detalle más tarde son Ext2 y Proc.
Todos los sistemas operativos requieren de un driver para su
correspondiente componente de hardware. Estos están alojados en el
directorio drivers/.
En el directorio ipc/ se encuentran los fuentes de la implementación
del IPC del System V.
La implementación de varios protocolos de red, además del código para
los sockets y los dominios de Internet están almacenados en net/.
Algunas funciones estándar en C están implementadas en lib/, así la
programación del kernel puede utilizar los hábitos de la programación
en C.
Los módulos generados cuando el kernel es compilado están contenidos
en el directorio modules/. Este directorio está normalmente vacío
hasta que el kernel es compilado por primera vez.
Probablemente el más importante directorio que utilizan los
programadores es include/. Aquí se alojan todos los headers que son
específicos del kernel. El directorio include/asm-386/ contiene los
headers que son específicos del kernel y además de la plataforma
Intel.
Compilando:
En general, un nuevo kernel es generado en tres simples pasos. Primero
las opciones de compilación son configuradas mediante:
# make config
Luego las dependencias del código fuente son recalculadas:
# make depend
Y por último la real compilación del kernel es realizada con:
# make
Más tarde entraremos en el tema sobre el trasfondo de estos scripts y
su modificación para nuevas opciones de configuración.
Espero que hayan disfrutado de este articulo. Si tienen
sugerencias/ comentarios/ correcciones envíenmelas vía email a
elesende@nextwork.net.
Nos vemos la próxima.
|