[Linux] Compilador de Linux - uso de gcc/g++

Este blog necesita usar el compilador vim. Si no está familiarizado con él, puede consultar el uso de vim en este blog.

1. Antecedentes

Para generar un archivo ejecutable a partir de un archivo fuente, debe pasar por el entorno de traducción del programa (traducir el archivo de texto del programa a un archivo binario que la máquina pueda reconocer), y el entorno de traducción se puede dividir en los siguientes cuatro pasos :

  1. Preprocesamiento (reemplazo de archivos de encabezado, compilación condicional, reemplazo de macros, eliminación de comentarios, etc.)
  2. compilar (generar lenguaje ensamblador)
  3. Ensamblar (genera un binario legible por máquina, no ejecutable, bin.obj)
  4. Vinculación (algún tipo de fusión de nuestros propios archivos .obj y archivos de biblioteca para generar archivos ejecutables)

Para obtener más información, consulte este entorno de programa de blog .

gcc/g++ puede ayudarnos a generar archivos ejecutables C/C++ bajo LInux y ejecutar cuatro pasos diferentes para el entorno de traducción a través de opciones.
gcc compila códigos de lenguaje C y g++ compila códigos de C++. Ambos se usan de la misma manera. A continuación se usa gcc como ejemplo.

2. Cómo generar gcc

Formato:gcc [选项] 要编译的文件 [选项] [目标文件]
primero creamos un archivo de prueba hello.c y usamos el editor vim para escribir el código

[YX@VM-16-5-centos lesson7]$ touch hello.c    //创建hello.c文件
[YX@VM-16-5-centos lesson7]$ vim hello.c      //使用vim编译器编译代码

inserte la descripción de la imagen aquí
Podemos usar gcc directamente para generar el archivo ejecutable del archivo de prueba y
inserte la descripción de la imagen aquí
luego ./a.outejecutar el archivo ejecutable para obtener el resultado de nuestro código,
inserte la descripción de la imagen aquí
pero cuando queremos obtener los archivos generados por él en las cuatro etapas diferentes del entorno de traducción, debemos ¿Cómo implementarlo?

1. Preprocesamiento (reemplazo de macros)

  • Las funciones de preprocesamiento incluyen principalmente el reemplazo de macros, la inclusión de archivos, la compilación condicional y la eliminación de comentarios.
  • Las directivas de preprocesamiento son líneas de código que comienzan con #.
  • Ejemplo: gcc -E hello.c(Esta instrucción es para obtener directamente el contenido preprocesado e imprimirlo en el monitor, lo cual es inconveniente de ver y no se demostrará)
  • Ejemplo: gcc -E hello.c -o hello.i(Coloque el contenido preprocesado en el archivo .i)
  • Opción "-E", la función de esta opción es detener el proceso de compilación después de que se complete gccel preprocesamiento.
  • La opción "-o" significa poner el resultado de la ejecución anterior en el siguiente archivo, y el archivo ".i" es el programa C original que ha sido preprocesado.
  • Nota: El nombre del archivo se puede elegir a voluntad, esto no lo afecta, pero es mejor seguir las reglas y escribirlo como un archivo .i, lo mismo es cierto para los siguientes archivos

De acuerdo con las instrucciones anteriores, ejecutamos y generamos archivos preprocesados
inserte la descripción de la imagen aquí
​​Nota: los archivos .i no son archivos ejecutables, no podemos usarlos para ./hello.iejecutarlos, pero se pueden ver a través del editor vim

Finalmente se puede ver el contenido del archivo.

inserte la descripción de la imagen aquí
Ya sabemos cómo ver los archivos generados por el preprocesamiento, pero el caso anterior no demuestra completamente el efecto del preprocesamiento. Aquí primero modificamos el archivo de prueba y luego generamos el archivo .i para ver los resultados, y podemos sentir claramente el preprocesamiento El papel de lo siguiente:

