[Linux] Bibliotecas dinámicas y estáticas

[Linux] Bibliotecas dinámicas y estáticas

jianyijianku

En los sistemas Linux, la biblioteca estándar C y otras bibliotecas de uso común se denominan bibliotecas C y generalmente se almacenan en el directorio /usr/libo :/usr/lib64

imagen-20230907132423757

En los sistemas Linux, /usr/includemuchos archivos de encabezado se almacenan en el directorio:

imagen-20230907132557509

  • El sistema Linux está preinstalado con archivos de encabezado y archivos de biblioteca C/C++. Los archivos de encabezado proporcionan descripciones de los métodos y los archivos de biblioteca proporcionan la implementación de los métodos. Los archivos de encabezado y los archivos de biblioteca tienen una relación correspondiente y deben utilizarse en combinación.
  • En el proceso de compilación de un programa para formar un programa ejecutable, los archivos de encabezado se introducen durante el preprocesamiento y los archivos de la biblioteca se vinculan durante la vinculación.
  • Al instalar el entorno de desarrollo en Visual Studio, no solo se instala el software compilador, sino también los archivos de encabezado y los archivos de biblioteca correspondientes al idioma.
  • El compilador buscará automáticamente contenido relevante en el archivo de encabezado según la entrada del usuario e implementará la función de solicitud de sintaxis.
  • El compilador compilará automática y continuamente en función de la entrada del usuario para implementar la función de informar errores de sintaxis.

La razón por la que existe la biblioteca.

El lenguaje de programación agrega funciones de uso común a la biblioteca para que los usuarios puedan usar estas funciones directamente y mejorar la eficiencia del desarrollo. Por ejemplo printf, los usuarios no necesitan escribir una función para imprimir datos cada vez que quieran imprimir datos.

Escribiendo una biblioteca

Simular la escritura de bibliotecas estáticas

Antes de escribir la biblioteca, explique:

  • Las bibliotecas se dividen en bibliotecas dinámicas y bibliotecas estáticas.
  • Reglas de nomenclatura para bibliotecas estáticas en Linux:lib库名.a
  • Reglas de nomenclatura para bibliotecas dinámicas en Linux:lib库名.so
  • Los servicios en la nube generalmente no tienen bibliotecas estáticas integradas.
  1. Escribir archivos de encabezado y archivos fuente

Escriba el archivo de encabezado myadd.h y su archivo fuente correspondiente myadd.c y el archivo de encabezado mysub.h y su archivo fuente correspondiente mysub.c. Los códigos específicos en cada archivo son los siguientes:

//myadd.h
#pragma once 

int my_add(int x, int y);

//myadd.c
#include "myadd.h" 

int my_add(int x, int y)//一个简单的加法函数
{
    
    
  return x + y;
}
//mysub.h
#pragma once 

int my_sub(int x, int y);

//mysub.c
#include "mysub.h" 

int my_sub(int x, int y)//一个简单的减法函数
{
    
    
  return x - y; 
}
  1. Compilar archivos de origen en archivos de destino

gcc -c 源文件名Compile archivos de origen en archivos de destino usando :

imagen-20230907162247874

  1. Empaquetado en una biblioteca estática

Úselo ar -rc lib库名.a 目标文件para empaquetar el archivo de destino en una biblioteca estática:

imagen-20230907162355901

  1. Estructura del directorio de archivos de la biblioteca de simulación

Cree el directorio de inclusión y mueva los archivos de encabezado a este directorio, cree el directorio lib y mueva las bibliotecas estáticas a este directorio:

imagen-20230907162516768

  1. Empaquetar la biblioteca en un paquete comprimido

Úselo tar -czf 目标压缩包名 源文件para empaquetar la biblioteca en un paquete comprimido:

imagen-20230907162735301

Simular el uso de bibliotecas estáticas.

  1. Copie el paquete comprimido de la biblioteca estática empaquetado en la operación anterior en un directorio determinado y descomprímalo para simular el proceso de descarga de la biblioteca.

imagen-20230907164341754

  1. Cree el archivo fuente main.c en el directorio actual y escriba el código para llamar a la biblioteca estática. El código específico se implementa de la siguiente manera:
#include <stdio.h>
#include "myadd.h"
#include "mysub.h"

int main()
{
    
    
  int x = 20;
  int y = 10;
  printf("%d + %d = %d\n", x, y, my_add(x, y));
  printf("%d - %d = %d\n", x, y, my_sub(x, y));
  return 0;
}
  1. Compile el archivo fuente main.c en un programa ejecutable:

