[Linux] Empaquetado de biblioteca estática y dinámica de aprendizaje básico cero


1. Enlaces blandos y duros


Desde la perspectiva del sistema de archivos mencionado anteriormente, la prueba de archivos en la figura a continuación tiene su propio inodo independiente, y la ruta de la prueba del programa ejecutable ( incluido el nombre del archivo ) se almacena en el bloque de datos de bloque correspondiente a su inodo.

inserte la descripción de la imagen aquí

Y si el programa de bin1/bin2/bin3/test se mueve a otra ubicación en este momento, la conexión suave no será válida.
inserte la descripción de la imagen aquí

Un archivo puede tener un vínculo suave o un vínculo fijo, y los cambios en el archivo se sincronizarán con el archivo vinculado.



2. Bibliotecas dinámicas y estáticas


Nombre de la biblioteca :
cancele el prefijo lib, elimine el contenido después de . y el resto es el nombre de la biblioteca.

Enlace dinámico -> Biblioteca dinámica libc.so
Enlace estático -> Biblioteca estática libc.a

Cognición perceptiva:
la vinculación dinámica es similar a pedir dinero a tus padres cada vez que lo pides.
El enlace estático es como una pequeña bóveda en casa que es suya y puede satisfacerla usted mismo.

La compilación Gcc está vinculada dinámicamente de forma predeterminada, y el mismo código del programa vinculado dinámicamente es más pequeño que el programa vinculado estáticamente

//分别生成动静态链接的程序
[ljh@VM-0-11-centos 2.27]$ gcc test.c -o test_dynamic
[ljh@VM-0-11-centos 2.27]$ gcc test.c  -static -o test_static
[ljh@VM-0-11-centos 2.27]$ ll
total 876
-rwxrwxr-x 1 ljh ljh   8360 Feb 27 11:28 a.out
-rw-rw-r-- 1 ljh ljh     27 Feb 27 11:12 log.txt
-rw-rw-r-- 1 ljh ljh     68 Feb 27 11:28 test.c
-rwxrwxr-x 1 ljh ljh   8360 Feb 27 11:29 test_dynamic
-rwxrwxr-x 1 ljh ljh 861288 Feb 27 11:29 test_static

A través del código anterior, podemos encontrar que el programa test_static es mucho más grande que el programa test_dynamic.Las bibliotecas utilizadas por los dos programas son libc.so y libc.a

El comando ldd puede ver la biblioteca dinámica de la que depende el archivo:

[ljh@VM-0-11-centos 2.27]$ ldd test_dynamic 
	linux-vdso.so.1 =>  (0x00007fff813cd000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fa5e59ce000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa5e5d9c000)

Hábitos: en general, para respaldar mejor el desarrollo, tanto las bibliotecas de terceros como las bibliotecas de idiomas deben proporcionar dos bibliotecas, una es una biblioteca estática y la otra es una biblioteca dinámica, lo cual es conveniente para que los programadores generen archivos binarios.

Enlace dinámico vs enlace estático Enlace
dinámico: tamaño pequeño, ahorro de recursos (disco, memoria), una vez que se pierde la biblioteca, el programa no se puede ejecutar.
Enlace estático: gran tamaño, desperdicio de recursos (disco, memoria), tal vez 10 programas ejecutables escritos en lenguaje C, habrá mucho código repetitivo. Pero falta la biblioteca (no instalada), no afecta.



Comprender bibliotecas dinámicas y estáticas.


Concéntrese en empaquetar bibliotecas dinámicas y estáticas y usar bibliotecas dinámicas y estáticas

Biblioteca estática:
Objetivo: Implementar una biblioteca estática para sumas y restas.

Análisis: otros quieren saber qué método requiere la biblioteca que proporciono, por supuesto, podemos enviar todos los .c*, .h a otros, pero si no queremos dar .c hoy , podemos compilar todos los .c en .o , .o* se empaqueta en una biblioteca y luego se coloca en una carpeta con .h para otros.

El código fuente necesita protección de privacidad , el archivo de encabezado puede indicar qué método

