La creación y el uso de la biblioteca de enlaces estáticos C (C ++) compilada por GCC (gcc -L, gcc -l) y la biblioteca de enlaces dinámicos (gcc -fPIC -shared)

1. Archivos de biblioteca

El llamado archivo de biblioteca, los lectores pueden ser equivalentes a un archivo de paquete comprimido, el archivo generalmente contiene más de un archivo de objeto (es decir, un archivo binario).

Vale la pena mencionar que el código almacenado en cada archivo objeto en el archivo de la biblioteca no es un programa completo, sino un módulo funcional práctico. Por ejemplo, una Cbiblioteca de lenguaje proporciona una serie de funciones (tales como scanf(), printf(), strlen()etc.), C++funciones de biblioteca proporcionar no sólo tienen que utilizar, hay un gran número de clases de pre-diseñadas (tales como stringclase String).

La generación del archivo de biblioteca mejora en gran medida la eficiencia de desarrollo del programador, porque muchas funciones no necesitan ser desarrolladas desde 0 en absoluto, simplemente llame al archivo de biblioteca que contiene la función directamente. Además, llamar al método de la biblioteca también es muy simple para la función de salida del Cidioma printf(), por ejemplo, el programa acaba de introducir <stdio.h>el archivo de encabezado, puede llamar a la printf()función.

¿Por qué está involucrado el archivo de encabezado cuando se llama al archivo de biblioteca? En primer lugar, los archivos de encabezado y los archivos de biblioteca no son lo mismo. La mayor diferencia entre ellos es:

  • El archivo de encabezado solo almacena la parte de declaración de estos módulos funcionales como variables, funciones o clases;
  • El archivo de la biblioteca es responsable de almacenar las partes de implementación específicas de cada módulo;

Los lectores pueden entender de esta manera: todos los archivos de la biblioteca se proporcionan con los archivos de encabezado correspondientes como interfaz para llamarlos. En otras palabras, los archivos de biblioteca no se pueden usar directamente y solo se pueden llamar indirectamente a través de archivos de encabezado.

La mayor ventaja del mecanismo de acceso combinado de archivos de encabezado y archivos de biblioteca es que a veces solo queremos que otros usen las funciones que hemos implementado y no queremos revelar el código fuente de las funciones. Podemos convertirlos en archivos de biblioteca, por lo que que los usuarios pueden obtener Es un archivo binario, y el archivo de encabezado solo contiene la parte de declaración, por lo que el propósito de "ocultar el código fuente" se realiza sin afectar el uso del usuario.

De hecho, los archivos de la biblioteca son solo un término general, que se refiere a un tipo de paquete comprimido, todos contienen archivos de objetos funcionales y prácticos. Debe saber que aunque el archivo de la biblioteca se utiliza en la fase de vinculación del programa, el compilador proporciona dos formas de lograr la vinculación, que se denominan vinculación estática y vinculación dinámica.

  • Los archivos de biblioteca que utilizan enlaces estáticos para lograr operaciones de enlace se denominan bibliotecas de enlaces estáticos;
  • Un archivo de biblioteca que utiliza vínculos dinámicos para lograr operaciones de vinculación se denomina biblioteca de vínculos dinámicos;

En C, C++el proceso de desarrollo real, además de utilizar los archivos de la biblioteca del sistema, podemos crear una biblioteca de vínculos estáticos o DLL de acuerdo a las necesidades reales, de forma manual.

2. Biblioteca de enlaces estáticos

La biblioteca de enlaces estáticos realiza la operación del enlace de una manera muy simple, es decir, cuando el módulo de función del archivo de la biblioteca se utiliza en el archivo del programa, el GCCcompilador copiará directamente el código de la plantilla en la ubicación adecuada del archivo del programa y finalmente generar un archivo ejecutable.