inserte la descripción de la imagen aquí

  • Para el archivo .i, podemos ver que tiene líneas 860, mientras que el archivo .c tiene solo líneas 24. El código redundante en el archivo .i es el código incluido en el archivo de encabezado

2. Compilar (generar ensamblado)

  • En esta etapa, gcc primero debe verificar la estandarización del código, si hay errores gramaticales, etc., para determinar el trabajo real del código, y luego de que la verificación sea correcta, gcc traduce el código a lenguaje ensamblador.
  • Los usuarios pueden usar la opción "-S" para ver, esta opción solo compila pero no ensambla y genera código ensamblador.
  • Ejemplo: gcc -S hello.c(genere directamente el contenido compilado del archivo .c, muéstrelo en el monitor y vuelva a someterse al preprocesamiento, no se recomienda usar de esta manera)
  • Ejemplo: gcc -S hello.i -o hello.s(Esta instrucción es para generar un archivo .s a partir de un archivo .i)
  • Ejemplo: gcc -S hello.c -o hello.s(También es posible generar directamente un archivo .s a partir de un archivo .c y volver a someterse a un preprocesamiento)
  • Los archivos ".s" son programas compilados en C originales

Aquí generamos directamente el archivo .i en el archivo .s

inserte la descripción de la imagen aquí

Después de abrir, puede ver claramente el código ensamblador que genera

inserte la descripción de la imagen aquí

3. Ensamblaje (generación de código legible por máquina)

  • La etapa de ensamblaje consiste en convertir el archivo ".s" generado en la etapa de compilación en un archivo de objeto.
  • Aquí puede usar la opción "-c" para ver que el código de ensamblaje se ha convertido en el código de objeto binario de ".o"
  • Ejemplo: gcc -c hello.c(igual que arriba, generar directamente datos compilados y mostrarlos en el monitor)
  • Ejemplo: gcc -c hello.c -o hello.o(igual que arriba, comenzando desde el archivo .c y reprocesando, compilando y ensamblando)
  • Ejemplo: gcc -c hello.s -o hello.o(del archivo compilado para generar el archivo ensamblado)

Aquí generaremos el archivo .o compilado a partir del archivo .s

inserte la descripción de la imagen aquí
Después de abrir, lo que vemos es que la máquina puede leer otros códigos, que no podemos entender

inserte la descripción de la imagen aquí

4. Enlace (generar archivo ejecutable o archivo de biblioteca)

  • Después de una compilación exitosa, ingresa a la fase de vinculación.
  • Ejemplo: gcc hello.c -o hello(Desde el archivo .c pasando por el entorno de traducción hasta el enlace)
  • Ejemplo: gcc hello.o -o hello(El archivo .o generado por ensamblaje genera un archivo vinculado)
  • El archivo vinculado es un archivo ejecutable, que se puede ejecutar directamente para ./helloobtener el resultado del programa

Usamos archivos .o para generar archivos vinculados

inserte la descripción de la imagen aquí

Ver el contenido del ejecutable

inserte la descripción de la imagen aquí
código legible por máquina

pregunta

Dado que el contenido de los archivos generados después del ensamblaje y la vinculación son códigos reconocibles por máquina, ¿se pueden ejecutar los archivos generados después del ensamblaje?

Realicemos operaciones en él primero:
inserte la descripción de la imagen aquí
descubra que el archivo no tiene permisos de ejecución, agréguelo y ejecute:

inserte la descripción de la imagen aquí

Conclusión: Incluso si un archivo tiene un programa ejecutable, si no es un archivo ejecutable, no hay forma de ejecutarlo, y prueba que .oel archivo no se puede ejecutar

Úselo para chmod -x hello.orevocar sus permisos ejecutables.

3. Biblioteca de funciones

En la fase de vinculación, vinculamos el archivo de biblioteca, entonces, ¿qué es un archivo de biblioteca? Esto se explicará en detalle.

La razón por la que el programa C/C++ que escribimos puede ejecutarse en el compilador es porque nuestro compilador convierte el programa en un programa ejecutable a través del entorno de traducción y finalmente genera el resultado.