Pasos:
1. Escriba archivos .c y .h

[ljh@VM-0-11-centos bin11]$ ll
total 16
-rw-rw-r-- 1 ljh ljh 56 Feb 27 11:55 Add.c
-rw-rw-r-- 1 ljh ljh 53 Feb 27 11:55 Add.h
-rw-rw-r-- 1 ljh ljh 55 Feb 27 11:55 Sub.c
-rw-rw-r-- 1 ljh ljh 53 Feb 27 11:55 Sub.h

2. Usa ar -rc命令打包r:replace para reemplazar, create para crear

Vamos a crear una biblioteca estática llamada mymath a continuación, empaquetarla como una biblioteca y enviarla al par. Tenga en cuenta que el archivo .o está empaquetado.

[ljh@VM-0-11-centos bin11]$ gcc -c *.c

[ljh@VM-0-11-centos bin11]$ ar -rc libmymath.a *.o

[ljh@VM-0-11-centos bin11]$ ll
total 36
-rw-rw-r-- 1 ljh ljh   56 Feb 27 11:55 Add.c
-rw-rw-r-- 1 ljh ljh   53 Feb 27 11:55 Add.h
-rw-rw-r-- 1 ljh ljh 1240 Feb 27 12:31 Add.o
drwxrwxr-x 2 ljh ljh 4096 Feb 27 12:01 lib
-rw-rw-r-- 1 ljh ljh 2920 Feb 27 12:31 libmymath.a
-rw-rw-r-- 1 ljh ljh   55 Feb 27 11:55 Sub.c
-rw-rw-r-- 1 ljh ljh   53 Feb 27 11:55 Sub.h
-rw-rw-r-- 1 ljh ljh 1240 Feb 27 12:31 Sub.o
drwxrwxr-x 3 ljh ljh 4096 Feb 27 12:33 test

[ljh@VM-0-11-centos bin11]$ mkdir lib

[ljh@VM-0-11-centos bin11]$ cp *.h *.a lib

[ljh@VM-0-11-centos bin11]$ tree lib
lib
|-- Add.h
|-- libmymath.a
`-- Sub.h

0 directories, 3 files

Con lib, podemos enviar la lib a otros Creamos una carpeta más en esta máquina para probar.

3. Prueba de biblioteca

[ljh@VM-0-11-centos bin11]$  mkdir test
[ljh@VM-0-11-centos bin11]$ cd test
[ljh@VM-0-11-centos test]$ cp ../lib . -rf



Empaquetado y uso de librerías estáticas


Li Si obtuvo el archivo lib de Zhang Sanfa hoy, revisó el archivo .h que se encuentra dentro y descubrió que Add y Sub estaban implementados. Quería usarlo, así que escribió el siguiente código, pero se informó un error.

[ljh@VM-0-11-centos test]$ vim main.c

[ljh@VM-0-11-centos test]$ cat main.c
#include<stdio.h>
#include"Add.h"
#include"Sub.h"
int main()
{
  printf("%d\n",Add(10,20));
  printf("%d\n",Sub(10,20));
}

[ljh@VM-0-11-centos test]$ gcc main.c -o main
main.c:2:16: fatal error: Add.h: No such file or directory
 #include"Add.h"
                ^
compilation terminated.

[ljh@VM-0-11-centos test]$ pwd
/home/ljh/2.27/bin11/test

No existe tal archivo o directorio, Li Si verificó el motivo, el archivo de encabezado solo se buscará en la ruta predeterminada o en la misma ruta de main.c /home/ljh/2.27/bin11/test, es decir, esta ruta, y .h se coloca /home/ljh/2.27/bin11/test/libdebajo, Li Si lo entiende en este momento, échale un vistazo Después de encontrar el método, encontró que -I ./libgcc
Luego, escribió este código: Li Si vio que se informó el error de enlace, por lo que debe haber encontrado el archivo, pero no había ningún enlace. Si pensó mucho y buscó información en Internet.

[ljh@VM-0-11-centos test]$ gcc main.c -o main -I ./lib/
/tmp/ccBm9pNY.o: In function `main':
main.c:(.text+0xf): undefined reference to `Add'
main.c:(.text+0x2f): undefined reference to `Sub'
collect2: error: ld returned 1 exit status