imagen-20230907165017051

Dado que el archivo de encabezado de terceros no está en el directorio compilado, -I 路径se requiere una opción para especificar la ruta del archivo de encabezado. Dado que el compilador de la biblioteca de terceros no lo encontrará ni lo usará por sí mismo, -L 路径el nombre de la ruta del archivo de la biblioteca y -l 库名el nombre de la biblioteca es necesario especificar.

Resuma el uso de bibliotecas de terceros en sistemas Linux:

  • Debe especificar la ruta del archivo de encabezado y la ruta y el nombre del archivo de la biblioteca.
  • Si los archivos de encabezado y los archivos de la biblioteca no están instalados en la ruta predeterminada buscada por el compilador, el usuario debe especificar las opciones correspondientes:
    • Ruta del archivo de encabezado ( -I 路径)
    • Ruta del archivo de la biblioteca ( -L 路径)
    • Nombre de la biblioteca ( -l 库名)
  • La esencia de instalar archivos de encabezado y archivos de biblioteca es copiar los archivos a la ruta predeterminada del sistema.
  • Una vez instalados los archivos de encabezado y los archivos de la biblioteca, debe especificar la opción de nombre de la biblioteca al compilar.

Simular la escritura de bibliotecas dinámicas

Al simular la escritura de una biblioteca dinámica, se utilizan el archivo de encabezado myadd.h y su archivo fuente correspondiente myadd.c y el archivo de encabezado mysub.h y su archivo fuente correspondiente mysub.c utilizados en el artículo anterior para empaquetar la biblioteca estática.

  1. Compilar archivos fuente

Al empaquetar una biblioteca dinámica, debe gcc -fPIC -c 源文件名compilar el archivo fuente en un archivo de destino:

imagen-20230907173438259

  1. Empaquetar archivos de destino en bibliotecas dinámicas

Úselo gcc -shared -o lib库名.so 目标文件para empaquetar el archivo de destino en una biblioteca dinámica:

imagen-20230907173847412

  1. Estructura del directorio de archivos de la biblioteca de simulación

Cree el directorio de inclusión y mueva los archivos de encabezado a este directorio, cree el directorio lib y mueva las bibliotecas estáticas a este directorio:

imagen-20230907174146799

  1. Empaquetar la biblioteca en un paquete comprimido

Úselo tar -czf 目标压缩包名 源文件para empaquetar la biblioteca en un paquete comprimido:

imagen-20230907174229960

Simular el uso de bibliotecas estáticas.

  1. Copie el paquete comprimido de la biblioteca dinámica empaquetado en la operación anterior en un directorio determinado y descomprímalo para simular el proceso de descarga de la biblioteca.

imagen-20230907184457085

  1. Cree el archivo fuente main.c en el directorio actual y escriba el código para llamar a la biblioteca estática. El código específico se implementa de la siguiente manera:
#include <stdio.h>
#include "myadd.h"
#include "mysub.h"

int main()
{
    
    
  int x = 20;
  int y = 10;
  printf("%d + %d = %d\n", x, y, my_add(x, y));
  printf("%d - %d = %d\n", x, y, my_sub(x, y));
  return 0;
}
  1. Compile el archivo fuente main.c en un programa ejecutable:

Después de especificar la ruta del archivo de encabezado de la biblioteca dinámica, la ruta del archivo de la biblioteca y el nombre de la biblioteca, el compilador puede compilar correctamente. Dado que es una biblioteca dinámica, cuando el programa se está ejecutando, el sistema operativo debe vincularse a la biblioteca dinámica. de acuerdo con la dirección de la biblioteca dinámica en el programa para ejecutarse correctamente, pero el sistema operativo no se puede encontrar la biblioteca dinámica, lo que resulta en la siguiente situación:

imagen-20230907184623458

  1. Utilice el método de importar variables de entorno para ejecutar el programa (solución temporal)

Al export LD_LIBRARY_PATH=LD_LIBRARAY_PATH:动态库所在目录路径importar la ruta de la biblioteca dinámica a la variable de entorno, el sistema operativo encontrará la biblioteca dinámica de la ruta en la variable de entorno cuando ejecute el programa y lo ejecutará correctamente:

imagen-20230907185214813

