You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享库与模块库的区别及起源解析请求

共享库(Shared Libraries)与模块库(Module Libraries)的区别及历史背景

核心定义与本质差异

  • 共享库:是为编译/加载时绑定设计的库文件,核心作用是提供程序运行必需的基础功能。它会被操作系统动态链接器(如ld.so)自动加载到进程地址空间,符号(函数、变量)在链接阶段就会被解析或标记为延迟解析。
  • 模块库:专为运行时动态加载而生,用于实现程序的功能扩展(如插件系统)。它无需在编译阶段与程序链接,而是通过dlopen()、dlsym()等函数手动加载,符号解析完全在运行时按需完成。

技术层面的关键区别

  • 链接与加载逻辑
    • 共享库:编译时需通过gcc -lxxx指定链接,生成的可执行文件会包含依赖信息,运行时由动态链接器自动触发加载。
    • 模块库:无需编译时链接,程序通过dlopen("./xxx.so", RTLD_LAZY)这类调用手动加载,符号需通过dlsym()主动查找。
  • 符号可见性设计
    • 共享库默认导出所有符号(可通过-fvisibility=hidden调整),方便链接阶段的符号解析。
    • 模块库通常仅显式导出特定插件接口符号,多通过__attribute__((visibility("default")))标记,避免全局符号冲突。
  • 加载时机
    • 共享库:要么在程序启动时加载(默认),要么通过延迟加载(RTLD_LAZY)在首次调用对应符号时加载。
    • 模块库:完全由程序在运行时按需加载,可随时加载或卸载。

历史起源

  • 共享库的起源:最早诞生于上世纪80年代的UNIX系统,初衷是解决静态库导致的可执行文件体积过大、内存冗余问题。System V和BSD系统先后实现动态链接机制,核心是让多个进程共享同一份库的内存映射,大幅节省系统资源。
  • 模块库的起源:随着插件化需求兴起(如文本编辑器插件、桌面环境扩展),单纯的共享库链接无法满足动态扩展需求。基于dlopen()系列函数的模块加载机制随之出现,允许程序在运行时加载未预链接的库,实现功能的灵活扩展。早期X Window系统插件、Apache模块都是模块库的典型应用场景。

同一.so文件既可以链接又可以加载的原因

*nix系统中,.so本质是ELF格式的共享对象文件,并没有严格的“共享库”或“模块库”标记。二者的区分更多是设计意图和使用场景的不同:

  • 按共享库设计的.so,只要导出了清晰的接口,就能通过dlopen()加载调用;
  • 按模块库设计的.so,如果所有依赖符号都能被链接器找到,也可以在编译时直接链接。
    CMake中区分二者,是为了生成适配不同场景的构建规则(如链接选项、安装路径),但底层文件格式并无本质差异。

跨系统差异的优化方向

若需扩展到其他系统,可针对以下差异细化问题:

  • Windows:共享库为.dll,模块库通常也是.dll,加载使用LoadLibrary()、GetProcAddress(),符号导出规则和链接机制与*nix不同;
  • macOS:共享库为.dylib,模块库可能是.bundle或.dylib,加载仍用dlopen()系列函数,但符号解析、库搜索路径有专属规则。

内容的提问来源于stack exchange,提问作者StoneThrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:37:04