El uso de archivos de biblioteca estática para implementar operaciones de vinculación de programas tiene ventajas y desventajas:

  • La ventaja es que el archivo ejecutable generado se puede ejecutar de forma independiente sin el soporte de ningún archivo de biblioteca estático (portabilidad fuerte);
  • La desventaja es que si se llama varias veces al mismo módulo de función de la biblioteca en el archivo de programa, el código del módulo se copiará inevitablemente varias veces y el archivo ejecutable generado contendrá varias piezas de código idéntico, lo que provocará la redundancia del código.

En comparación con el archivo ejecutable generado por la biblioteca de vínculos dinámicos, el archivo ejecutable generado por la biblioteca de vínculos estáticos tiene un volumen mayor.

  • En la Linuxversión de lanzamiento del sistema, la extensión de los archivos de la biblioteca de enlaces estáticos generalmente .arepresentan;
  • En el Windowssistema, el sufijo nombre de archivo de biblioteca de vínculos estáticos .lib;

2.1 Crear una biblioteca de enlaces estáticos

Una biblioteca de enlaces estáticos es en realidad equivalente a un paquete comprimido, que puede contener varios archivos fuente. Pero debe tenerse en cuenta que no se puede procesar ningún archivo fuente en una biblioteca de enlaces estáticos, debe cumplir al menos las dos condiciones siguientes:

  • Los archivos de origen solo proporcionan que el código se puede reutilizar, como funciones, etc. diseñadas, no pueden contener mainla función principal;
  • Si bien el archivo fuente realiza la función del módulo, también proporciona una interfaz para acceder a él, es decir, el archivo de encabezado que contiene la parte de declaración de cada módulo de función;

Estructura de código de muestra:

wohu@ubuntu:~/cpp/src$ tree
.
├── function.h
├── greeting.cpp
├── main.cpp
└── name.cpp

0 directories, 4 files
wohu@ubuntu:~/cpp/src$ 

function.h Código

void sayGreetings();
void sayName();

greeting.cppEl código que lo contiene #include "function.h"no necesita incluir el archivo de encabezado cuando no se crea la biblioteca estática.

#include <iostream>
#include "function.h"

void sayGreetings()
{
    
    
    std::cout << "hello,world" << std::endl;
}

name.cppEl código, que está incluido #include "function.h", no necesita incluir el archivo de encabezado cuando no se crea la biblioteca estática.

#include <iostream>
#include "function.h"

void sayName()
{
    
    
    std::cout << "My name is wohu" << std::endl;

}

main.cpp Código

#include <iostream>
#include "function.h"

int main()
{
    
    
    sayGreetings();
    sayName();
    return 0;
}

Para name.cppy greeting.cppestán en línea con las dos condiciones anteriores, se puede procesar en una biblioteca de enlaces estáticos. Y de acuerdo con las necesidades reales, podemos comprimirlos colectivamente en una biblioteca de enlaces estáticos, o cada uno puede comprimirse en una biblioteca de enlaces estáticos.

El proceso de empaquetar el archivo fuente como una biblioteca de enlaces estáticos es muy simple, solo siga los siguientes 2 pasos:

  1. Compile todos los archivos de origen especificados en los archivos de destino correspondientes
wohu@ubuntu:~/cpp/src$ g++ -c greeting.cpp  name.cpp 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 
  1. Luego, usando arinstrucciones comprimidas, los archivos de objetos generados en una biblioteca de enlaces estáticos, el formato básico es el siguiente:
ar rcs 静态链接库名称 目标文件1 目标文件2 ...

Acerca de arlas instrucciones de empaquetado de compresión, así como rcsel significado y la función de cada opción, consulte el comando ar de Linux

El punto importante es que la biblioteca de enlaces estáticos no se puede nombrar arbitrariamente y se deben seguir las siguientes reglas de nomenclatura:

libxxx.a
  • LinuxEn el sistema, el sufijo de la biblioteca de enlaces estáticos es .a;
  • WindowsEn el sistema, el sufijo de la biblioteca de enlaces estáticos es .lib;

