[Enlace de compilación y gestión de memoria de iOS y enlazador dinámico]

Prefacio

En lo que a mí respecta, tengo muy pocos conocimientos sobre compilación y vinculación durante el desarrollo de iOS, pero este conocimiento sigue siendo muy importante.

El proceso de compilación y vinculación de iOS no es difícil y es bastante similar al proceso de ensamblaje de los principios de una microcomputadora. Hoy aprenderé y comprenderé el proceso de compilación y vinculación.
Referencia: Autocultivo de programadores de iOS: proceso de compilación y vinculación
Referencia: proceso de compilación de iOS

Idiomas informáticos

Los lenguajes informáticos incluyen el lenguaje de máquina, el lenguaje ensamblador y el lenguaje de alto nivel. Para lenguajes de alto nivel como OC, se dividen en lenguajes compilados y lenguajes interpretados.
Insertar descripción de la imagen aquí

  • Idioma compilado (traducción única)
    • Características: Traducción única.
    • Los programas en lenguaje compilado se pueden ejecutar directamente cada vez que el compilador los compila , como es el caso de OC y Swift.
    • La ventaja es que la velocidad de ejecución es lo suficientemente rápida porque no es necesario compilar varias veces.
    • La desventaja es que la portabilidad es deficiente: es necesario vincular las bibliotecas del sistema operativo al compilar y es posible que se necesiten bibliotecas diferentes.
  • Idiomas interpretados (traducción paso a paso)
    • Un programa escrito en un lenguaje interpretado debe ser interpretado y ejecutado dinámicamente por el intérprete cada vez que se ejecuta, por ejemplo, se interpreta php,javascriptun fragmento de código
      y se ejecuta un fragmento de código.
    • La ventaja es que tiene buena portabilidad y no requiere bibliotecas de sistema complejas.
    • La desventaja obvia es que la velocidad de ejecución es lenta y no es una operación única.

Extensión de archivo

Durante el proceso de compilación y vinculación de iOS, diferentes nombres de sufijos de archivos representan diferentes tipos de archivos y procesos intermedios.

  • .iArchivo: .iel archivo es un archivo generado después de que el preprocesador procesa el código fuente y contiene el código después de operaciones de preprocesamiento, como la expansión de macros y la compilación condicional.

  • .sArchivo: .sun archivo es un archivo de código ensamblador generado por el ensamblador. Traduce archivos generados por el preprocesador .ien representaciones textuales de instrucciones de máquina, una para cada instrucción de ensamblaje.

  • .oArchivo: .oun archivo es un archivo objeto generado por el compilador, también conocido como archivo objeto. Contiene instrucciones de máquina generadas por el ensamblador, así como algunas tablas de símbolos, información de reubicación y otra información de depuración.

  • .mArchivo: .mArchivo es una extensión común para archivos de código fuente Objective-C. Contiene código Objective-C y se puede mezclar con código C y C++.

Estos archivos se generan en diferentes etapas del proceso de compilación y vinculación, y se convierten y se pasan entre sí durante todo el proceso, generando en última instancia archivos ejecutables o archivos de biblioteca.

Proceso de compilación y vinculación.

Como se mencionó anteriormente, OC/swift son lenguajes compilados. Durante la ejecución, el compilador genera código de máquina. El código de máquina se puede ejecutar directamente en la CPU, lo cual es más rápido.

La compilación de OC se basa en Clang/LLVM. Una comprensión simple es que LLVM es una colección de tecnologías de herramientas y compiladores modulares y reutilizables. Clang es una subrutina de LLVM. C, C++ y OC son todas subrutinas de Clang. Su propósito es compilar mejores programas de manera más rápida y eficiente.

Proceso de compilación y vinculación: preprocesamiento -> análisis léxico -> análisis de sintaxis -> análisis estático -> generar código intermedio y optimización -> ensamblaje -> enlace =
preprocesamiento -> compilar -> ensamblaje -> enlace
Por favor agregue la descripción de la imagen.

compilar enlace