Li Si finalmente descubrió que la ruta del archivo de la biblioteca no estaba especificada , es decir, podía encontrar .h, pero si no se podía encontrar .c, no se podía encontrar la biblioteca y gcc下 -L ./libse podía especificar la biblioteca. Li Si inmediatamente Cambió el código a lo siguiente, pero aún así informó el error.

[ljh@VM-0-11-centos test]$ gcc main.c -o main -I ./lib/ -L ./lib/
/tmp/ccHZnoAe.o: In function `main':
main.c:(.text+0xf): undefined reference to `Add'
main.c:(.text+0x2f): undefined reference to `Sub'
collect2: error: ld returned 1 exit status

Li Si lo pensó, la ruta del archivo de biblioteca importado ya está allí y se puede encontrar el archivo de encabezado. ¿Desea dar un nombre de archivo de biblioteca específico? , gcc下 -l mymathdespués de agregar el nombre de la biblioteca, después de cambiar el código, Li Si descubrió que podía ejecutarse normalmente.

[ljh@VM-0-11-centos test]$ gcc main.c -o main -I ./lib/ -L ./lib/  -lmymath
[ljh@VM-0-11-centos test]$ ./main 
30
-10

Nota 1:
si se produce el siguiente error, el archivo .c está mal empaquetado durante el empaquetado.
[ljh@VM-0-11-centos test]$ gcc main.c -o main -I ./lib/ -L ./lib/ -lmymath
./lib//libmymath.a: error al agregar símbolos: el archivo no tiene index; ejecute ranlib para agregar un
collect2: error: ld devolvió 1 estado de salida

Nota 2:
la biblioteca estática que proporcionamos anteriormente se vincula dinámicamente de forma predeterminada al compilar, y el vínculo se convertirá en un vínculo estático. Aunque el archivo muestra enlaces estáticos, ldd no muestra nuestra biblioteca staticlib, lo que indica que esta biblioteca está enlazada estáticamente.
fileSi el archivo de comando está en estado de enlace

[ljh@VM-0-11-centos zhangsan]$ ls
main  main.c  stlib
[ljh@VM-0-11-centos zhangsan]$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=fc61dd09c0e83aa9d34292bb5dfcfd2322b5337f, not stripped 这里显示动态

但是ldd当中没有,说明staticlib库没有被动态链接。
[ljh@VM-0-11-centos zhangsan]$ ldd main
	linux-vdso.so.1 =>  (0x00007ffec1fd9000)
	libc.so.6 => /lib64/libc.so.6 (0x00007ff39e814000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ff39ebe2000)

Resumen:
opciones de gcc:
-I + path 给定路径或默认路径当中查找, la ruta predeterminada generalmente es /usr/include.
-L + path:告诉gcc除了默认路径和当前路径,也要到我们的指定路径下找库文件, la biblioteca predeterminada predeterminada del sistema está en /lib o /lib64.
-l +库名称Por ejemplo, ls/lib64, podemos ver muchas bibliotecas, pero debemos especificar qué biblioteca queremos.

¿Por qué no hay un uso obvio de las otras opciones al compilar el lenguaje C -L,-I,-i?
Debido a que gcc puede encontrar los archivos de la biblioteca y los archivos de encabezado en la ruta predeterminada, y gcc compila el código C, libc está vinculado de manera predeterminada, por lo que podemos compilar el programa sin una sola opción.

¿Cómo puede nuestro programa compilar sin usar estas opciones?
Los archivos de encabezado y los archivos de biblioteca se copian en la ruta predeterminada (instalación de biblioteca). Pero, por lo general, cuando se llama a una biblioteca de terceros, aún debe -lindicar qué biblioteca vincular.

Empaquetado de bibliotecas estáticas Escritura de Makefile

Después de empaquetar y crear la carpeta stlib, solo necesita enviar la stlib a otros.
Código:

[ljh@VM-0-11-centos dystlib]$ cat Makefile 
lib:Add.o Sub.o
	ar -rc libstaticlib.a *.o 
	mkdir stlib
	cp *.h stlib 
	cp libstaticlib.a stlib
Add.o:Add.c
	gcc -c $^
Sub.o:Sub.c
	gcc -c $^

resultado:

[ljh@VM-0-11-centos dystlib]$ cd zhangsan
[ljh@VM-0-11-centos zhangsan]$ cp ../stlib/ .
[ljh@VM-0-11-centos zhangsan]$ tree stlib
stlib
|-- Add.h
|-- libstaticlib.a
`-- Sub.h