Entre ellos, xxxen nombre de los que jugamos para el nombre de la biblioteca, tales como Linuxel sistema viene con algún nombre de la biblioteca de vínculos estáticos libc.a,, libgcc.a, libm.asus nombres son c, gccy m.

A continuación, empaque greeting.oy name.oempaque en una biblioteca de enlaces estáticos:

wohu@ubuntu:~/cpp/src$ ar rcs libmyfunction.a name.o greeting.o 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

Entre ellos, libmyfunction.aes decir name.o, greeting.oempaquetados juntos generaron biblioteca de enlaces estáticos, myfunctionun nombre de biblioteca personalizado.

2.2 Usar biblioteca de enlaces estáticos

El uso de la biblioteca de vínculos estáticos es muy simple, es decir, en la etapa de vinculación del programa, la biblioteca de vínculos estáticos y otros archivos objeto se vinculan entre sí para generar un archivo ejecutable.

Usando el código anterior como ejemplo, primero el main.cpparchivo se compilará en archivos de objeto:

wohu@ubuntu:~/cpp/src$ g++ -c main.cpp 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

Sobre esta base, podemos ejecutar directamente los siguientes comandos para completar la operación del enlace:

wohu@ubuntu:~/cpp/src$ g++ -static main.o libmyfunction.a 
wohu@ubuntu:~/cpp/src$ ls
a.out  function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

Entre ellos, -staticla opción de obligar GCCal compilador a utilizar una biblioteca de enlaces estáticos.

Tenga en cuenta que si GCCel compilador no puede encontrar los consejos libmyfunction.a, también puede utilizar el siguiente enlace. Se realiza la operación:

wohu@ubuntu:~/cpp/src$ g++ -static main.o -L /home/wohu/cpp/src -lmyfunction
wohu@ubuntu:~/cpp/src$ ls
a.out  function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  main.o  name.cpp  name.o

entre ellos,

  • -LLa Lopción (mayúsculas ) se usa para GCCespecificar la ubicación de almacenamiento de la biblioteca de enlaces del compilador estático (puede usar el comando pwd para ver la ubicación de almacenamiento específica);
  • -l(Lowercase Lopción) se utiliza para indicar el nombre de la biblioteca de enlace estática requerida, prestar atención a los nombres utilizados en esta memoria se refiere a la xxxparte, y recomendará -ly xxxconjunción directa (es decir -lxxx), sin espacios intermedios.

Como resultado, genera a.outun archivo ejecutable:

wohu@ubuntu:~/cpp/src$ ./a.out 
hello,world
My name is wohu
wohu@ubuntu:~/cpp/src$ 

3. Biblioteca de vínculos dinámicos

Biblioteca de vínculos dinámicos, también conocida como biblioteca de vínculos compartidos. A diferencia de la biblioteca de enlaces estáticos, cuando se utiliza la biblioteca de enlaces dinámicos para realizar la operación del enlace, donde se necesita el módulo de función del archivo de la biblioteca en el archivo de programa, el GCCcompilador no copiará directamente el código del módulo de función al archivo, pero la información de ubicación del módulo de función Grabe en el archivo y genere directamente el archivo ejecutable.

Obviamente, el archivo ejecutable generado de esta manera no puede ejecutarse de forma independiente. Cuando se ejecuta el archivo ejecutable generado por la biblioteca de vínculos dinámicos, el GCCcompilador cargará la biblioteca de vínculos dinámicos correspondiente en la memoria juntos. Dado que la información de posición del módulo de función requerido se registra en el archivo ejecutable de antemano, la biblioteca de vínculos dinámicos existente También se puede ejecutar con éxito con el apoyo de.

Las ventajas y desventajas de usar la biblioteca de enlaces dinámicos para realizar la operación de conexión del programa son exactamente opuestas a las de la biblioteca de enlaces estáticos:

  • La ventaja es que debido a que el archivo ejecutable registra la dirección del módulo de función, el código de implementación real se cargará en la memoria cuando el programa se esté ejecutando, lo que significa que incluso si el módulo de función se llama varias veces, el mismo código de implementación es utilizado (Esta es también la razón por la que la biblioteca de vínculos dinámicos se denomina biblioteca de vínculos compartidos).
  • La desventaja es que el archivo ejecutable generado por este método no se puede ejecutar de forma independiente y se debe utilizar el archivo de biblioteca correspondiente (poca portabilidad).

