Kernel de Linux: desde el archivo ejecutable hasta el inicio del proceso

Referencia de este artículo: https://www.jianshu.com/p/84d96a6385b0
https://zhuanlan.zhihu.com/p/148426554?from_voters_page=true
https://www.cnblogs.com/qscfyuk/p/11697816. html
https://www.cnblogs.com/icecri/p/4438351.html

1. Concepto

1. Archivo
ejecutable El archivo ejecutable pertenece al archivo elf, y el cargador de procesos es para cargar el archivo ejecutable. El archivo ejecutable contiene muchas secciones, como la sección legible y ejecutable representada por la sección de código; la sección de datos y el BSS La autoridad representada por el segmento es legible y escribible, la autoridad representada por el segmento de datos de solo lectura es el segmento de solo lectura, y la información del programa cargada cuando se crea el proceso son estas partes. En Linux, las secciones se almacenan en unidades de "páginas" (la memoria física también está paginada, corresponden uno a uno, y una página generalmente tiene 4096 bytes, que es 4k). Si no hay una página, una página también está ocupada. El
archivo ejecutable ELF se carga en la ubicación de memoria 0x8048000 de forma predeterminada y comienza a cargarse desde esta ubicación. La información del encabezado del archivo ejecutable ELF se carga antes, pero debido a los diferentes tamaños de archivo, la entrada real del programa es: 0x8048x00, la leyenda es 0x8048300, lo que significa que esta ubicación es la dirección de entrada real del programa, es decir , el archivo ejecutable se acaba de cargar. El proceso (el punto de entrada para iniciar la ejecución después de que un proceso carga un nuevo archivo ejecutable), es desde este lugar para iniciar la ejecución

Para obtener más información sobre los archivos elf, consulte: https://www.cnblogs.com/qscfyuk/p/11697816.html

2. Procesar el espacio de direcciones virtuales.
Cada proceso tiene su propio espacio de direcciones virtuales de 4G (sistema de 32 bits). De hecho, no todos los procesos tienen un espacio tan grande en el disco o la memoria, pero el espacio direccionable del proceso es 4G (Para sistemas de 32 bits, el rango de direccionamiento es 0x0000 0000 ~ 0xFFFF FFFF)
La memoria virtual es una tecnología de gestión de la memoria del sistema informático. Hace que la aplicación piense que tiene memoria disponible continuamente (un espacio de direcciones continuo y completo), pero de hecho, generalmente se divide en múltiples fragmentos de memoria física, y algunos se almacenan temporalmente en un disco externo, cuando es necesario. Realizar intercambio de datos. En comparación con los sistemas que no usan tecnología de memoria virtual, los sistemas que usan esta tecnología facilitan la escritura de programas grandes y usan la memoria física real de manera más eficiente. Cuando el procesador lee o escribe en una ubicación de memoria, usa una dirección virtual. Durante una operación de lectura o escritura, el procesador traduce la dirección virtual en una dirección física.
Ventajas: los
programadores no necesitan preocuparse por cómo almacenar datos o programas. Los
programas pueden usar una serie de direcciones virtuales continuas para acceder a grandes áreas de memoria discontinuas en la memoria física. Los usuarios ven direcciones continuas sin preocuparse por direcciones físicas de nivel inferior. Disposición .
Al usar la memoria virtual, el programa puede usar más espacio que la memoria física real disponible. Cuando la memoria física no es suficiente, el sistema operativo guardará la página de memoria física en el archivo de disco y la página de datos o la página de códigos se moverá entre la memoria física y el disco según sea necesario.
Las direcciones virtuales utilizadas por diferentes procesos están aisladas entre sí, y los usuarios no necesitan preocuparse por afectar los datos en las direcciones de memoria de otros programas. El módulo de administración de memoria del sistema operativo asigna las direcciones virtuales a direcciones físicas.
3. Un proceso ocupa principalmente las siguientes partes en la memoria, Son el segmento de código, segmento de datos, BSS, pila, montón y otros parámetros. Entre ellos, el contenido de código, datos y BSS es el contenido correspondiente en el archivo ejecutable. El cargador no llena su contenido del programa ejecutable en la memoria, sino que actualiza su información (dirección base, longitud, etc.) en el bloque de control de proceso (task_struct), cuando la CPU realmente se ocupa de la ejecución por primera vez, causará una interrupción por falla de página y el sistema operativo copiará el contenido real del archivo ejecutable a la memoria física.
El contenido del montón se asigna dinámicamente durante la ejecución del programa, por lo que el cargador solo actualiza su dirección de inicio en el bloque de control de proceso, y cuando encuentra una operación de asignación de memoria dinámica durante la ejecución, asigna páginas reales en la memoria física. El área de parámetros debe almacenarse en la variable de entorno y la lista de parámetros de la línea de comandos cuando se carga el nuevo proceso. Los contenidos almacenados en la pila cuando se carga el programa son los punteros a la lista de parámetros del entorno y la lista de parámetros de la línea de comandos y el número de parámetros de la línea de comandos.

