外观
09.Linux下C语言库管理-常用命令
约 1680 字大约 6 分钟
动态库C个人随笔
2025-12-12
📌 核心命令分类速查
一、静态库相关命令
1. ar - 创建和管理静态库
# 创建静态库
ar rcs libmath.a math1.o math2.o
# 查看静态库内容
ar t libmath.a # 列出库中所有目标文件
ar tv libmath.a # 详细信息(大小、时间、权限)
# 修改静态库
ar r libmath.a newfile.o # 添加/替换文件
ar d libmath.a oldfile.o # 删除文件
ar x libmath.a # 提取所有文件
ar x libmath.a math1.o # 提取特定文件2. nm - 查看符号表
# 查看静态库符号
nm libmath.a # 显示所有符号
nm -C libmath.a # 显示demangled C++符号
nm -g libmath.a # 只显示外部符号
nm -u libmath.a # 只显示未定义符号
# 常用选项组合
nm --defined-only libmath.a | grep -v ' U ' # 只查看已定义符号3. objdump - 目标文件反汇编
# 查看静态库信息
objdump -t libmath.a # 显示符号表(类似nm)
objdump -T libmath.a # 动态符号表(对静态库通常为空)
objdump -d libmath.a # 反汇编
objdump -s libmath.a # 显示完整内容
objdump -h libmath.a # 显示节头信息二、动态库相关命令
1. 创建动态库
# 基本创建
gcc -shared -fPIC -o libmath.so math1.c math2.c
# 带版本号和优化
gcc -shared -fPIC -Wl,-soname,libmath.so.1 -o libmath.so.1.0.0 *.c2. ldd - 查看动态库依赖
# 查看程序/库的依赖
ldd ./myapp # 查看程序依赖
ldd libmath.so # 查看库的依赖
# 常用技巧
ldd -v ./myapp # 显示详细信息
ldd -r ./myapp # 显示未解析的符号
ldd -u ./myapp # 显示未使用的依赖3. readelf - ELF文件分析
# 动态库信息查看
readelf -d libmath.so # 查看动态段(最重要!)
readelf -s libmath.so # 查看符号表
readelf -h libmath.so # 查看ELF头
readelf -l libmath.so # 查看程序头
readelf -r libmath.so # 查看重定位信息
# 面试重点:动态段内容解读
readelf -d libmath.so | grep -E '(SONAME|NEEDED|RPATH|RUNPATH)'4. objdump(动态库)
objdump -p libmath.so # 查看动态段(与readelf -d类似)
objdump -T libmath.so # 动态符号表
objdump -t libmath.so # 所有符号表
objdump -R libmath.so # 重定位信息5. strip - 去除调试信息
strip --strip-unneeded libmath.so # 去除不需要的符号
strip --strip-debug libmath.so # 只去除调试信息
strip --strip-all libmath.so # 去除所有符号信息三、编译和链接相关命令
1. gcc链接选项
# 链接静态库
gcc main.c -L. -lmath -o app
# 链接动态库
gcc main.c -L. -lmath -Wl,-rpath,/usr/local/lib -o app
gcc main.c -L. -lmath -Wl,-rpath,'$ORIGIN' -o app # 相对路径
gcc main.c -L. -lmath -Wl,--enable-new-dtags -Wl,-rpath,/custom/lib -o app
# 常用优化选项
gcc -fPIC -shared -Wl,-Bsymbolic -Wl,--as-needed -o libmath.so *.c2. 查看链接过程
# 显示详细链接过程
gcc -v main.c -lmath 2>&1 | grep -E 'collect2|ld'
# 保存中间文件
gcc -save-temps main.c -lmath
# 生成: main.i, main.s, main.o四、运行时管理命令
1. ldconfig - 动态链接器配置
# 查看当前配置
ldconfig -p # 打印缓存内容
ldconfig -v # 显示扫描的目录
ldconfig -N # 不重建缓存,只打印
# 管理配置
sudo ldconfig # 更新缓存
sudo ldconfig -n /custom/lib # 临时添加目录
cat /etc/ld.so.conf # 查看配置文件
ls /etc/ld.so.conf.d/ # 查看配置片段2. 动态加载器控制
# 环境变量控制
export LD_LIBRARY_PATH=/custom/lib:$LD_LIBRARY_PATH
export LD_PRELOAD=/path/to/libpreload.so
export LD_DEBUG=libs # 调试库加载
# 调试输出级别
export LD_DEBUG=all # 全部信息
export LD_DEBUG=bindings # 符号绑定信息
export LD_DEBUG=files # 文件操作信息
export LD_DEBUG=statistics # 统计信息3. 查看进程库映射
# 查看运行中进程的库映射
pmap <PID> # 内存映射
cat /proc/<PID>/maps # 更详细的内存映射
lsof -p <PID> | grep '\.so' # 查看打开的库文件五、调试和问题排查命令
1. 动态库加载问题排查
# 1. 检查库是否存在
whereis libmath.so
find / -name "libmath.so*" 2>/dev/null
# 2. 检查库架构是否匹配
file libmath.so # 查看文件类型和架构
file ./myapp
# 3. 检查符号是否存在
nm -D libmath.so | grep function_name
readelf -Ws libmath.so | grep function_name
# 4. 版本冲突检查
strings libmath.so | grep -i version2. 性能分析工具
# strace跟踪系统调用
strace -e open,openat ./myapp 2>&1 | grep '\.so'
# ltrace跟踪库调用
ltrace ./myapp
# gdb调试动态库
gdb ./myapp
(gdb) set environment LD_LIBRARY_PATH=.
(gdb) break function_in_library
(gdb) run📊 面试常考问题对应命令
问题1:如何查看一个程序依赖哪些动态库?
ldd ./program # 最常用
readelf -d ./program | grep NEEDED # 查看直接依赖
objdump -p ./program | grep NEEDED # 另一种方式问题2:如何查看动态库导出哪些函数?
nm -D libmath.so # 查看动态符号
readelf -Ws libmath.so | grep 'FUNC' # 详细查看函数
objdump -T libmath.so # 动态符号表问题3:动态库加载失败如何排查?
# 检查步骤:
1. ldd ./app # 查看哪些库找不到
2. file libmissing.so # 检查架构是否匹配
3. readelf -d libmissing.so # 检查依赖
4. LD_DEBUG=libs ./app # 调试加载过程问题4:如何创建带版本的动态库?
gcc -shared -fPIC -Wl,-soname,libmath.so.1 -o libmath.so.1.0.0 math.c
ln -sf libmath.so.1.0.0 libmath.so.1
ln -sf libmath.so.1 libmath.so问题5:如何查看静态库的内容?
ar t libmath.a # 列出文件
ar tv libmath.a # 详细信息
nm libmath.a # 查看符号
objdump -d libmath.a # 反汇编🎯 实战演练命令集
场景1:编译链接全过程
# 1. 编译为目标文件
gcc -c -fPIC math1.c math2.c
# 2. 创建动态库
gcc -shared -o libmath.so math1.o math2.o
# 3. 链接程序
gcc main.c -L. -lmath -Wl,-rpath,'$ORIGIN' -o app
# 4. 验证
ldd app
./app场景2:调试符号问题
# 查找未定义符号
nm -u libmath.so
nm -g libmath.a
# 查看符号冲突
nm -D libmath.so | grep -v ' U '
# 检查C++名称修饰
nm -C libmath.so场景3:性能优化
# 1. 去除调试信息
strip --strip-unneeded libmath.so
# 2. 检查依赖是否必要
ldd -u app
gcc -Wl,--as-needed -o app main.c -lmath
# 3. 预链接优化
ld -r -o combined.o *.o
gcc -shared -o libmath.so combined.o💡 记忆技巧
命令分类记忆
- 查看内容:
ar t,nm,objdump - 查看依赖:
ldd,readelf -d - 创建库:
ar rcs(静态),gcc -shared(动态) - 调试:
LD_DEBUG,strace,ltrace
常用选项记忆
-fPIC:位置无关代码(动态库必须)-shared:创建共享库-L:指定库搜索路径-l:指定链接的库-Wl,-rpath:指定运行时库搜索路径
面试高频命令
ldd- 库依赖检查(必考)nm- 符号表查看(必考)readelf -d- 动态段信息gcc -shared -fPIC- 创建动态库ar rcs- 创建静态库