0 directories, 3 files
[ljh@VM-0-11-centos zhangsan]$ gcc main.c -o main -I ./stlib/ -L ./stlib/  -lstaticlib
[ljh@VM-0-11-centos zhangsan]$ ./main 
30
-10

Empaquetado y uso de librerías dinámicas


Empaquetado de librerías dinámicas:
generar una librería dinámica dy_lib para sumas y restas

  • Generar biblioteca dinámica compartida: Indica la generación de formato de biblioteca compartida fPIC: Genera código independiente de posición
    Reglas de nombre de biblioteca: libxxx.so
    llamar a la biblioteca dinámica es esencialmente el código del archivo de biblioteca ejecutado por el proceso en el área compartida después de que se ejecuta el proceso.
    Cuando el proceso ejecuta el código en el área de código, el contenido de la biblioteca dinámica se puede ejecutar en el área compartida.
    inserte la descripción de la imagen aquí

Al enlazar dinámicamente:
Cuando tenemos varios procesos que necesitan el contenido de una misma biblioteca dinámica, solo necesitamos almacenar una entidad en nuestra memoria.
Cuando está vinculado estáticamente:
cada programa de ejecución del proceso se cargará en el área de código y puede haber varias entidades para la implementación de un código en la memoria.
inserte la descripción de la imagen aquí
Código independiente de la posición: cada proceso tiene un área compartida, diferentes ubicaciones del área compartida se pueden asignar al mismo código de biblioteca dinámica y el código de biblioteca dinámica también se puede cargar en cualquier ubicación en la memoria (conversión de tabla de página), cada El proceso se La función correspondiente se puede ejecutar en el archivo de biblioteca dinámico abierto.
Se garantiza que cuántas líneas de código hay en la biblioteca y cómo ejecutarlo sin error, independientemente de la ubicación, puede ejecutarse normalmente incluso si hay llamadas a funciones. En resumen, no afecta la ejecución de la biblioteca.

Empaquetado de bibliotecas dinámicas Escritura de Makefile

