Portabilidad del sistema Linux: proceso de inicio del kernel
Para iniciar el código del kernel de Linux, primero mire el archivo vmlinux.lds de su secuencia de comandos de enlace, el archivo es el siguiente:
Indica una entrada de entidad de función: función stext, ubicada en arch/arm/kernel/head.S
Hay un comentario de segmento en la entrada de la función.
Se estipula que la MMU, D-cache, r0=0, r1=machine nr (es decir, el ID de la máquina), r2=atags o la primera dirección del árbol de dispositivos (dtb) deben cerrarse antes de ejecutar la función ( r1, r2 son los parámetros pasados por la función)
La función primero realiza algunos juicios y conversiones para determinar que el modo está en BE8 y usa instrucciones de pulgar
Luego use la macro safe_svcmode_maskall para proteger las interrupciones IRQ y FIQ y cambie al modo SVC; guarde el valor CPSR original guardado en r9 en SPSR
safe_svcmode_maskall r9
Luego lea la identificación del procesador, el valor de la identificación se almacena en el registro r9
Llame a la función __lookup_processor_type para verificar si el sistema actual admite esta CPU y, de ser así, obtenga la información de procinfo en r5
El kernel de Linux abstrae cada procesador en una estructura proc_info_list, y cada procesador corresponde a un procinfo, por lo que la estructura procinfo correspondiente se encuentra a través de la ID del procesador.
Las siguientes definiciones de macro realizan diferentes funciones de acuerdo con las definiciones, sáltelas y no las mire.
Línea 121, llame a la función __vet_atags para verificar la validez de las etiquetas o el árbol de dispositivos (dtb)
Luego llame a __create_page_tables para crear una tabla de páginas y guarde la dirección de la función __mmap_switched al registro r13
Finalmente, llame a la función __enable_mmu para habilitar la MMU, __enable_mmu enciende la MMU llamando a __turn_mmu_on, y luego __turn_mmu_on ejecutará la función __mmap_switched guardada en r13 al final, __mmap_switched finalmente llama a start_kernel para iniciar el kernel de Linux
La función start_kernel se define en el archivo init/main.c. Esta función completa algunos trabajos de inicialización antes de que Linux comience llamando a muchas subfunciones. Hay muchas subfunciones aquí, que no se ampliarán en detalle. Estas funciones establecerán el tamaño de la pila e inicialice la pila. , configure algún código relacionado con la arquitectura, complete alguna inicialización del kernel y llame a la función rest_init después de que todo esté listo
La función rest_init se define en el archivo init/main.c
Primero llame a la función rcu_scheduler_starting para iniciar el programador de bloqueo de RCU
Luego llame a la función kernel_thread para crear el proceso kernel_init. El proceso init es un proceso kernel al principio (es decir, se ejecuta en el modo kernel), y luego el proceso init buscará un programa llamado "init" en el sistema de archivos raíz. , y este programa "init" está en modo usuario. , al ejecutar este programa "init", el proceso init realizará la transición del modo kernel al modo usuario
Luego llame a la función kernel_thread para crear el proceso del kernel kthreadd, el PID de este proceso del kernel es 2, y el proceso kthreadd es responsable de la programación y administración de todos los procesos del kernel.
Finalmente, se llama a la función cpu_startup_entry para ingresar al proceso inactivo cpu_startup_entry llamará a cpu_idle_loop .
Ingrese ps -A debajo de la interrupción de Linux para ver el proceso init y el proceso ktthreadd
systemd es el proceso de inicio
Es muy importante usar el proceso init. Parte del contenido se inicializa en el proceso. De acuerdo con los parámetros de ramdisk_execute_command y execute_command, se encuentra un programa ejecutable init en el sistema de archivos raíz. Si todo está vacío, ejecute "/sbin/ init", "/etc/init", "/bin/init" y "/bin/sh" son los cuatro programas de inicio de respaldo. Si estos cuatro no se ejecutan, se terminará y el sistema no podrá iniciarse. Además, el proceso init también llamará La función do_basic_setup se utiliza para completar la inicialización del controlador del dispositivo en Linux, completar la inicialización del subsistema del modelo del controlador en Linux y abrir el dispositivo "/dev/console" como entrada estándar y salida del sistema, realice la interacción de la línea de comandos y llame a la función prepare_namespace para montar el sistema de archivos raíz, por lo que la función do_basic_setup es muy importante para el proceso de inicio.
Lo anterior es un proceso general de inicio del kernel de Linux