En comparación con el archivo ejecutable generado por la biblioteca de vínculos estáticos, el archivo ejecutable generado por la biblioteca de vínculos dinámicos tiene un volumen más pequeño, porque un montón de códigos redundantes no se copiarán en su interior.

  • En la Linuxversión de lanzamiento del sistema, la biblioteca de vínculos dinámicos de extensión suele estar .sorepresentada;
  • En el Windowssistema, la biblioteca de vínculos dinámicos de sufijos denominada .dll;

GCCCuando el compilador genera un archivo ejecutable, dará prioridad al uso de la biblioteca de vínculos dinámicos para lograr la operación del vínculo de forma predeterminada. A menos que no exista una biblioteca de vínculos dinámicos requerida por el archivo de programa en el entorno del sistema actual, el GCCcompilador seleccionará la biblioteca de enlaces estáticos correspondiente. Si no se encuentran ambos (o GCCno se encuentra el compilador), el enlace falla.

3.1 Crear una biblioteca de enlaces dinámicos

En general, hay dos formas de crear una biblioteca de vínculos dinámicos.

  1. La creación directa de archivos fuente de biblioteca de vínculos dinámicos, utilizando el gccformato básico del comando, se implementa de la siguiente manera:
gcc -fpic -shared 源文件名... -o 动态链接库名

entre ellos,

  • -shared La opción se utiliza para generar una biblioteca de enlaces dinámicos;
  • -fpicLa -fPICopción (también escrita como función) es hacer que GCCel compilador genere una biblioteca de vínculos dinámicos (archivar varios archivos de objeto), indica la dirección de cada función de archivo de objeto, las clases y otros módulos funcionales usan una dirección relativa, en lugar de una dirección absoluta. De esta manera, no importa dónde se cargue la biblioteca de enlaces en la memoria en el futuro, se puede usar normalmente.

Por ejemplo, al frente del proyecto greeting.cpp, name.cppestos dos archivos fuente para generar una biblioteca de vínculos dinámicos, ejecute el comando de la siguiente manera:

wohu@ubuntu:~/cpp/src$ g++ -fPIC -shared name.cpp  greeting.cpp  -o libmyfunction.so 
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  libmyfunction.a  libmyfunction.so  main.cpp  name.cpp
wohu@ubuntu:~/cpp/src$ 

Tenga en cuenta que el nombre de las bibliotecas de vínculos dinámicos y las bibliotecas vinculadas estáticamente son idénticos, pero en el Linuxsistema de lanzamiento, su extensión con .sorepresentación; Windowssufijo del sistema .dll.

  1. Primero use las gcc -cinstrucciones para especificar que los archivos de origen se compilan en archivos de objeto y luego cree un archivo de biblioteca de vínculos dinámicos desde el destino

Tenga en cuenta que cuando el seguimiento para generar una biblioteca de vínculos dinámicos y se puede utilizar normalmente, los archivos de origen se compilan en archivos de objeto, también es necesario utilizar la -fpicopción.

wohu@ubuntu:~/cpp/src$ g++ -c -fPIC name.cpp greeting.cpp  
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

Sobre esta base, utilice el archivo objeto generado en el paso anterior para generar una biblioteca de vínculos dinámicos:

wohu@ubuntu:~/cpp/src$ g++ -shared greeting.o name.o -o libmyfunction.so
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  libmyfunction.so  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

3.2 Usar biblioteca de enlaces dinámicos

