Interpretación del código fuente del kernel del sistema operativo Linux

  
Para muchos entusiastas de Linux interesados ​​en el kernel, pero sin otra opción, este artículo pretende presentar una forma de entender el código fuente del kernel de Linux, en lugar de explicar el complejo mecanismo del kernel de Linux; Uno Organización de archivos del programa fuente principal:
1. Los programas fuente del kernel de Linux generalmente se instalan bajo /usr /src /linux, y tiene una convención de numeración muy simple: cualquier núcleo par (como 2.0.30) es un núcleo estable, y cualquier núcleo impar.
(Ej. 2.1.42) es un núcleo de desarrollo. Este artículo se basa en un código fuente estable 2.2.5, y la segunda parte de la plataforma de implementación es Redhat Linux 6.0. 2. Los archivos de la fuente principal están organizados en una estructura de árbol. En la parte superior de la fuente, verá directorios como este: • El subdirectorio Arco: arco contiene todo el código principal relacionado con la arquitectura. Cada uno de sus subdirectorios representa una arquitectura compatible, como i386 es un subdirectorio de la CPU de Intel y su arquitectura compatible. Las PC generalmente se basan en este directorio: ● Incluir: los subdirectorios incluyen la mayoría de los archivos de encabezado necesarios para compilar el núcleo. Los archivos de encabezado independientes de la plataforma están en el subdirectorio include /linux, los archivos de encabezado relacionados con intel cpu están en el subdirectorio include /asm-i386, y el directorio include /scsi es el directorio del archivo de encabezado para el dispositivo scsi; ● Init: El directorio contiene el código de inicialización del núcleo (nota: no es el código de inicio del sistema), contiene dos archivos main.c y Version.c, que es un muy buen punto de partida para el funcionamiento del núcleo. Mm: este directorio incluye todo el código de administración de memoria independiente de la arquitectura de la CPU, como la asignación y el lanzamiento de la memoria de administración de almacenamiento de páginas, y el código de administración de la memoria relacionada con la arquitectura se encuentra en arch /* /mm /, como arch /I386 /mm /Fault.c ● Kernel: el código del núcleo principal, los archivos en este directorio implementan las funciones del kernel de la mayoría de los sistemas Linux, el archivo más importante es sched.c; asimismo, el código relacionado con la arquitectura es Arch /* /kernel; ● Controladores: coloque todos los controladores de dispositivo para el sistema; cada controlador ocupa un subdirectorio: por ejemplo, /block es un controlador de dispositivo de bloque, como ide (ide.c). Si desea ver cómo se inicializan todos los dispositivos que pueden contener un sistema de archivos, puede mirar device_setup () en drivers /block /genhd.c. No solo inicializa el disco duro, sino que también inicializa la red, ya que la red debe instalarse al instalar el sistema de archivos nfs: por ejemplo, Lib coloca el código de la biblioteca principal; código de red, núcleo y red; Ipc, este directorio contiene el código de comunicación entre procesos del núcleo Fs, todos los códigos de sistema de archivos y varios tipos de código de operación de archivos, cada uno de sus subdirectorios admite un sistema de archivos, como fat y ext2; Scripts, este directorio contiene archivos de comandos para configurar el núcleo. Generalmente, en cada directorio, hay un archivo .depend y un Makefile. Estos dos archivos son archivos auxiliares que se usan en el momento de la compilación. Lea estos dos archivos cuidadosamente para comprender la conexión y las dependencias de cada archivo. Muy útil; además, también hay archivos Léame en algunos directorios, es una descripción de los archivos en el directorio, también es propicio para nuestra comprensión de la fuente del kernel; II. Interpretación de combate real: agregue una llamada del sistema a su kernel. Aunque el código fuente del kernel de Linux está organizado en una estructura de árbol muy razonable y científica, los archivos de funciones asociadas se ubican en el mismo subdirectorio, lo que hace que el programa sea más Legibilidad. Sin embargo, el código fuente del kernel de Linux es demasiado grande y muy complicado. Incluso con un método de organización de archivos muy razonable, todavía hay muchas asociaciones entre archivos en directorios diferentes. Algunos de los análisis de código del núcleo generalmente se verán en otros archivos. Archivos relacionados, y tal vez estos archivos no están en el mismo subdirectorio. La gran complejidad del sistema y las complejidades de los vínculos entre los documentos pueden ser la razón principal por la que muchas personas lo temen. Por supuesto, las recompensas de este trabajo desalentador también son muy fascinantes: no solo puede aprender mucho del conocimiento subyacente de la computadora (como lo indica el sistema a continuación), sino también toda la operación. La sutileza de la arquitectura del sistema y la inteligencia del algoritmo al resolver un problema de detalle específico y, lo que es más importante, en el proceso de análisis del código fuente, se irá especializando poco a poco, incluso mientras Después de analizar una décima parte del código, comprenderá profundamente qué tipo de código está escrito por un programador profesional, qué tipo de código está escrito por un aficionado. A fin de que los lectores entiendan mejor esta característica, a continuación se ofrece un ejemplo específico del análisis del kernel. Espero que a través de este ejemplo, los lectores puedan tener una comprensión específica de la organización del kernel de Linux, y los lectores también puedan aprender algo. Método de análisis del núcleo. El siguiente es un ejemplo de análisis: A, plataforma operativa:
Hardware: cpu intel Pentium II; Software: Redhat Linux 6.0; versión del kernel 2.2.5 B, análisis del código fuente del kernel relacionado:
1 . Arranque e inicialización del sistema: hay varias formas de arrancar un sistema Linux: comúnmente hay Lilo, Loadin boot y Linux bootstrapping (bootsect-loader), mientras que este último corresponde al programa fuente arch /i386 /boot /bootect. S, es un ensamblador en modo real, que no se analiza aquí debido al espacio; no importa qué método de arranque, finalmente salte a arch /i386 /Kernel /setup.S, setup.S se encuentra principalmente en el modo de tiempo de ejecución. Inicialización, en preparación para que el sistema ingrese al modo de protección; después de eso, el sistema ejecuta arch /i386 /kernel /head.S (para el kernel comprimido, primero ejecute arch /i386 /boot /compress /head.S); head. Un programa de ensamblaje setup_idt definido en S, que es responsable de crear una tabla idt de 256 elementos (tabla de descriptores de interrupción), que contiene todas las direcciones de entrada de interrupciones e interrupciones, que incluye la dirección de entrada del sistema de control maestro de llamadas system_call; Por supuesto, además de esto, head.S todavía tiene que hacer algún otro trabajo de inicialización; El primer programa del kernel que se ejecuta después de la inicialización del sistema, asmlinkage void __init start_kernel (void) se define en /usr/src/linux/init/main.c llamando a usr /src /linux /arch /i386 /kernel /traps. Una función en c __init trap_init (void) establece la dirección de entrada de cada trampa y la rutina de servicio de interrupción a la tabla idt, donde el programa maestro de llamadas al sistema system_cal es una de las rutinas de servicio de interrupción; la función void __init trap_init (void) pasa Llame a una macro set_system_gate (SYSCALL_VECTOR, &system_call); cuelgue la entrada del maestro de llamadas del sistema en la interrupción 0x80; donde SYSCALL_VECTOR se define en /usr/src/linux/arch/i386/kernel/irq.h Constante 0x80; y system_call es la dirección de entrada del programa de control maestro de interrupciones; el programa maestro de interrupciones se define en lenguaje ensamblador en /usr/src/linux/arch/i386/kernel/entry.S; 3. El programa de control maestro de interrupciones es el principal responsable Guarda el estado del procesador antes de ejecutar la llamada del sistema, comprueba si la llamada actual es legal y hace que el procesador salte a la rutina de servicio del sistema correspondiente almacenada en la tabla sys_call_table según el vector de llamada del sistema. El estado del manejador de recuperación se devuelve al programa de usuario después de regresar de la rutina de servicio del sistema, el vector de llamadas del sistema se define en /usr/src/linux/include/asm-386/unistd.h, la tabla sys_call_table se define en /usr /src /En linux /arch /i386 /kernel /entry.S; la interfaz de programación del usuario de la llamada al sistema también se define en /usr/src/linux/include/asm-386/unistd.h; 4. Se puede ver que Linux La llamada al sistema también es como el servicio de interrupción int 21h del sistema DOS. Toma la interrupción 0x80 como la entrada general y luego va a la dirección de entrada de las diversas rutinas de servicio de interrupción almacenadas en la tabla sys_call_table para formar varios servicios de interrupción. El análisis del código fuente muestra que para agregar una llamada al sistema, debe agregar una entrada en la tabla sys_call_table, guardar la dirección de entrada de su rutina de servicio del sistema y luego volver a compilar el kernel. Por supuesto, las rutinas de servicio del sistema son esenciales. . Se puede ver que en esta versión de la fuente del kernel de Linux, los archivos de origen asociados con la llamada al sistema incluyen lo siguiente: arch /i386 /boot /bootsect.S arch /i386 /Kernel /setup.S arch /i386 /boot /comprimido /head.S arch /i386 /kernel /head.S init /main.c arch /i386 /kernel /traps.c arch /i386 /kernel /entry.S arch /i386 /kernel /irq.h include /asm-386 /unistd.h Por supuesto, estos son solo algunos de los archivos principales involucrados. De hecho, aumentar la llamada al sistema realmente necesita modificar el archivo solo incluye /asm-386 /unistd.h y arch /i386 /kernel /entry.S dos

Copyright © Conocimiento de Windows All Rights Reserved