Además del código que escribimos, los programas que escribimos también llaman a las funciones proporcionadas en los archivos de encabezado. Por ejemplo, las funciones que usamos con frecuencia se declaran printf、scanfen los archivos de encabezado stdio.h. Estos archivos de encabezado se almacenan en /usr/includedirectorios y subdirectorios en Linux. :

inserte la descripción de la imagen aquí
Dado que la declaración de estas funciones se coloca en el archivo de encabezado, ¿dónde se definen?

Sabemos que el entorno de traducción se divide en cuatro pasos, la función del último paso 链接es combinar los archivos generados después del ensamblaje con los archivos de biblioteca, y las funciones declaradas en los archivos de encabezado se almacenan en los archivos de biblioteca.

En el sistema Linux, todas estas implementaciones de funciones se implementarán en libc.so.6el archivo de biblioteca nombrado. Si no hay una instrucción especial, gcc buscará en la ruta de búsqueda predeterminada del sistema “/usr/lib”, es decir, vinculará a la libc.so.6función de biblioteca. Esto habilita la función "printf" o lo que sea, y eso es lo que hace la vinculación.

inserte la descripción de la imagen aquí
Por ejemplo, echemos un vistazo al archivo ejecutable a.fuera del archivo de prueba hello.c escrito arriba, y veamos el archivo de biblioteca al que se vincula. Aquí necesitamos usar lddinstrucciones para verlo.

inserte la descripción de la imagen aquí
De hecho, cuando instalamos compiladores como vs2019 y vs2022, la tarea más importante es ayudarnos a descargar e instalar los archivos de encabezado de idioma y los archivos de biblioteca.

Entonces podemos concluir que la biblioteca de funciones en sí misma es un archivo, que se usa para definir y almacenar funciones.

1. Clasificación de bibliotecas de funciones

Existen dos tipos de bibliotecas de funciones, bibliotecas estáticas y bibliotecas dinámicas, sus diferencias son las siguientes:

(1) Biblioteca dinámica

nombre:libXXXXX.so

Entre ellos, XXXXX puede ser cualquier nombre, como el archivo de biblioteca utilizado anteriormente libc.so.6, es una biblioteca dinámica. Elimine el prefijo lib y el sufijo .so cpara mostrar que es una biblioteca escrita en lenguaje c, y el .6 restante representa el número de versión.

El papel de la biblioteca dinámica: el archivo de la biblioteca de enlaces dinámicos, en la etapa de enlace, copie la dirección del código que necesitamos en la biblioteca dinámica a la ubicación relevante en nuestro propio programa ejecutable, y llame a la función en la biblioteca dinámica a través del Dirección al ejecutar el programa para garantizar que el código de funcionamiento normal.

Cuando el código que escribimos está vinculado, si no se especifica, el vínculo predeterminado es la biblioteca dinámica.

(2) biblioteca estática

nombre:libXXXXX.a

Como arriba, lib es el prefijo, .a es el sufijo y cualquier nombre puede estar en el medio

El papel de la biblioteca estática: el archivo de biblioteca de enlaces estáticos, al compilar y vincular, copie el código que necesitamos en la biblioteca estática al archivo ejecutable, por lo que el archivo generado es relativamente grande, pero el archivo de biblioteca ya no es necesario en tiempo de ejecución .

Por ejemplo: cuando escribimos un programa, la printffunción puede aparecer más de una vez, luego cada printffunción se reemplazará con el código correspondiente en la biblioteca estática, lo que hará que el archivo sea más grande y las printffunciones reemplazadas muchas veces desperdician espacio.

