Solicitando un análisis del código fuente del sistema operativo Linux

El sistema de configuración del kernel de Linux consta de tres partes, a saber: Makefile: Makefile distribuido en el código fuente del kernel de Linux, que define las reglas de compilación del archivo de configuración del kernel de Linux (config.in): proporcionado a los usuarios Proporciona la función de selección de configuración Herramientas de configuración: incluido el intérprete de comandos de configuración (interpreta los comandos de configuración utilizados en el script de configuración) y la interfaz de usuario de configuración (que proporciona una interfaz de configuración de usuario basada en una interfaz de caracteres, una interfaz gráfica de Ncurses y una interfaz gráfica de Xwindows; Cada uno corresponde a Make config, Make menuconfig y make xconfig).

Estas herramientas de configuración están escritas utilizando lenguajes de scripting como Tcl/TK y Perl (incluyendo también algo de código escrito en C). Este artículo no es un análisis del sistema de configuración en sí, sino una introducción a cómo utilizar el sistema de configuración. Por lo tanto, a menos que sean mantenedores de sistemas de configuración, los desarrolladores comunes del kernel no necesitan comprender sus principios. Solo necesitan saber cómo escribir Makefiles y archivos de configuración. Por lo tanto, en este artículo solo analizamos los Makefiles y los archivos de configuración. Además, cuando se trata de contenido relacionado con arquitecturas de CPU específicas, usaremos ARM como ejemplo. Esto no solo aclarará los problemas discutidos, sino que tampoco tendrá ningún impacto en el contenido en sí.

2. Makefile

2.1 Descripción general de Makefile

La función de Makefile es construir una lista de archivos fuente que deben compilarse de acuerdo con la configuración, luego compilarlos por separado y vincular el destino. código juntos para finalmente formar los binarios del kernel de Linux.

Dado que el código fuente del kernel de Linux está organizado según una estructura de árbol, los Makefiles también se distribuyen en el árbol de directorios. Los Makefiles en el kernel de Linux y los archivos directamente relacionados con Makefiles son: Makefile: el Makefile de nivel superior es el archivo de control general para toda la configuración y compilación del kernel. .config: archivo de configuración del kernel, que contiene opciones de configuración seleccionadas por el usuario, utilizado para almacenar los resultados de la configuración del kernel (como make config). arch/*/Makefile: Los Makefiles ubicados en varios directorios del sistema de la CPU, como arch/arm/Makefile, son Makefiles para plataformas específicas. Makefiles en cada subdirectorio: como controladores/Makefile, son responsables de la gestión del código fuente en el subdirectorio. Rules.make: Archivo de reglas, utilizado por todos los Makefiles.

Después de que el usuario configura a través de make config, se genera .config. El Makefile de nivel superior lee las opciones de configuración en .config. El Makefile de nivel superior tiene dos tareas principales: generar archivos vmlinux y módulos del kernel. Para lograr este objetivo, el Makefile de nivel superior ingresa recursivamente a cada subdirectorio del kernel y llama a los Makefiles ubicados en estos subdirectorios respectivamente. En cuanto a qué subdirectorios ingresar, depende de la configuración del kernel. En el Makefile de nivel superior, hay una oración: incluya arch/$(ARCH)/Makefile, que contiene el Makefile bajo una arquitectura de CPU específica. Este Makefile contiene información relacionada con la plataforma.

El Makefile ubicado en cada subdirectorio también construye una lista de archivos fuente requeridos bajo la configuración actual basada en la información de configuración proporcionada por .config, e incluye $(TOPDIR)/Rules al final del archivo. . hacer.

El archivo Rules.make juega un papel muy importante, define las reglas de compilación utilizadas por todos los Makefiles. Por ejemplo, si necesita compilar todos los programas C en este directorio en código ensamblador, debe tener las siguientes reglas de compilación en el Makefile:

.s: .c

$ (CC) $(CFLAGS) -S $lt; -o $@

Si hay muchos subdirectorios con los mismos requisitos, debe incluir esta regla de compilación en sus respectivos Makefiles, lo que será más problemático . En el kernel de Linux, dichas reglas de compilación se colocan de manera uniforme en Rules.make y se incluyen en Rules.make (incluye Rules.make) en sus respectivos Makefiles, evitando así la duplicación de las mismas reglas en múltiples Makefiles. Para el ejemplo anterior, las reglas correspondientes en Rules.make son:

.s: .c

$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$ ( *F)) $(CFLAGS_$@) -S $lt; -o $@

2.2 Variables en Makefile

El Makefile de nivel superior define y envía muchas variables al entorno. , pase cierta información al Makefile en cada subdirectorio. Algunas variables, como SUBDIRS, no solo se definen e inicializan en el Makefile de nivel superior, sino que también se expanden en arch/*/Makefile.