Métodos para resolver el problema de que el sistema operativo no puede encontrar la biblioteca dinámica de terceros:

  1. Importar variables de entorno: utilice export LD_LIBRARY_PATH=LD_LIBRARAY_PATH:动态库所在目录路径la ruta de la biblioteca dinámica para importar variables de entorno. Las variables de entorno se recargarán cuando se vuelva a abrir el shell, por lo que es una solución temporal.
  2. Establezca un enlace suave a la biblioteca dinámica en la ruta del sistema: utilícelo para sudo ln -s 动态库路径 /lib64/lib库名.soagregar el enlace suave a la biblioteca dinámica en la ruta del sistema
  3. Modifique el archivo de configuración: /etc/ld.so.conf.d/cree .confun archivo con el sufijo debajo de la ruta, escriba la ruta de la biblioteca estática al archivo y luego utilícelo para que sudo ldconfigel archivo de configuración surta efecto.

Principio de carga de la biblioteca

Principio de carga de biblioteca estática

El proceso de carga de la biblioteca dinámica consiste en copiar directamente la implementación en la biblioteca estática al programa ejecutable durante el proceso de vinculación para formar el programa ejecutable. Por tanto, las bibliotecas estáticas ocupan muchos recursos (disco, memoria, recursos de red).

Principio de carga dinámica de la biblioteca

En primer lugar, cuando se utiliza una biblioteca dinámica para generar un programa ejecutable, durante el proceso de vinculación, solo los símbolos externos que representan métodos en la biblioteca serán reemplazados por las direcciones correspondientes en el programa ejecutable, ya que no existe una implementación específica en el programa ejecutable. , es difícil de ejecutar, el sistema operativo realiza una serie de trabajos. Después de que el programa se carga en la memoria para formar un proceso, el sistema operativo mantiene el bloque de control del proceso, el espacio de direcciones del proceso y la tabla de páginas para él:

imagen-20230908133542761

Después de que el proceso se ejecuta en el método en la biblioteca dinámica, el sistema operativo buscará la asignación en la tabla de páginas y encontrará que lo que está asignado a la memoria es solo una dirección correspondiente en lugar de una implementación de método específica. Busque esta biblioteca dinámica y, de acuerdo con una determinada estrategia, convierta la biblioteca dinámica en una biblioteca dinámica, cargue la biblioteca en la memoria y luego el sistema operativo asigne la biblioteca dinámica cargada en la memoria al área compartida entre el área de la pila y el montón. área en el espacio de direcciones del proceso:

imagen-20230908133642887

Luego, cada vez que el proceso ejecuta un método en la biblioteca, solo necesita saltar al área compartida en el espacio de direcciones del proceso para completar la ejecución del programa:

imagen-20230908133705099

Además, después de cargar la biblioteca en la memoria, cuando el proceso en ejecución posterior necesita ejecutar el método de la biblioteca, no es necesario cargar la biblioteca en la memoria, sino que se crea directamente la asignación del área compartida y luego los métodos. en la biblioteca se utilizan.

Estrategias de abordaje para bibliotecas en programas ejecutables.

Estrategia de abordaje de bibliotecas estáticas en programas ejecutables.

Cuando se forma un programa ejecutable, habrá una dirección lógica en el programa ejecutable. Si se utiliza una biblioteca estática, los métodos de la biblioteca estática en el programa ejecutable también se abordarán y se obtendrá una dirección lógica. Cuando se forma el programa se convierte en un proceso y se ejecuta, solo salta según la dirección lógica.

Estrategia de abordaje de bibliotecas dinámicas en programas ejecutables.

Cuando se forma un programa ejecutable, habrá una dirección lógica en el programa ejecutable. Si se utiliza una biblioteca dinámica, también se abordarán los métodos de la biblioteca dinámica en el programa ejecutable, pero esta dirección es la dirección inicial del método. en la biblioteca. El desplazamiento inicial. Al crear una biblioteca dinámica para obtener el archivo de destino, use gcc para agregarlo y -fPICobtener este desplazamiento de dirección, que se denomina código independiente de la dirección. Cuando el proceso real se está ejecutando, el proceso solo necesita espere el método en la biblioteca, se carga en la memoria y se asigna al área compartida, y luego usa la asignación del área compartida más la dirección de desplazamiento para completar la operación.

Explicar:

  • Cuando el compilador gcc/g++ compila un programa ejecutable, utiliza bibliotecas dinámicas de forma predeterminada.
  • Cuando el compilador gcc/g++ compila un programa ejecutable, al usar -staticla opción se utilizará una biblioteca estática.
  • Cuando el compilador gcc/g++ compila un programa ejecutable, algunas bibliotecas dinámicas no existen y se utiliza un uso mixto de bibliotecas dinámicas.

Supongo que te gusta

Origin blog.csdn.net/csdn_myhome/article/details/132758600
Recomendado
Clasificación