A través del estudio de los capítulos anteriores, sabemos que el escenario de uso de la biblioteca de vínculos dinámicos es participar en la vinculación con otros archivos fuente o archivos de destino en el proyecto. Usando el ejemplo anterior, por ejemplo, estaremos al frente greeting.cpp, name.cppempaquetados en una libmyfunction.sobiblioteca de enlaces dinámicos, en cuyo caso el proyecto quedó como main.cpparchivos fuente, por lo que evolucionó hacia la implementación del proyecto de demostración main.cppy el libmyfunction.soenlace, y luego generaremos un archivo ejecutable.

Tenga en cuenta que el archivo de encabezado function.h no participa directamente en la compilación, porque en la etapa de preprocesamiento del programa, se han procesado los archivos de encabezado que deben usarse en el proyecto.

Ejecute las siguientes instrucciones para generar con éxito un archivo ejecutable con la ayuda de la biblioteca de vínculos dinámicos:

wohu@ubuntu:~/cpp/src$ g++ main.cpp  libmyfunction.so -o main
wohu@ubuntu:~/cpp/src$ ls
function.h  greeting.cpp  greeting.o  libmyfunction.a  libmyfunction.so  main  main.cpp  name.cpp  name.o
wohu@ubuntu:~/cpp/src$ 

Tenga en cuenta que los archivos ejecutables generados maingeneralmente no se pueden implementar directamente, como:

wohu@ubuntu:~/cpp/src$ ./main 
./main: error while loading shared libraries: libmyfunction.so: cannot open shared object file: No such file or directory
wohu@ubuntu:~/cpp/src$ 

Podemos ver, el proceso de implementación no puede encontrar libmyfunction.sola biblioteca de enlaces dinámicos. Al ejecutar la ldd maininstrucción, puede ver todo el archivo de biblioteca de vínculos dinámicos que se encuentra actualmente en la implementación que necesita usar, así como la ubicación de almacenamiento de cada archivo de biblioteca:

wohu@ubuntu:~/cpp/src$ ldd main 
        linux-vdso.so.1 =>  (0x00007fffb17ea000)
        libmyfunction.so => not found
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f548673a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5486370000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5486067000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5486abc000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f5485e51000)
wohu@ubuntu:~/cpp/src$ 

Como puede ver, mainel archivo ejecutable necesita el soporte de siete bibliotecas de vínculos dinámicos, incluida libmyfunction.so, pero el archivo no se puede encontrar, por lo que mainla implementación fallará.

Al ejecutar el archivo ejecutable generado por la biblioteca de vínculos dinámicos, debe asegurarse de que el programa pueda encontrar la biblioteca de vínculos dinámicos cuando se esté ejecutando. Las soluciones más utilizadas son las siguientes:

  • El archivo de biblioteca de vínculos con el directorio de la biblioteca estándar (por ejemplo /usr/lib, /usr/lib64, /lib, /lib64);
  • Escribe la terminal
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx

Donde xxxla ruta absoluta almacenada en el archivo de biblioteca de enlace dinámico (en esta realización solo es válida en el terminal actual, el terminal no es válido después del cierre);

  • Modificar ~/.bashrco ~/.bash_profilearchivar, el archivo se agrega en la última línea
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:xxx

Que xxx, después de una ruta absoluta al almacenamiento de archivos de la biblioteca de vínculos dinámicos, preservación, ejecute el source bashrccomando (de esta manera solo el usuario registrado actual es válido).

En este ejemplo se utiliza la segunda opción, que es ingresar en la terminal

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wohu/cpp/src

Para la mainimplementación exitosa.

wohu@ubuntu:~/cpp/src$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wohu/cpp/src
wohu@ubuntu:~/cpp/src$ ldd main 
        linux-vdso.so.1 =>  (0x00007ffddc5fa000)
        libmyfunction.so (0x00007f017bec9000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f017bb47000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f017b77d000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f017b474000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f017c0cb000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f017b25e000)
wohu@ubuntu:~/cpp/src$ ./main 
hello,world
My name is wohu
wohu@ubuntu:~/cpp/src$ 

Supongo que te gusta

Origin blog.csdn.net/wohu1104/article/details/110789570
Recomendado
Clasificación