IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

关于Linux共享库的一点儿知识

PHPor 的blog 2012-01-29 20:47:14 累计浏览 3,508 次
本机暂存
1. 关于动态链接的文件依赖的共享库:
链接时使用-l指定的库文件都会记录到elf文件里面的,程序加载前的动态链接一定会加载的,不管你的程序是否会用到;如:
======= phpor.c ============
  1. #include <stdlib.h>
  2. void phpor_hello() {
  3.         printf("hello\n");
  4. }


======= phpor_test.c =============
  1. //void phpor_hello();
  2. int main(int ac, char **av) {
  3. //  phpor_hello();
  4.     printf("no dependent \n");
  5.     return 0;
  6. }

----------------------------------
# gcc -shared -o libphpor.so phpor.c
# gcc -o phpor_test -l phpor -L. phpor_test.c
# LD_LIBRARY_PATH=. ./phpor_test
no dependent
# LD_LIBRARY_PATH=. ldd ./phpor_test
libphpor.so => ./libphpor.so (0x00e4f000)
libc.so.6 => /lib/tls/libc.so.6 (0x00865000)
/lib/ld-linux.so.2 (0x00846000)

你可以把libphpor.so 删掉,执行的时候就报错了

2. 关于共享库的版本号:
我创建了一个so文件 libphpor.so.1 ,现在我要编译一个phpor_test的文件,该文件依赖libphpor.so.1,于是有如下命令:
gcc -o phpor_test -l phpor -L. phpor_test.c
我的libphpor.so.1 是在当前目录下的,所以 -L.
如果我不创建软连接 libphpor.so => libphpor.so.1 的话,则是无法连接的。 为什么不能直接使用 libphpor.so.1 呢? 关键是:
# ldd /bin/ls
librt.so.1 => /lib/tls/librt.so.1 (0x00ce9000)
libacl.so.1 => /lib/libacl.so.1 (0x00f7f000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00a22000)
libc.so.6 => /lib/tls/libc.so.6 (0x00865000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x009f5000)
/lib/ld-linux.so.2 (0x00846000)
libattr.so.1 => /lib/libattr.so.1 (0x00502000)

为什么ls这个命令就能依赖一个带有主版本号的库,而我就不能依赖指定的主版本号?

我只好创建一个软连接 libphpor.so => libphpor.so.1 ,因为该so文件没有在LD_LIBRARY_PATH 下,所以,这里测试时临时指定一下:
LD_LIBRARY_PATH=. ./phpor_test

3. 关于共享库、静态库和动态链接、静态链接的概念
共享库、静态库
强调的是:
我能否其它程序动态加载
特点:
  1. 静态(不是静态链接的可执行程序)可能(也可能不)依赖别的未定义的符号,但是,自己不知道(也不会说明)这些符号在那里可以找到,即: 不描述依赖关系
  2. 共享库可能(也可能不)依赖别的未定义的符号,但是,自己会说明这些符号可能在哪里可以找到,即:描述依赖关系
  3. 其实,静态库实际是没有经过链接的,只是一些目标文件的打包;共享库是经过了链接这个步骤了的
动态链接、静态链接:
强调的是:
我(就是链接的结果文件,可能是一个可执行文件,也可能是一个共享库so文件,注意,so文件有的也可以直接执行,但一定不是静态库文件)在运行的时候,是否依赖别的动态库文件。
特点:
  1. 动态链接的文件一定依赖其他的so文件,至少要依赖 ld.so
  2. 静态链接的文件一定不依赖其他的so文件
库类型与链接类型之间的关系:
  1. 共享库也可以是静态链接的,如:
        # ldd /lib/ld-linux.so.2
        statically linked
  2. 可以使用共享库来静态链接生成一个静态的可执行程序,如:
        LD_LIBRARY_PATH=. gcc -o phpor_test -static -l phpor -L. phpor_test.c
  3. 你也可以使用静态库来动态链接生成一个动态的可执行程序, 如:
        # gcc -o phpor_test phpor_test.c ./libphpor.a
        # ./phpor_test
        hello
        # ldd phpor_test
        libc.so.6 => /lib/tls/libc.so.6 (0x00b9a000)
        /lib/ld-linux.so.2 (0x00b7b000)

4. 我们说,共享库也可以是静态链接的,下面我们做一个实验,把上面的phpor.c 编译成一个静态链接的共享库文件:
因为linux几乎所有程序都依赖libc.so, 现在要静态链接,就需要指定需要的.a 文件 libc.a, 在/usr/lib下; 一般默认是动态链接的,如果要静态连接,就需要使用 -static 选项指定,命令如下:
gcc  -shared  -static -o libphpor.so.2 /usr/lib/libc.a  phpor.c
但是,这样编译的结果还是动态链接的,为什么? -static 没有起作用吗?
使用如下命令:
# gcc  -shared  -nodefaultlibs -o libphpor.so.2 /usr/lib/libc.a  phpor.c
# ldd libphpor.so.2
statically linked

当然,您可以同时使用 -nodefaultlibs和 -static ; 不明白的是: 难道static不是用来屏蔽其它的动态库文件的吗?

先生成目标文件,自己使用ld命令来做静态连接:
# gcc -o phpor.o -c phpor.c    
# ld -shared -dn -o libphpor.so.3 phpor.o
# ldd libphpor.so.3
statically linked
# ln -s  libphpor.so.3 libphpor.so
# LD_LIBRARY_PATH=. ./phpor_test  
hello
又有问题了,为什么我没有指定/usr/lib/libc.a , 这里却能链接完成,而且还能用了呢?难道ld帮我做了?

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. Linux如何统计进程的CPU利用率 (累计阅读 16,308)
  2. 我的 RHCA 之路 (累计阅读 14,013)
  3. Linux内存点滴 用户进程内存空间 (累计阅读 13,230)
  4. 给程序员新手的一些建议 (累计阅读 13,089)
  5. Linux 性能监控、测试、优化工具 (累计阅读 13,011)
  6. 关于linux内存free的一些事情 (累计阅读 12,867)
  7. ps - 按进程消耗内存多少排序 (累计阅读 12,688)
  8. Google怎么用linux (累计阅读 12,581)
  9. Linux Used内存到底哪里去了? (累计阅读 11,868)
  10. find命令的一点注意事项 (累计阅读 11,866)