1. Preprocesamiento: macros, reemplazo de archivos de encabezado de importación y procesamiento de otras instrucciones de precompilación . 产生.i文件(todos comienzan con #)

2. Compilar: compila una serie de archivos preprocesados 词法、语法、语义分析,并且优化后生成相应的汇编代码,产生.s文件;

3. Ensamblaje: el ensamblador genera instrucciones de máquina a partir del código ensamblador ( 输出目标文件,产生.o文件simplemente tradúzcalas una por una de acuerdo con la tabla de comparación de instrucciones de ensamblaje e instrucciones de máquina);

4. Vinculación: puede haber otros archivos en un archivo, por lo que también es necesario combinar los archivos de destino generados por la compilación y los archivos proporcionados por el sistema, este proceso es la vinculación. Después del enlace, 最后生成可执行文件.

Después de la compilación y vinculación, el código escrito se convierte en instrucciones binarias que la computadora puede reconocer.

Preprocesamiento (precompilación) -> Generar archivo .i

clang -E main.m -o main.i

Procesar directivas de precompilación que comienzan con "#" en archivos de código fuente

  • "#define" elimina y expande la definición de macro correspondiente.
  • Maneja todas las directivas de precompilación condicional. como#if/#ifdef/#else/#endif。
  • "#include/#import"Los archivos contenidos se insertan recursivamente aquí.
  • Elimine todos los comentarios "// o /**/".
  • Agregue identificadores de número de línea y nombre de archivo. 如“# 1 "main.m"”, se utilizará para la compilación y depuración.

Para resumir los resultados de lo que hace el compilador en la fase de preprocesamiento:

  • Reemplazo de macros (las definiciones de macros utilizadas en el código fuente se reemplazarán con el contenido correspondiente)
  • La introducción del archivo de encabezado (#include,#import)usa el contenido del archivo correspondiente .h para reemplazar el contenido de esta línea, así que intente reducir #import en el archivo de encabezado, use @class en su lugar y coloque #import en el archivo .m. )
  • Manejo de directivas de compilación condicional(#if,#else,#endif)

Compilar -> Generar archivo .s

clang -S main.i -o main.s

El proceso de compilación también se divide en análisis léxico -> análisis de sintaxis -> análisis estático y finalmente optimización para generar el código ensamblador correspondiente y obtener el archivo .s.

  • Análisis léxico: este paso convierte el código del archivo fuente en un flujo de marcado especial. El código fuente se divide en caracteres y palabras uno por uno. El archivo fuente correspondiente y el número de línea específico donde se encuentra el código fuente se marcan en el Loc al final de la línea, lo cual es conveniente Localice el problema al informar un error.
    Por favor agregue la descripción de la imagen.
  • Análisis de sintaxis: este paso consiste en analizar el flujo de tokens generado por el análisis léxico en un árbol de sintaxis abstracta (AST) De manera similar, cada nodo en él también está marcado con su posición en el código fuente. En este momento, se ha determinado la prioridad de los símbolos de operación; también se han determinado los múltiples significados de algunos símbolos, como por ejemplo si "*" es un signo de multiplicación o un puntero para tomar el contenido; si la expresión es ilegal, el los corchetes no coinciden, etc., se informarán errores.
    Por favor agregue la descripción de la imagen.
  • Análisis estático: analice la declaración de tipos y los problemas de coincidencia, como los métodos que se llaman pero no se definen, las variables que se definen pero no se utilizan, etc., para mejorar la calidad del código.
    • Análisis de tipos: en esta etapa, clang realizará comprobaciones, las más comunes son comprobar si el programa envía el mensaje correcto al objeto correcto y si llama a funciones normales con el valor correcto. NSObject*Si envía un mensaje a un objeto simple hello, clang informará un error. Del mismo modo, si establece una propiedad para un objeto que no coincide con su propio tipo, el compilador le advertirá que puede estar utilizado incorrectamente.
    • Otro análisis: compruebe si se inicializa varias veces.
  • Generación y optimización de código intermedio: LLVM compilará y optimizará el código, como optimización de variables globales, optimización de bucle, optimización de recursión de cola, etc., y finalmente generará código ensamblador.
  • Generación y optimización de código de destino: genere un lenguaje ensamblador específico de la máquina basado en un lenguaje intermedio. y optimizar el lenguaje ensamblador.

Ensamblaje->Generar archivo .o

clang -c main.s -o main.o

En esta etapa, el ensamblador convierte el código ensamblador legible generado en el paso anterior en código de máquina. El producto final es un archivo objeto que termina en .o. Los programas creados con Xcode encontrarán este archivo en el directorio DerivedData.

Enlace

clang main.o -o main

Esta etapa consiste en vincular el archivo de destino generado en la etapa anterior con la biblioteca estática referenciada y finalmente generar un archivo ejecutable.El vinculador resuelve el vínculo entre el archivo de destino y la biblioteca.

clang main.m生成可执行文件a.out(不指定名字默认为a.out),使用file a.outPuede ver la información de su tipo usando :

a.out: Mach-O 64-bit executable x86_64

Se puede ver que el tipo de archivo ejecutable es Mach-Ode tipo, y los archivos ejecutables en las plataformas MAC OS e iOS son de este tipo.

Mach-O (documentación oficial de Apple)

Por favor agregue la descripción de la imagen.

Bibliotecas dinámicas y estáticas.

Referencia: biblioteca estática y biblioteca dinámica de iOS, consulte aquí.
El proceso de vinculación consiste en vincular archivos y bibliotecas estáticas referenciadas y bibliotecas dinámicas. Entonces, ¿qué son las bibliotecas dinámicas y las bibliotecas estáticas y cómo se vinculan?

1. Biblioteca estática

Una biblioteca estática es una biblioteca de enlaces estáticos; es un paquete de archivos formado al comprimir y empaquetar múltiples archivos de destino. Los siguientes son tipos de bibliotecas estáticas.

  • ventanas.lib
  • linux.a
  • Exclusivo para MacOS.framework

biblioteca estática

  • Ventajas :: La biblioteca estática se integrará en el archivo ejecutable al compilar y vincular, lo que permitirá que el programa se ejecute de forma independiente en tiempo de ejecución sin depender de bibliotecas externas.
    Rápido, debido a la integración en el archivo ejecutable, las llamadas a bibliotecas estáticas suelen ser más rápidas que las llamadas a bibliotecas dinámicas porque no se requieren enlaces dinámicos.
  • Desventajas : El programa ejecutable generado es más grande. Si se ejecutan varios programas generados mediante enlaces estáticos al mismo tiempo, ocuparán una gran cantidad de espacio de memoria. Una vez que la biblioteca estática se compila y se vincula al archivo ejecutable, el código que desea actualizar o reemplazar la biblioteca estática debe volver a compilarse. todo el programa.
    Si varios programas utilizan la misma biblioteca estática, cada programa contendrá una copia del mismo código de biblioteca, lo que dará como resultado un código duplicado.

2. Biblioteca dinámica

  • La biblioteca dinámica es una biblioteca de enlaces dinámicos, que es una forma de implementar una biblioteca de funciones compartidas.
  • La biblioteca dinámica no se copiará al programa de destino durante la compilación, y el programa de destino solo almacenará referencias a la biblioteca dinámica.
  • Solo cuando las funciones de la biblioteca dinámica se utilicen realmente, se encontrarán, vincularán y utilizarán las funciones.
  • Los formatos de las bibliotecas dinámicas son: .framework, .dylib, .tbd……

Biblioteca dinámica :

  • Ventajas : Ahorre espacio en disco y, cuando se ejecuten varios programas que utilizan la misma biblioteca dinámica al mismo tiempo, los archivos de la biblioteca se compartirán a través del espacio de direcciones del proceso y no habrá código duplicado en la memoria. la biblioteca dinámica es más conveniente y solo necesita ser reemplazada. Los archivos de la biblioteca dinámica son suficientes y no es necesario volver a compilar todo el programa. Las bibliotecas dinámicas se vinculan dinámicamente cuando el programa se está ejecutando, lo que hace que los archivos de programa sean más pequeños y más fáciles de distribuir e implementar.
  • Desventajas : debe depender de bibliotecas dinámicas; de lo contrario, no se puede ejecutar. Las bibliotecas dinámicas deben cargarse cuando se inicia el programa, lo que puede aumentar ligeramente el tiempo de inicio del programa. Compatibilidad: dado que diferentes sistemas operativos o diferentes versiones de bibliotecas dinámicas pueden tener problemas de compatibilidad, se debe prestar especial atención a la compatibilidad de las versiones.

3. La diferencia entre bibliotecas dinámicas y bibliotecas estáticas

  • biblioteca estática
    • Cargado en tiempo de compilación
    • Ventajas: la carga y ejecución de código son más rápidas que las bibliotecas dinámicas.
    • Desventajas: desperdicio de memoria y espacio en disco, dificultad para actualizar los módulos.
  • biblioteca dinámica
    • Cargar en tiempo de ejecución
    • Ventajas: el tamaño es mucho más pequeño que el de la biblioteca estática y ahorra más memoria.
    • Desventajas: la velocidad de carga y ejecución del código es más lenta que la de las bibliotecas estáticas.
  • Observación:
    • 最小单位16kEl tamaño de la biblioteca dinámica compilada será menor que el de la biblioteca estática.等于16k。
    • Cambiar a una biblioteca dinámica provocará algunas ralentizaciones, pero se optimizará mediante la tecnología Lazy Binding.
    • Enlace retrasado: busque y registre la dirección de memoria del método cuando se use por primera vez, y el proceso de búsqueda se puede omitir para llamadas posteriores.

4. ¿Cuál es la relación entre bibliotecas dinámicas, bibliotecas estáticas y marcos?

  1. Las bibliotecas son archivos binarios compilados.
  2. Si es necesario proporcionar el código para uso externo pero no desea que se cambie, el código se puede encapsular en una biblioteca y solo se expone el archivo de encabezado para la llamada.
  3. Si desea mejorar la velocidad de compilación, puede encapsular parte del código en una biblioteca y solo necesita vincularlo durante la compilación.
  4. Todas las bibliotecas deben estar vinculadas. Hay formas estáticas y dinámicas de vincular bibliotecas, por lo que se producen bibliotecas estáticas y bibliotecas dinámicas.

frameworkEs un método de empaquetado de archivos que encapsula archivos de encabezado, archivos binarios y archivos de recursos para facilitar la administración y distribución. Por lo tanto, existen formatos de biblioteca dinámica y de biblioteca estática..framework;
Por favor agregue la descripción de la imagen.

Resumir

La compilación y vinculación es el proceso desde el comienzo de un archivo iOS hasta convertirse en un archivo ejecutable. No estudiaremos el principio, pero aún es necesario dominar todo el proceso.

Supongo que te gusta

Origin blog.csdn.net/weixin_61639290/article/details/131735461
Recomendado
Clasificación