Las variables comúnmente utilizadas incluyen las siguientes categorías:

1) Información de versión

La información de versión incluye: VERSIÓN, PATCHLEVEL, SUBLEVEL, EXTRAVERSION, KERNELRELEASE. La información de versión define la versión actual del kernel, como VERSION=2, PATCHLEVEL=4, SUBLEVEL=18, EXATAVERSION=-rmk7, que en conjunto constituyen la versión de lanzamiento del kernel KERNELRELEASE: 2.4.18-rmk7

2) Arquitectura de CPU: ARCH

Al comienzo del Makefile de nivel superior, use ARCH para definir la arquitectura de la CPU de destino, como ARCH:=arm, etc. En el Makefile de muchos subdirectorios, se selecciona una lista de archivos fuente a compilar de acuerdo con la definición de ARCH.

3) Información de ruta: TOPDIR, SUBDIRS

TOPDIR define el directorio raíz donde se encuentra el código fuente del kernel de Linux. Por ejemplo, el Makefile en cada subdirectorio puede encontrar la ubicación de Rules.make a través de $(TOPDIR)/Rules.make.

SUBDIRS define una lista de directorios Al compilar el kernel o módulo, el Makefile de nivel superior determina qué subdirectorios ingresar según SUBDIRS. El valor de SUBDIRS depende de la configuración del kernel. En el Makefile de nivel superior, a SUBDIRS se le asigna el valor de los controladores del kernel mm fs net ipc lib. Según la configuración del kernel, el valor de SUBDIRS se expande en arch/*/Makefile. el ejemplo en 4).

4) Información de composición del kernel: HEAD, CORE_FILES, NETWORKS, DRIVERS, LIBS

El archivo del kernel de Linux vmlinux se genera mediante las siguientes reglas:

vmlinux: $ (CONFIGURACIÓN) init/main.o init/version.o linuxsubdirs

$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o

--start-group

$(CORE_FILES)

$(DRIVERS)

$(NETWORKS)

$(LIBS)

--end-group

-o vmlinux

Se puede ver que vmlinux está compuesto por HEAD, main.o, version.o, CORE_FILES, DRIVERS , REDES y LIBS. Estas variables (como HEAD) se utilizan para definir la lista de archivos de destino y archivos de biblioteca que están conectados para generar vmlinux. Entre ellos, HEAD se define en arch/*/Makefile y se utiliza para determinar la lista de archivos que se vinculan primero a vmlinux. Por ejemplo, para las CPU de la serie ARM, HEAD se define como:

HEAD := arch/arm/kernel/head-$(PROCESSOR).o

arch/arm/kernel/ init_task .o

