Linux 动态链接库和静态链接库

发布时间: 更新时间: 总字数:1144 阅读时间:3m 作者: 分享 复制网址
专栏文章
  1. Linux 基础知识
  2. chroot 技术简介
  3. Linux 中个目录说明
  4. 进程、线程、协程的作用和区别
  5. Linux 动态链接库和静态链接库(当前)
  6. Linux PAM 可插拔认证模块介绍
  7. Linux limits.conf 详解与配置
  8. Linux Signal 信号量介绍
  9. Linux GDB 调试
  10. Linux core dump 文件介绍
  11. Linux procfs 介绍
  12. Linux 进程 /proc/PID/status 深入分析
  13. Linux sysfs 介绍
  14. Linux nsswithch.conf 详解
  15. Linux Systemd 介绍
  16. Linux Interrupt 中断介绍
  17. Linux namespace 介绍
  18. Linux Cgroups 介绍
  19. Linux Capabilities 介绍

本文介绍 Linux 动态和静态链接库,并通过demo示例,介绍动态链接库和静态链接库的工作过程和原理。

文件格式

  • .h : C 语言头文件,包含了 C 函数声明、宏定义、结构体定义等内容
  • .c : C 语言程序文件,内含函数实现,变量定义等内容
  • .o : 目标(object)文件,一个 *.c*.cpp 文件编译生产一个 .o 文件
  • .a : archive 归档包,一个或多个 *.o 打包生产,实现静态连接库功能,即 static mode,多个 *.a 可以链接生成一个可执行文件
  • .so : shared object 共享库文件,实现动态链接库功能。和 windows的dll 差不多,使用时才载入
  • .la : libtool archive 文件,是libtool自动生成的共享库文件

其他文件:

  • .ko: kernel object文件(内核模块),该文件把内核的一些功能移动到内核外边,需要的时候插入内核,不需要时卸载,一般为驱动程序。达到减少内核体积的目的。参考:Linux kernel 内核模块编译、装载和卸载

概念

  • 静态链接库
    • 在链接阶段,会将汇编生成的目标文件 .o 与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接
    • 库命名规范,必须是 lib[your_library_name].alib为前缀,中间是静态库名,扩展名为.a
  • 动态链接库
    • 是一种不可执行的二进制程序文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Linux 中以 *.so 结尾

示例

编译相关工具:

yum install -y gcc binutils
# 目录初始化
[root@xiexianbin_cn ~]# mkdir ldd-demo
[root@xiexianbin_cn ~]# cd ldd-demo/

# 文件内容
[root@xiexianbin_cn ldd-demo]# cat test.h
void print();
[root@xiexianbin_cn ldd-demo]# cat test.c
#include <stdio.h>
#include "test.h"

void print()
{
    printf("hello world!\n");
}
[root@xiexianbin_cn ldd-demo]# cat main.c
#include "test.h"

int main()
{
    print();
    return 0;
}

# gcc 编译
[root@xiexianbin_cn ldd-demo]# ls
main.c  test.c  test.h
[root@xiexianbin_cn ldd-demo]# gcc -c main.c test.c
[root@xiexianbin_cn ldd-demo]# gcc main.o test.o
[root@xiexianbin_cn ldd-demo]# ls
a.out  main.c  main.o  test.c  test.h  test.o

# 执行
[root@xiexianbin_cn ldd-demo]# ./a.out
hello world!

# 使用 ldd 查看 a.out
[root@xiexianbin_cn ldd-demo]# ldd a.out
	linux-vdso.so.1 =>  (0x00007ffc92fc3000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fb6b0c02000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb6b0fcf000)
[root@xiexianbin_cn ldd-demo]# ldd *

a.out 依赖于 libc.so.6,路径为 /lib/libc.so.6

静态库

[root@xiexianbin_cn ldd-demo]# ls
main.c  test.c  test.h
[root@xiexianbin_cn ldd-demo]# gcc -c test.c
[root@xiexianbin_cn ldd-demo]# ls
main.c  test.c  test.h  test.o
[root@xiexianbin_cn ldd-demo]# ar rcs libtest.a test.o
[root@xiexianbin_cn ldd-demo]# ls
libtest.a  main.c  test.c  test.h  test.o
[root@xiexianbin_cn ldd-demo]# gcc main.c -L. -ltest
[root@xiexianbin_cn ldd-demo]# ls
a.out  libtest.a  main.c  test.c  test.h  test.o
[root@xiexianbin_cn ldd-demo]# ./a.out
hello world!
[root@xiexianbin_cn ldd-demo]# ldd a.out
	linux-vdso.so.1 =>  (0x00007ffc8c9fa000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f5f4647a000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f5f46847000)

