动态库和静态库 | AI工程化部署

简介: 我们在编写接口或者使用第三方应用时,都会打包或者引入.so或者.a文件。这个so就是动态库,.a文件就是静态库 【1月更文挑战第5天】

1.什么是动态库和静态库

我们在编写接口或者使用第三方应用时,都会打包或者引入.so或者.a文件。这个so就是动态库,.a文件就是静态库。

具体的,动态库和静态库是在C语言中用来组织和共享代码的两种方式。

静态库(Static Library)是一组预编译的对象文件的集合,它们被组合成一个单一的文件。当使用静态库时,链接器会将库中的代码和数据复制一份到最终的可执行文件中。这意味着可执行文件会包含所有需要的函数和数据,使得程序可以独立运行。静态库的文件扩展名通常为 .a(Unix-like系统)或 .lib(Windows系统)。

动态库(Dynamic Library)是一组目标文件的集合,它们在程序运行时被加载到内存中。当程序运行时,操作系统会加载动态库中的代码和数据,多个程序可以共享已加载的库,这样可以减少内存占用并方便对库文件进行更新。动态库的文件扩展名通常为 .so(Unix-like系统)或 .dll(Windows系统)。

动态库和静态库区别在于:

  1. 静态库的代码和数据会被复制到可执行文件中,程序独立运行;而动态库的代码和数据是在程序运行时加载到内存中,多个程序可以共享已加载的库。
  2. 静态库会增加可执行文件的大小,动态库不会影响可执行文件的大小。
  3. 静态库在程序编译时就已经链接到可执行文件中,而动态库则是在程序运行时动态加载的。

应用场景:

  • 静态库常用于需要独立运行且不需要频繁更新的程序,或者在无法依赖外部动态库的环境下使用。
  • 动态库常用于需要共享代码、减少内存占用或者便于库文件更新的场景。

我们知道,在编译c语言程序时,会生成.o的中间文件和最终可执行文件,其中".o"文件是编译器生成的目标文件,它包含了源代码文件编译后的机器代码和相关的符号表信息。".elf"文件是可执行和可链接格式(Executable and Linkable Format)文件,它包含了程序的可执行代码、数据、符号表和其他信息,用于在操作系统中执行程序。通常,".o"文件是编译后的中间文件,而".elf"文件是最终的可执行文件。而本质上看,静态库和动态库都是众多.o文件的集合。

2.如何编译

编译动态库和静态库的过程略有不同。以下是具体的步骤:

静态库

假设你有一个叫做hello.c的文件,你想把它编译成一个静态库。以下是步骤:

  1. 首先,你需要使用gcc编译hello.c,但是你需要使用-c标志来生成一个对象文件而不是一个完整的程序。这将生成一个hello.o文件。
gcc -c hello.c
  1. 然后,你使用ar命令来创建静态库。此命令会生成libhello.a文件。
ar rcs libhello.a hello.o

ar命令的rcs选项执行以下操作:

  • r:替换旧的对象文件(如果存在)。
  • c:创建新的库(如果不存在)。
  • s:创建一个对象文件索引(对于库的链接很重要)。

动态库

如果你有一个源文件hello.c,你想要编译成一个动态库。以下是步骤:

  1. 首先,你需要使用gcc编译hello.c,但是你需要使用-c标志来生成一个对象文件而不是一个完整的程序。这将生成一个hello.o文件。
gcc -c -fPIC hello.c

-fPIC标志告诉gcc生成位置无关代码(PIC),这是创建共享库所必需的。

  1. 然后,你可以使用gcc命令和-shared选项来创建动态库。这将生成一个libhello.so共享库。
gcc -shared -o libhello.so hello.o

-shared选项告诉链接器创建一个共享库。

在链接时,需要使用-L-l选项指定库的路径和名称。

例如,如果你的程序名为main.c,并且你想链接之前创建的静态库或动态库,你可以这样做:

对于静态库:

gcc main.c -L. -lhello -o main

对于动态库:

gcc main.c -L. -lhello -o main

请注意,-L.告诉链接器在当前目录中查找库,-lhello告诉它链接到libhello库(无论是.a还是.so)。程序的输出在-o后指定,这里是main

特别注意的是,动态库需要加上-fPIC, 在cmake里动态库关键字为share,静态库为static

另外在链接so库的时候,编译器是如何通过-l后面的名字寻找相对应的so库呢,动态链接库的有一定的寻找顺序:

  • rpath 指定的目录;
  • 环境变量 LD_LIBRARY_PATH 指定的目录;
  • runpath 指定的目录;
  • /etc/ld.so.cache 缓存文件,通常包含 /etc/ld.so.conf 文件编译出的二进制俩别哦(比如 CentOS 上,该文件会使用 include 从而使用 ld.so.conf.d 目录下面所有的 *.conf 文件,这些都会缓存在 ld.so.cache 中)
  • 系统默认路径,比如 /lib,/usr/lib。

在编译时若使用 -z nodefaultlib 选项编译,则会跳过 4 和 5。至于 runpath,和 rpath 类似,都是二进制(ELF)文件的动态 section 属性(分别为 DT_RUNPATH 和 DT_RPATH),唯一区别就是是否优先于 LD_LIBRARY_PATH 来查找

3.如何使用

动态库和静态库使用分为隐式使用和显示打开,其中隐式使用就是通过-l直接链接到主程序中,而显示使用时通过dlopen的方式在程序使用的时候打开so文件并获取通过dlsym相应的函数接口。

这里详细介绍下dlopen的方式。

#include <stdio.h>
#include <dlfcn.h>
#include <iostream>

