Linux动静态库

发布于:2025-03-13 ⋅ 阅读:(12) ⋅ 点赞:(0)

Linux动静态库

静态库

核心特性:

  • 链接时机:在编译时将库代码直接嵌入到可执行文件中。
  • 文件格式:.a(Linux)、.lib(Windows)。
  • 内存占用:每个使用该库的可执行文件都会包含一份完整的库代码副本。

创建静态库(.a文件)

  1. 编写源代码:首先,编写你需要的库函数的源代码文件,例如mylib.c
  2. 编译为目标文件:使用gcc/g++编译源码为目标文件(.o文件)
g++ -c mylib.cpp -o mylib.o
  1. 创建静态库:使用ar工具将目标文件打包为静态库(.a文件)
ar rcs libmylib.a mylib.o
  • rcs:替换旧文件(r)、创建新库(c)、生成索引(s)

动态库

核心特性:

  • 链接时机:在运行时由操作系统动态加载到内存(映射到地址空间的共享区)。
  • 文件格式:.so(Linux)、.dll(Windows)。
  • 内存占用:多个进程可共享同一份库的内存实例。

创建动态库(.so文件)

  1. 编写源代码:首先编写库函数的源代码文件,例如mylib.c
  2. 编译并生成位置无关代码(PIC):在编译为目标文件时,需要添加-fPIC选项以生成位置无关代码
g++ -c -fPIC mylib.cpp -o mylib.o
  1. 创建动态库:使用gcc/g++的-shared选项将目标文件链接为动态库(.so文件)
g++ -shared mylib.o -o libmylib.so

库的链接

在gcc/g++的编译和链接过程中,-I(大写i)、-L、-l(小写L)是三个常用的选项,它们分别用于指定头文件的搜索路径库文件的搜索路径以及要链接的库的名称

gcc -I /home/user/include -L /home/user/lib -lmylib my_program.c -o my_program


-I/home/user/include 告诉编译器在 /home/user/include目录下查找头文件。
-L/home/user/lib 告诉链接器在 /home/user/lib目录下查找库文件。
-Imylib告诉链接器链接名为mylib的库 (即查找libmylib.a或libmylib.so文件)。

】:

  • 库就是功能性代码块的包装,也是包含:头文件 和 源文件(所谓的:库文件),头文件和库文件一般都是存储在各自的目录下,所以需要分别链接。
  • 链接库名时要去掉前后缀,前缀lib,后缀 .a / .so。

上述操作是让编译器知道了文件路径,但链接完成后的程序运行时动态库还需要加载,加载器还不知道所使用的第三方动态库的路径。

五种方法解决:

  1. 将动态库文件拷贝到系统默认的库路径 /lib64/ 或 /usr/lib64/;
  2. 建立系统默认的库路径下的软链接指向第三方库;
  3. 将库的路径添加进环境变量 LD_LIBRARY_PATH 中
//临时追加
export LD_LIBRARY_PATH=/path/to/your/lib:$LD_LIBRARY_PATH
./your_program
  1. 编译时指定 rpath(硬编码路径到可执行文件)
g++ main.cpp -L./mylib -lmylib -Wl,-rpath='$ORIGIN/mylib' -o main

//-Wl,-rpath=...:将 rpath 写入可执行文件,$ORIGIN 表示可执行文件所在目录。
  1. 配置/etc/ld.so.conf.d/,ldconfig更新
    在/etc/ld.so.conf.d/路径下创建一个 .conf文件,把动态库所在的路径放到这个.conf文件中,然后ldconfig 重新加载一份即可。
cd  /etc/ld.so.conf.d/
touch  myname.conf
vim myname.conf  //打开后把路径复制粘贴进去就行

怎么简化链接库的命令呢?

  1. 如果自己创建的头文件和库文件 分别放在系统中存储库的文件的目录中时,就不需要-I和-L了,仅需链接指定库文件即可(就像使用C语言库直接编译那样,还是需要指定库名称)。
  2. 建立系统标准库目录下的软链接
    eg:
#include “myinc/mymath.h”
gcc main.c -o main -lmymath

//在系统头文件和库文件的标准库目录下 分别创建指向自己创建的库的头文件和库文件的软链接

在这里插入图片描述

动态库在系统中加载之后,会被所有链接了该库的进程共享,这是如何被共享的?

答:动态库从磁盘加载到物理内存,然后这一份动态库文件可以与所有链接该库的进程建立映射,映射到每个进程的进程地址空间的共享区中。