Referencia: https://blog.csdn.net/weixin_29058331/article/details/113368011?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4. -4.control

4. La tabla de páginas
puede hacer referencia a "Esencia del sistema operativo y principios de diseño".

Dos, creación de procesos

Inserte la descripción de la imagen aquí

1. Crear descriptor de proceso task_struct
2. Solicitar descriptor de memoria mm_struct. El
descriptor de memoria es el espacio de direcciones del proceso, que es lo que llamamos memoria virtual 4G. Se puede ver en el nombre que esta estructura se usa para describir la memoria, no realmente abrió 4G de espacio de memoria para él.
3. Cargar el programa ejecutable El programa
ejecutable se divide en segmento de código, segmento de datos y otras partes. Cuando se carga el sistema, estos segmentos de información se dan respectivamente (no para copiar todo el contenido del segmento real del archivo ejecutable, sino solo la información de este segmento. Marque la ubicación del segmento para crear una estructura vm_area_struct (área de memoria virtual), el vm_start / vm_end en la estructura respectivamente señalan a qué segmento del área de memoria virtual debe mapearse, como se muestra en la En la figura anterior, cada vm_area_struct apunta a la memoria virtual de la derecha Un intervalo del área.
El archivo ejecutable ELF se carga en la ubicación de memoria virtual 0x8048000 de forma predeterminada y comienza a cargarse desde esta ubicación. La información del encabezado del archivo ejecutable ELF se carga antes, pero debido a los diferentes tamaños de archivo, la entrada real del programa es: 0x8048x00
Este paso es equivalente a la relación de mapeo establecida entre la memoria virtual y los archivos ejecutables.

Tres, ejecución del proceso

Después del paso dos, el proceso ha cargado la información del programa ejecutable en su propia estructura, entonces, ¿cómo carga el programa los datos que se ejecutarán en la memoria física cuando el programa se está ejecutando?
1. La tabla de página,
la memoria virtual de marco de página y la memoria física se basan en la paginación, es decir, están divididas en áreas de 4k. Estas áreas de la memoria virtual se denominan tablas de página y la memoria física se denomina marcos de página. El principio específico no se detalla
2. Cuando el
programa de proceso en ejecución está programado, el sistema asignará algunos marcos de página al proceso y cargará el archivo ejecutable correspondiente en él. El proceso comienza a ejecutarse. Cuando el programa se ejecuta en una determinada dirección, el se encuentra el marco de página (el diseño aquí calcula el contenido de la dirección física real basándose en la dirección virtual) y no hay datos para ejecutar (es decir, se ha ejecutado parte del programa en el marco de página actual), y el Es necesario cargar la siguiente parte del programa ejecutable. Cuando se activa la interrupción de falla de página, el sistema cargará el siguiente programa ejecutable en el cuadro de página para continuar ejecutando
un proceso. La memoria ocupa principalmente las siguientes partes, que son segmentos de código, segmento de datos, BSS, pila, montón y otros parámetros. Entre ellos, el contenido de código, datos y BSS es el contenido correspondiente en el archivo ejecutable. El cargador no llena su contenido del programa ejecutable en la memoria, sino que actualiza su información (dirección base, longitud, etc.) en el bloque de control de proceso (task_struct) , cuando la CPU realmente se ocupa de la ejecución por primera vez, causará una interrupción por falla de página y el sistema operativo copiará el contenido real del archivo ejecutable al contenido del
montón en la memoria física. Se asigna dinámicamente durante la ejecución del programa, por lo que el cargador solo actualiza su dirección de inicio al bloque de control de proceso y asigna páginas reales en la memoria física cuando encuentra una operación de asignación dinámica de memoria durante la ejecución . El área de parámetros debe almacenarse en la variable de entorno y la lista de parámetros de la línea de comandos cuando se carga el nuevo proceso. Los contenidos almacenados en la pila cuando se carga el programa son los punteros a la lista de parámetros del entorno y la lista de parámetros de la línea de comandos y el número de parámetros de la línea de comandos.
Interrupción por fallo de página:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Citar otros artículos

1) Ingrese el nombre del archivo ./executable en la interfaz del shell.
Después del análisis del shell, si este parámetro no es un comando incorporado del shell, se considera que carga un archivo ejecutable. Así que llame a la función fork para comenzar a crear un nuevo proceso, genere una interrupción 0x80, mapee a la función sys_fork (), llame a la función find_empty_process () y solicite un número de proceso disponible para el nuevo proceso.
2) Encontrar espacio de almacenamiento
para la estructura de gestión del programa ejecutable Para proteger el proceso, el sistema diseña especialmente una estructura para la gestión de cada proceso, a saber, task_struct. El kernel obtiene la página para guardar task_struct y la pila del kernel llamando a la función get_free_page y solo puede estar en el espacio de direcciones lineal del kernel.
3) El proceso de shell copia la estructura task_struct
para el nuevo proceso. Después de que se copia task_struct para el programa ejecutable, el nuevo proceso hereda toda la información de gestión del shell. Sin embargo, debido a que la información en la estructura task_struct de cada proceso es diferente, la estructura debe ser personalizada (para evitar que se cambie al proceso durante el proceso de configuración, debe establecerse en un estado ininterrumpido). Las configuraciones personalizadas incluyen principalmente el número de proceso, el proceso principal, la franja de tiempo, el segmento TSS (diseñado para cambiar entre procesos, el proceso de conmutación se basa en la protección del proceso y TSS se utiliza para guardar o restaurar cuando se cambia el proceso. valor del registro utilizado en el escenario del proceso). Todo esto se hace a través de la función copy_process.
4) Copie la nueva tabla de páginas de proceso y configure su entrada de directorio de páginas correspondiente.
Ahora llame a la función copy_mem como segmento de proceso (LDT), actualice la dirección base del segmento de código y segmento de datos, es decir, determine el espacio de direcciones lineales ( la clave es determinar la dirección base del segmento y el límite de longitud). Luego está la paginación, que se basa en la segmentación.
5) Establecer la asociación entre el nuevo proceso y el descriptor global (GDT)
Enganche el TSS y LDT del nuevo proceso en la ubicación especificada de la GDT. (Nota: TSS y LDT son vitales para la protección del proceso)
6) Establezca el nuevo proceso en el estado listo
7) Cargue el archivo ejecutable Después de
ingresar la función do_execve, cargue la tabla de encabezado del archivo ejecutable en la memoria y verifique la información relevante. Cargue el programa ejecutivo (el programa se carga en la memoria a pedido).

Supongo que te gusta

Origin blog.csdn.net/chengcheng1024/article/details/114669992
Recomendado
Clasificación