与上面的基本一样。

动态链接库

[root@xiexianbin_cn ldd-demo]# ls
main.c  test.c  test.h
[root@xiexianbin_cn ldd-demo]# gcc test.c -shared -fPIC -o libtest.so
[root@xiexianbin_cn ldd-demo]# ls
libtest.so  main.c  test.c  test.h
[root@xiexianbin_cn ldd-demo]# gcc main.c -L. -ltest
[root@xiexianbin_cn ldd-demo]# ls
a.out  libtest.so  main.c  test.c  test.h
[root@xiexianbin_cn ldd-demo]# ./a.out
hello world!
[root@xiexianbin_cn ldd-demo]# ./a.out
hello world!

# a.out 依赖 libtest.so 库
[root@xiexianbin_cn ldd-demo]# ldd a.out
	linux-vdso.so.1 =>  (0x00007ffc509ce000)
	libtest.so (0x00007fd80275b000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fd80238e000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fd80295d000)
[root@xiexianbin_cn ldd-demo]# ldd libtest.so
	linux-vdso.so.1 =>  (0x00007ffc1ad75000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fe1e6141000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fe1e6710000)

说明:

  • 命令:gcc test.c -shared -fPIC -o libtest.so
    • -shared: 编译成的文件为动态链接库,不使用该选项相当于可执行文件
    • -fPIC: PIC(Position-Independent Code)编译为位置独立的代码,不用此选项是编译的代码是与位置相关的
  • 命令:gcc main.c -L. -ltest
    • -L.: 表示链接的文件在当前目录下
    • -ltest: 链接的文件名 gcc 会自动为其前面添加 lib,在其后边添加 .solibtest.so

若将 libtest.so 移动到 /tmp 目录

[root@xiexianbin_cn ldd-demo]# mv libtest.so /tmp/
[root@xiexianbin_cn ldd-demo]# ldd  a.out
	linux-vdso.so.1 =>  (0x00007fff8fb00000)
	libtest.so => not found
	libc.so.6 => /lib64/libc.so.6 (0x00007fb52c0bf000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb52c48c000)
[root@xiexianbin_cn ldd-demo]# ./a.out
./a.out: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

可以看到 libtest.so => not found,执行 a.out 失败。将 libtest.so 移动到 /usr/lib64/ 目录也可以正常使用:

[root@xiexianbin_cn ldd-demo]# mv /tmp/libtest.so /usr/lib64/
[root@xiexianbin_cn ldd-demo]# ./a.out
hello world!
[root@xiexianbin_cn ldd-demo]# ldd a.out
	linux-vdso.so.1 =>  (0x00007fffe87f4000)
	libtest.so => /lib64/libtest.so (0x00007f808dc89000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f808d8bc000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f808de8b000)

说明:

  • /usr/lib64/ 为默认动态链接库的目录,可以通过 LD_LIBRARY_PATH 查看其它的动态链接库位置
专栏文章
  1. Linux 基础知识
  2. chroot 技术简介
  3. Linux 中个目录说明
  4. 进程、线程、协程的作用和区别
  5. Linux 动态链接库和静态链接库(当前)
  6. Linux PAM 可插拔认证模块介绍
  7. Linux limits.conf 详解与配置
  8. Linux Signal 信号量介绍
  9. Linux GDB 调试
  10. Linux core dump 文件介绍
  11. Linux procfs 介绍
  12. Linux 进程 /proc/PID/status 深入分析
  13. Linux sysfs 介绍
  14. Linux nsswithch.conf 详解
  15. Linux Systemd 介绍
  16. Linux Interrupt 中断介绍
  17. Linux namespace 介绍
  18. Linux Cgroups 介绍
  19. Linux Capabilities 介绍
最新评论
加载中...
Home Archives Categories Tags Statistics