Los enlaces estáticos deben ser enlazados por nosotros mismos. El método de enlace es el siguiente:

  1. Podemos usar el filecomando para verificar si el archivo ejecutable está vinculado a una biblioteca dinámica o estática, o usar el lddcomando para verificar el nombre de la biblioteca de enlaces y juzgar según el nombre.
    inserte la descripción de la imagen aquí

  2. gcc hello.c -o hello-static -staticHaga que el hello-staticejecutable resultante esté vinculado estáticamente a través de una directivainserte la descripción de la imagen aquí

    • Es normal que los archivos después del enlace estático y el enlace dinámico difieran aproximadamente 10 veces
  3. Estoy usando un servidor en la nube. Por defecto, solo hay bibliotecas dinámicas. Necesitamos instalar manualmente bibliotecas estáticas para usarlas. El método es el siguiente:

     sudo yum install -y glibc-static   //在普通用户下安装c语言静态库
    yum install -y glibc-static        //在root用户下安装c语言静态库
    
    sudo yum install -y glibc-static libstdc++-static    //在普通用户下安装c++静态库
    yum install -y glibc-static libstdc++-static    //在root用户下安装c++静态库
    

2. Diferencia

La biblioteca dinámica llama a la función correspondiente en la biblioteca dinámica a través de la dirección correspondiente al código de la biblioteca dinámica en el programa para completar la ejecución del código.Si la biblioteca dinámica desaparece repentinamente, el programa ejecutable no podrá ejecutarse.

La biblioteca estática encuentra la función correspondiente en la biblioteca a través de la dirección generada por el nombre de la función, la copia en el archivo ejecutable y la llama en el archivo, lo que hace que el archivo ejecutable ejecute código incluso sin una biblioteca estática, pero con la copia , Los ejecutables también aumentan de tamaño.

3. Expansión

Las instrucciones que usamos en Linux están todas escritas en lenguaje C. Podemos revisar las bibliotecas de enlaces de diferentes instrucciones para ver si están escritas en lenguaje C, de la siguiente manera:

Vea el archivo de biblioteca del comando ls:

inserte la descripción de la imagen aquí
Ver el archivo de biblioteca del comando which:

inserte la descripción de la imagen aquí

Así que las instrucciones son programas.

  • Este es el único conocimiento sobre la biblioteca de funciones en este blog, y se explicará más contenido en E/S básica.

4. Memoria

1. Opciones

En los cuatro pasos del entorno de traducción, usamos -oopciones, y solo usamos enlaces.Podemos recordar los -otres pasos restantes a través del botón en la esquina superior izquierda del teclado .Esc

Preprocesamiento—— -E, compilación—— -S, compilación——c

Si lo olvidamos, solo tenemos que mirar el Escbotón en la esquina superior izquierda del teclado, pero tenga en cuenta que Ey Sestán en mayúscula.

2. Sufijo

El archivo generado por el enlace no tiene sufijo y no necesita ser memorizado, y los otros tres corresponden al sufijo del archivo de imagen en orden.iso

Opciones de Five.gcc

Entre las opciones de gcc, las opciones más utilizadas son las opciones de los cuatro pasos anteriores del entorno de traducción, que se resumen y se ponen aquí junto con otras opciones para su comodidad.

  • -E solo activa el preprocesamiento, esto no produce un archivo, necesita ser redirigido a un archivo de salida.
  • -S Compilar en lenguaje ensamblador No ensamblar y vincular.
  • -c Compilar en código objeto.
  • -o archivo Salida a archivo.
  • -static Esta opción vincula estáticamente los archivos generados.
  • -g Genera información de depuración. El depurador GNU puede aprovechar este mensaje.
  • -shared Esta opción intentará usar la biblioteca dinámica, por lo que el archivo generado es relativamente pequeño, pero el sistema necesita la biblioteca dinámica.
  • -O 0
  • -O 1
  • -El 2
  • -O 3 Los 4 niveles de opciones de optimización del compilador, -O0 significa que no hay optimización, -O1 es el valor predeterminado y -O3 tiene el nivel de optimización más alto.
  • -w No genera ningún mensaje de advertencia.
  • -Wall Generar todos los mensajes de advertencia.

Supongo que te gusta

Origin blog.csdn.net/m0_52094687/article/details/128608256
Recomendado
Clasificación