Indica que head-$(PROCESSOR).o e init_task.o deben vincularse primero a vmlinux. PROCESADOR es armv o armo, dependiendo de la CPU de destino. CORE_FILES, NETWORK, DRIVERS y LIBS se definen en el Makefile de nivel superior y se aumentan según sea necesario mediante arch/*/Makefile. CORE_FILES corresponde a los archivos principales del kernel, incluidos kernel/kernel.o, mm/mm.o, fs/fs.o, ipc/ipc.o. Se puede ver que estos son los archivos más importantes que componen el kernel. núcleo.

Al mismo tiempo, arch/arm/Makefile extiende CORE_FILES:

# arch/arm/Makefile

# Si tenemos un directorio específico de la máquina, inclúyalo en la compilación.

MACHDIR:= arco/brazo/mach-$(MÁQUINA)

ifeq ($(MACHDIR), $(comodín $(MACHDIR)))

SUBDIRS = $(MACHDIR)

CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)

endif

HEAD := arch /arm/kernel/head-$(PROCESSOR).o

arch/arm/kernel/init_task.o

SUBDIRS = arch/arm/kernel arch/arm/mm arch/ arm/lib arch/arm/nwfpe

CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)

LIBS := arch/arm/lib/lib.a $(LIBS)

5) Información de compilación: CPP, CC, AS, LD, AR, CFLAGS, LINKFLAGS

En Rules.make Qué Lo que se define son las reglas generales de compilación. Para ocasiones específicas, el entorno de compilación debe especificarse claramente en las variables anteriores. Para requisitos de compilación cruzada, se define CROSS_COMPILE. Por ejemplo:

CROSS_COMPILE = arm-linux-

CC = $(CROSS_COMPILE)gcc

LD = $(CROSS_COMPILE)ld

......

CROSS_COMPILE define el prefijo del compilador cruzado arm-linux-, lo que indica que todas las herramientas de compilación cruzada comienzan con arm-linux-, por lo que antes de cada herramienta del compilador cruzado, $( CROSS_COMPILE) se agrega para formar un nombre de archivo completo de herramienta de compilación cruzada, como arm-linux-gcc.

CFLAGS define los parámetros pasados ​​al compilador de C.

LINKFLAGS es un parámetro utilizado por el vinculador cuando vincula para generar vmlinux. LINKFLAGS se define en arm/*/Makefile, por ejemplo:

# arch/arm/Makefile

LINKFLAGS:=-p -X -T arch/arm/vmlinux.lds< / p>

6) Variables de configuración CONFIG_*

Hay muchas ecuaciones de variables de configuración en el archivo .config para explicar los resultados de la configuración del usuario. Por ejemplo, CONFIG_MODULES=y indica que el usuario ha seleccionado la función del módulo del kernel de Linux.

Después de que .config es incluido en el Makefile de nivel superior, forma una serie de variables de configuración, cada una de las cuales tiene un valor determinado: y significa que el código del núcleo correspondiente a esta opción de compilación se compila estáticamente en el kernel de Linux; m significa que este El código del kernel correspondiente a la opción de compilación se compila en un módulo; n significa que esta opción de compilación no está seleccionada, si no hay ninguna selección, el valor de la variable de configuración está vacío;

2.3 Variable Rules.make

Como se mencionó anteriormente, Rules.make es un archivo de reglas de compilación y todos los Makefiles incluirán Rules.make. El archivo Rules.make define muchas variables, siendo las más importantes las que compilan y vinculan las variables de la lista.

O_OBJS, L_OBJS, OX_OBJS, LX_OBJS: una lista de archivos de destino en este directorio que deben compilarse en el kernel de Linux vmlinux. La "X" en OX_OBJS y LX_OBJS indica que el archivo de destino usa EXPORT_SYMBOL. símbolo de salida.

M_OBJS, MX_OBJS: una lista de archivos de destino en este directorio que deben compilarse en módulos cargables. Asimismo, la "X" en MX_OBJS indica que el archivo de destino utiliza el símbolo de salida EXPORT_SYMBOL.

O_TARGET, L_TARGET: hay un O_TARGET o L_TARGET en cada subdirectorio. Rules.make primero compila y genera todos los archivos de destino en O_OBJS y OX_OBJS a partir del código fuente, y luego usa $(LD) -r. para compilarlos Enlace a un O_TARGET o L_TARGET. O_TARGET termina en .o, mientras que L_TARGET termina en .a.