[ljh@VM-0-11-centos dy_lib]$ cat Makefile 
lib:Add.o Sub.o
	gcc -shared *.o -o libmymath.so 
	mkdir dylib
	cp ./*h dylib 
	cp libmymath.so dylib
Add.o:Add.c
	gcc -fPIC -c $^
Sub.o:Sub.c
	gcc -fPIC -c $^
.PHONY:clean
clean:
	rm -rf dylib

Hay una ligera diferencia en el uso en comparación con el estático, y el error
no puede abrir el archivo de objeto compartido: no se informará sobre dicho archivo o directorio.

错误示范
[ljh@VM-0-11-centos zhangsan]$ cp -rf ../dylib/ .
[ljh@VM-0-11-centos zhangsan]$ ls
dylib  main.c
[ljh@VM-0-11-centos zhangsan]$ tree dylib
dylib
|-- Add.h
|-- libmymath.so
`-- Sub.h

0 directories, 3 files
[ljh@VM-0-11-centos zhangsan]$ gcc main.c -o main -I ./dylib/ -L ./dylib/  -lmymath
[ljh@VM-0-11-centos zhangsan]$ ./main
./main: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

Análisis del problema:
cuando lo ejecutamos no tiene nada que ver con el compilador gcc. ¡Cuando se ejecuta, el sistema tiene que ayudarnos a encontrar la biblioteca dinámica que se usará en el tiempo de ejecución! ! !
Es equivalente a darle al compilador una ruta clara, el compilador lo sabe y el compilador genera una ruta correcta con la ayuda de las variables de entorno, pero el sistema no se lo pedirá al compilador, también debemos especificar la ruta al compilador nosotros mismos.
inserte la descripción de la imagen aquí

¿Por qué otros programas que antes estaban conectados dinámicamente pueden ejecutarse directamente?
Debido a que la biblioteca está en la ruta predeterminada, el sistema puede encontrarla.


Solución:
La primera solución: la
variable de entorno LD_LIBRARY_PATH, solo necesitamos importar la ruta del directorio de la biblioteca a la variable de entorno.

[ljh@VM-0-11-centos dy_lib]$ cd zhangsan

[ljh@VM-0-11-centos zhangsan]$ ls dylib
Add.h  libmymath.so  Sub.h

[ljh@VM-0-11-centos zhangsan]$ ./main
./main: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory

[ljh@VM-0-11-centos zhangsan]$ pwd  查询当前目录
/home/ljh/2.27/dystlib/dy_lib/zhangsan

[ljh@VM-0-11-centos zhangsan]$ export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ljh/2.27/dystlib/dy_lib/zhangsan/dylib    追加导入环境变量
[ljh@VM-0-11-centos zhangsan]$ ./main
30
-10

inserte la descripción de la imagen aquí

Luego, podemos colocar las bibliotecas dinámicas y estáticas previamente escritas en la misma carpeta (lib), que pueden usar otros.

[ljh@VM-0-11-centos zhangsan]$ ls
lib  main.c

打印文件内容
[ljh@VM-0-11-centos zhangsan]$ tree lib
lib
|-- Add.h
|-- libmymath.a
|-- libmymath.so
`-- Sub.h

0 directories, 4 files

[ljh@VM-0-11-centos zhangsan]$ gcc main.c -o main -I ./lib/ -L ./lib/  -lmymath -static

main就可以是静态编译了
[ljh@VM-0-11-centos zhangsan]$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=02ddaebbe1c007e6bfcd54f5b91e3128a136ebac, not stripped

Por supuesto, la biblioteca aquí también se puede colocar en el directorio de segundo nivel y en el directorio de tercer nivel.
inserte la descripción de la imagen aquí
La segunda forma de encontrar la biblioteca dinámica : copie el archivo .so escrito por usted mismo en la ruta de la biblioteca compartida del sistema, que generalmente se refiere a /sur/lib.
La tercera forma de encontrar la biblioteca dinámica : ldconfig configure /etc/ld.so.conf.d/, actualice el usuario raíz ldconfig
y cree un archivo de sufijo .conf en la ruta /etc.ld.so.con.d/, Luego escriba la dirección del directorio de lib.
Luego, actualice ldconfig, puede ejecutar el archivo de enlace dinámico normalmente.

编写lib文件的路径
[root@VM-0-11-centos ~]# echo "/home/ljh/2.27/dystlib/dy_lib/zhangsan/lib" > /etc/ld.so.conf.d/ljh_tmp.conf
[root@VM-0-11-centos ~]# logout
刷新
[root@VM-0-11-centos ~]# ldconfig
[root@VM-0-11-centos ~]# logout
[ljh@VM-0-11-centos zhangsan]$ ./main30
-10

inserte la descripción de la imagen aquí

Dado que los dos primeros métodos no están escritos en el archivo de script de configuración del sistema, no se pueden ejecutar después de volver a iniciar sesión, mientras que el tercer método se puede usar de forma permanente.




Comprensión de la biblioteca:

Cuando usamos una biblioteca de terceros y descargamos bibliotecas de otras personas, si es un archivo fuente, podemos compilar y generar la biblioteca nosotros mismos y luego usarla. Si alguien más nos ayuda a escribirla, podemos instalarla y copiarla en la ruta predeterminada para nosotros.


Resumir

!_!

Supongo que te gusta

Origin blog.csdn.net/weixin_52344401/article/details/123160988
Recomendado
Clasificación