// g++ dlopen_test.cpp -o test -ldl
int main(int argc, char* argv[]){
   
    void *handle;
    int (*hello)();

    // 打开动态库
    handle = dlopen("./libso21.so", RTLD_LAZY);
    if (!handle) {
   
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    // 获取动态库中的函数指针
    *(void **)(&hello) = dlsym(handle, "hello_world_so");
    if (!hello) {
   
        fprintf(stderr, "%s\n", dlerror());
        dlclose(handle);
        return 1;
    }

    // 调用动态库中的函数
    (*hello)();


    // 关闭动态库
    dlclose(handle);

通过dlopen的方式,编译并不会检查so的正确性,只会在运行时加载so到内存中,并获取相应的函数。

4.查看动态库和静态库信息

通常我们需要查看打包的动态库和静态库是否符合要求,链接是否正常以及是否包含相应的函数符号等,有一些命令可以帮助我们更可了解它们。

  1. patchelf:该命令可以用来修改ELF可执行文件的动态链接器(即解释器),RPATH,或者动态符号表。主要用于处理库路径问题,有时候运行某个程序时,系统找不到其依赖的库,可以通过这个命令来修改。

    使用示例:patchelf --set-rpath /path/to/lib your_program

    这个命令将程序二进制文件中的rpath设置为/path/to/lib

  2. nm:这个命令可以显示从目标文件的符号表中列出符号。默认情况下,nm会按照字母顺序列出符号。

    使用示例:nm /path/to/libyourlib.so

    这个命令将列出动态库文件libyourlib.so中的所有符号。

  3. ldd:这个命令可以用来查看可执行文件或者动态库所依赖的其他动态库文件。它会列出所有的依赖库以及这些库的位置。

    使用示例:ldd /path/to/your_program

    这个命令将列出可执行文件your_program依赖的所有动态库的位置。

  4. objdump:这个命令可以显示一个或多个目标文件的信息。它可以显示二进制文件的详细信息,包括文件头,节信息,符号表等。

    使用示例:objdump -x /path/to/your_program

    这个命令将显示可执行文件your_program的详细信息。

  5. readelf:这是一个用于显示ELF格式文件信息的程序。它可以显示ELF文件的各种信息,包括文件头信息,节信息,段信息,符号表等。

    使用示例:readelf -a /path/to/your_program

    这个命令将显示可执行文件your_program的所有ELF信息。

请记住,每一个命令都有很多选项可以使用,这里只是提供了一些基本示例。一定要查阅对应命令的man手册以获取更详细的信息。

目录
相关文章
|
25天前
|
人工智能 自然语言处理 开发者
AIGC创作活动 | 跟着UP主秋葉一起部署AI视频生成应用!
本次AI创作活动由 B 站知名 AI Up 主“秋葉aaaki”带您学习在阿里云 模型在线服务(PAI-EAS)中零代码、一键部署基于ComfyUI和Stable Video Diffusion模型的AI视频生成Web应用,快速实现文本生成视频的AI生成解决方案,帮助您完成社交平台短视频内容生成、动画制作等任务。制作上传专属GIF视频,即有机会赢取乐歌M2S台式升降桌、天猫精灵、定制保温杯等好礼!
|
25天前
|
人工智能
一键生成视频!用 PAI-EAS 部署 AI 视频生成模型 SVD 工作流(清晰的实例)
用 PAI-EAS 部署 AI 视频生成模型 SVD 工作流(清晰的实例)
159 2
|
2月前
|
人工智能 边缘计算 监控
【开源视频联动物联网平台】视频AI智能分析部署方式
【开源视频联动物联网平台】视频AI智能分析部署方式
127 3
|
3月前
|
传感器 机器学习/深度学习 算法
无人机视角yolo多模态、模型剪枝、国产AI芯片部署
无人机视角yolo多模态、模型剪枝、国产AI芯片部署
192 0
无人机视角yolo多模态、模型剪枝、国产AI芯片部署
|
4月前
|
人工智能 Serverless 数据安全/隐私保护
云端服务器应用实践:函数计算X 通义千问快速部署 AI 个人助手应用
云端服务器应用实践:函数计算X 通义千问快速部署 AI 个人助手应用
330 2
|
3月前
|
人工智能 Serverless API
【体验有奖】5 分钟函数计算部署 AI 艺术字应用,晒姓氏头像赢 Cherry 键盘!
【体验有奖】5 分钟函数计算部署 AI 艺术字应用,晒姓氏头像赢 Cherry 键盘!
|
3月前
|
存储 物联网 Serverless
玩转 AI 绘图,基于函数计算部署 Stable Diffusion可自定义模型
本文主要将带大家通过使用阿里云产品函数计算 FC 和文件存储 NAS ,快速使用 Stable Diffusion 实现更高质量的图像生成,本方案内置模型库+常用插件+ControlNet ,用户可根据自己的需要更换需要的模型、Lora、增加插件。
48872 27
玩转 AI 绘图,基于函数计算部署 Stable Diffusion可自定义模型
|
6天前
|
人工智能 Ubuntu 机器人
AI电销机器人系统源码部署之:freeswitch安装Linux
在Linux服务器上安装FreeSWITCH的简要步骤:更新软件包,安装依赖(如build-essential,libssl-dev等),下载v1.10.7源代码,解压并配置,编译,然后运行`./bootstrap.sh -j`,`./configure`,`make`,`make install`。启动FreeSWITCH服务,配置SIP用户和路由,测试连接与通话,并确保防火墙打开SIP(5060)和RTP端口。注意,实际部署可能需按需求调整。
|
9天前
|
人工智能 API 网络架构
【AI大模型应用开发】【LangChain系列】7. LangServe:轻松将你的LangChain程序部署成服务
【AI大模型应用开发】【LangChain系列】7. LangServe:轻松将你的LangChain程序部署成服务
19 0
|
9天前
|
人工智能 安全 机器人
AI电销机器人系统源码部署:freeswitch安装Windows
在Windows上安装FreeSWITCH:访问官网下载安装程序,运行并按提示安装;选择安装路径和组件;等待安装完成;配置FreeSWITCH,修改设置;启动服务;测试其功能;如遇问题,参考官方文档或进行调试故障排除。记得定期更新维护以保证稳定安全。