当前位置: 首页 > news >正文

详细介绍 .so 文件(Linux 动态链接库)

目录

一、基础概念

1. 全称与作用

2. 动态库 vs 静态库(.so vs .a)

二、文件结构与格式

三、常见使用场景

1. Linux 服务 / 程序

2. Android 开发(最常接触场景)

3. 嵌入式 Linux

四、核心工作原理(动态链接)

两种加载方式

五、常用命令(Linux/Android adb 调试 so)

1. 查看依赖库

2. 查看内部符号(函数 / 变量)

3. 查看 ELF 段、架构、信息

4. 瘦身 / 去除调试符号(发布常用)

5. Android 专用(adb)

六、常见问题与坑

1. error while loading shared libraries: xxx.so: cannot open shared object file

2. 架构不匹配

3. 符号未导出(JNI 常见)

4. 版本冲突

七、Android 端补充(开发重点)

八、总结


.soLinux/Android/Unix 系统下的动态共享库文件(Shared Object),对应 Windows 的.dll、macOS 的.dylib,是二进制可执行文件,存放编译后的代码、函数、变量、资源。

一、基础概念

1. 全称与作用

  • 全称:Shared Object(共享目标文件)
  • 核心特点运行时动态加载、多个程序共享一份库代码,区别于.a静态库(编译时打包进程序)。
  • 后缀惯例:
    • 标准:libxxx.so(Linux 库命名规范,前缀lib
    • 带版本:libxxx.so.1.2.3(主版本。次版本。修订版),通常用软链接指向最新版

2. 动态库 vs 静态库(.so vs .a)

特性.so 动态库.a 静态库
链接时机程序运行时加载编译链接阶段打包进可执行文件
体积可执行文件小,库单独存在可执行文件体积大
占用空间多程序共用一份,省磁盘 / 内存每个程序都拷贝一份,冗余大
更新方式替换 .so 文件即可,无需重新编译主程序必须重新编译链接整个程序
依赖运行环境必须存在对应 .so无外部库依赖,独立运行

二、文件结构与格式

.so本质是ELF 格式文件(Executable and Linkable Format),Linux 下所有可执行、库文件基本都是 ELF。 主要分段(Section):

  1. .text:编译后的机器指令(函数代码),只读
  2. .data:已初始化全局变量
  3. .bss:未初始化全局变量(不占文件空间,运行时分配内存)
  4. .rodata:只读常量(字符串、const 变量)
  5. .symtab / .dynsym:符号表(函数名、变量名,供链接 / 调用)
  6. .dynstr:动态符号字符串表
  7. .rel:重定位段(动态链接时修正内存地址)

关键:动态符号表 (.dynsym)是外部程序调用库函数的核心,被strip瘦身的 so 会丢失调试符号,但保留动态调用符号。

三、常见使用场景

1. Linux 服务 / 程序

系统底层、第三方组件、中间件大量使用.so

  • C/C++ 程序依赖系统库:libc.so(标准 C 库)、libpthread.so(线程库)
  • Nginx、MySQL、Redis 等都会加载各类动态库

2. Android 开发(最常接触场景)

Android 基于 Linux 内核,Native 层完全使用 .so

  • 架构区分(不同 CPU 架构不能通用):
    • armeabi-v7a:32 位 ARM 老设备
    • arm64-v8a:64 位 ARM 主流安卓机
    • x86/x86_64:模拟器、Intel 平板
  • 用途:
    1. JNI 调用:Java ↔ C/C++,把 C++ 代码编译成 so 给 App 调用
    2. 音视频(FFmpeg、OpenCV)、加解密、渲染、逆向、插件等核心能力
    3. 代码保护:so 是二进制,反编译难度远高于 Java 字节码

3. 嵌入式 Linux

路由器、机顶盒、工控机、物联网设备,普遍依赖.so库。

四、核心工作原理(动态链接)

  1. 编译阶段主程序只记录「需要调用哪个 so 的哪个函数」,不拷贝代码,只留符号引用。
  2. 运行阶段OS 的动态链接器 ld-linux.so工作:
    • 加载可执行文件到内存
    • 根据依赖列表,查找并加载对应.so到进程地址空间
    • 重定位:修正函数内存地址,完成符号绑定
    • 多个进程可共享同一份 so 内存副本,仅数据段私有

两种加载方式

  1. 隐式加载(编译链接时指定依赖)编译程序时-lxxx链接 so,程序启动自动加载,最常用。
  2. 显式加载(运行时手动加载)代码中主动调用 API 加载、卸载 so:
    • Linux/Android C:dlopen()dlsym()dlclose()
    • 适用:插件化、动态按需加载、版本热更新

五、常用命令(Linux/Android adb 调试 so)

1. 查看依赖库

ldd 可执行文件/xxx.so # 作用:列出当前 so/程序 依赖的所有 .so,排查 "找不到库" 问题

2. 查看内部符号(函数 / 变量)

# 查看所有符号(含调试符号) nm xxx.so # 只看动态导出符号(外部可调用的函数,重点) nm -D xxx.so

3. 查看 ELF 段、架构、信息

# 查看文件架构、类型、位数 file xxx.so # 详细 ELF 信息 readelf -h xxx.so # 查看所有段 readelf -S xxx.so

4. 瘦身 / 去除调试符号(发布常用)

strip xxx.so # 作用:删除调试符号、注释,大幅减小文件体积,不影响正常调用

5. Android 专用(adb)

# 进入手机 shell adb shell # 查看进程加载的所有 so cat /proc/[PID]/maps

六、常见问题与坑

1.error while loading shared libraries: xxx.so: cannot open shared object file

原因:系统找不到依赖的 so解决

  1. 把 so 放到系统库路径:/lib/usr/lib
  2. 配置环境变量:export LD_LIBRARY_PATH=/你的so目录:$LD_LIBRARY_PATH
  3. 更新系统库缓存:ldconfig

2. 架构不匹配

现象:文件存在但加载失败、Exec format error原因:32 位 / 64 位、ARM/x86 架构不兼容

  • arm64-v8a so 不能在 32 位 ARM 设备运行
  • x86 so 不能在真机 ARM 上运行

3. 符号未导出(JNI 常见)

现象dlsym找不到函数,Java JNI 报UnsatisfiedLinkError原因

  • C/C++ 函数没加extern "C"(C++ 名字会被篡改(名字改编))
  • 编译脚本(CMake/Android.mk)未指定导出符号

4. 版本冲突

系统已有同名但版本不同的 so,导致符号冲突、崩溃。

七、Android 端补充(开发重点)

  1. 编译工具
    • 旧版:Android.mk
    • 主流:CMake + NDK,将 C/C++ 源码编译为对应架构.so
  2. 调用流程Java (JNI) → 加载 so → 调用 C/C++ 函数
  3. 安全相关
    • so 属于原生二进制,可被IDA、Ghidra逆向分析
    • 加固手段:加壳、混淆、字符串加密、ollvm 控制流平坦化

八、总结

  1. .so=Linux/Android 动态共享库,对应 Windows.dll,ELF 二进制格式。
  2. 优势:体积小、易更新、多程序共享,是 Linux 生态的基础组件。
  3. 两大核心场景:Linux C/C++ 服务、Android NDK 原生开发。
  4. 日常排错重点:依赖缺失、架构不匹配、符号未导出、库路径问题
http://www.jsqmd.com/news/980512/

相关文章:

  • 边缘计算崛起 正在改变未来数字世界的运行方式
  • ViGEmBus驱动终极指南:5步轻松实现Windows游戏控制器模拟
  • MATLAB珍珠图像处理工具包:自动分割、轮廓提取与尺寸分级一体化实现
  • 北京黄金回收品牌综合服务六店实测横评 - 润富黄金回收
  • DE1-115开发板即用型Gold码发生器FPGA工程(Quartus 13.1编译通过,EP4CE115芯片)
  • 线装机技术工艺标准与行业适配指南分享 - 奔跑123
  • 终极iOS越狱指南:轻松解锁iPhone隐藏功能
  • 高并发系统设计
  • MBTI实操指南:从人格标签到团队效能的四级跃迁
  • Claude 3.5原生能力如何让RAG与Agent中间件走向零值
  • PDF文件在线压缩怎么做?2026年保姆级教程+工具推荐
  • 从邻居吵架到路由同步:一个故事讲明白OSPF那5封关键‘信件’都写了啥
  • VS2022配置C++ 20解决import std报错
  • 高效智能的国家中小学智慧教育平台电子课本解析工具:专业PDF下载解决方案
  • 遗传算法Python实战:N皇后问题工程化实现
  • 终极解密指南:3步轻松解锁网易云音乐NCM格式,实现跨平台播放自由
  • 北京黄金回收品牌综合服务六店横评实录 - 润富黄金回收
  • pandas多维聚合实战:银行级高性能分组计算与避坑指南
  • 西瓜视频去水印方法2026最新教程:4个工具秒速去除水印 - 科技热点发布
  • FIO参数太多看不懂?一张图帮你搞定磁盘测试,附送常用场景(数据库/云盘)配置模板
  • 用Cheat Engine 7.5给植物大战僵尸“开挂”:从阳光到僵尸血量的保姆级修改教程
  • Hitboxer终极指南:免费解决游戏键盘输入冲突的神器
  • 如何利用单北斗变形监测实现大坝安全监测?
  • 干货测评|2026年超实用AI论文写作工具榜单,AI工具一键写高质论文
  • 计算机毕业设计之基于Hadoop的运动员健康分析系统的设计与实现
  • AI 实时推理流式预热实战:首字符延迟从 800ms 砍到 200ms
  • 体验感强的新疆小团旅行社排行:5家机构实测对比 - 互联网科技品牌测评
  • 基于深度学习YOLOv10的安全手套佩戴识别检测系统(YOLOv10+YOLO数据集+UI界面+Python项目源码+模型)
  • 2026年6月9日佛山南海区黄金回收简报 金价947元每克本地需求旺 - 上门黄金回收
  • 机器学习数据挖掘集成学习:群英荟萃的智能决策