静态库(.a)和动态库(.so)详解

一、什么是库

库是早已写好的代码,现实中每个程序的代码不可能都是从零开始,都要依赖很多基础的底层库 ,因此库的存在意义非同寻常

二、静态库

程序在编译期间直接把静态库的代码链接到可执行文件中,如此程序运行时将不再依赖静态库

静态库的生成和使用

$ cat add.h
#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif  /* __ADD_H__ */

$ cat add.c
#include "add.h"

int add(int a, int b)
{
  return a + b;
}

$ cat sub.h
#ifndef __SUB_H__
#define __SUB_H__
int sub(int a, int b);
#endif /* __SUB_H__ */

$ cat sub.c
#include "add.h"

int sub(int a, int b)
{
  return a - b;
}

$ gcc -c add.c -o add.o
$ gcc -c sub.c -o sub.o

生成静态库
$ ar -rc libmymath.a add.o sub.o
ar:gnu 归档工具
rc:replace and create

查看静态库
$ ar -tv libmymath.a
rw-r--r-- 1005/1001   1240 Oct  2 11:36 2025 add.o
rw-r--r-- 1005/1001   1240 Oct  2 11:37 2025 sub.o

$ ll
total 28
-rw-r--r-- 1 mam mam   80 Oct  2 11:34 add.c
-rw-r--r-- 1 mam mam   97 Oct  2 11:32 add.h
-rw-r--r-- 1 mam mam 1240 Oct  2 11:36 add.o
-rw-r--r-- 1 mam mam 2688 Oct  2 11:37 libmymath.a
-rw-r--r-- 1 mam mam   80 Oct  2 11:34 sub.c
-rw-r--r-- 1 mam mam   95 Oct  2 11:33 sub.h
-rw-r--r-- 1 mam mam 1240 Oct  2 11:37 sub.o
drwxr-xr-x 2 mam mam   20 Oct  2 11:40 test_liba
drwxr-xr-x 2 mam mam   20 Oct  2 11:40 test_libso

$ pwd
/mam/mylib
$ cd test_liba
$ cat main.c
#include <stdio.h>
#include "add.h"
#include "sub.h"

int main()
{
  int a = 10;
  int b = 20;

  printf("add(%d, %d)=%d\n", a, b, add(a, b));
  printf("sub(%d,%d)=%d\n", a, b, sub(a, b));

  return 0;
}

编译
$ gcc main.c -I../ -L../ -lmymath
-I:指定头文件路径
-L:指定库路径
-l:指定库名
$ ll
total 16
-rwxr-xr-x 1 mam mam 8600 Oct  2 11:55 a.out
-rw-r--r-- 1 mam mam  264 Oct  2 11:36 main.c
或者
$ export LIBRARY_PATH=/mam/mylib
$ gcc main.c -I../ -lmymath
$ ll
total 16
-rwxr-xr-x 1 mam mam 8600 Oct  2 12:01 a.out
-rw-r--r-- 1 mam mam  264 Oct  2 11:36 main.c

运行
$ ./a.out

三、动态库

1、编译链接

  1. 符号解析
    链接器(ld)会扫描你的目标文件(.o 文件),找出其中所有未定义的符号(比如你调用了 add() 和 sub(),但二者的实现并不在你的代码里),然后在你通过 -l 选项指定的动态库(.so 文件)中查找这些符号是否存在,如果找不到,链接就会失败并报如下错误
    $ gcc main.c -I../
    /tmp/cceii5lL.o: In function `main':
    main.c:(.text+0x21): undefined reference to `add'
    main.c:(.text+0x49): undefined reference to `sub'
    collect2: error: ld returned 1 exit status
    
  2. 创建符号表和重定位表
    链接器不会把 add() 和 sub() 所在目标文件(.o 文件)的整个机器码复制到你的可执行文件里,相反,它会在生成的可执行文件中创建两张很重要的表
    • 符号表:记录了程序需要哪些外部函数(add() 和 sub()),以及这些函数来自哪个动态库(libmymath.so)
    • 重定位表:记录了代码中哪些地址是 “空的”,需要在运行时替换成动态库函数的真实地址

2、运行

动态链接器加载动态库并完成重定位后,交出控制权

3、注意

由于 Linux 的虚拟内存机制,使得物理内存中的一份动态库可以被所有需要用到该库的进程共享,因此动态库也被称为共享库

4、动态库的生成和使用

$ cat add.h
#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif  /* __ADD_H__ */

$ cat add.c
#include "add.h"

int add(int a, int b)
{
  return a + b;
}

$ cat sub.h
#ifndef __SUB_H__
#define __SUB_H__
int sub(int a, int b);
#endif /* __SUB_H__ */

$ cat sub.c
#include "add.h"

int sub(int a, int b)
{
  return a - b;
}

生成动态库
$ gcc -fPIC -c sub.c add.c
$ gcc -shared -o libmymath.so *.o

$ ll
total 36
-rw-r--r-- 1 mam mam   80 Oct  2 11:34 add.c
-rw-r--r-- 1 mam mam   97 Oct  2 11:32 add.h
-rw-r--r-- 1 mam mam 1240 Oct  2 12:14 add.o
-rw-r--r-- 1 mam mam 2688 Oct  2 11:37 libmymath.a
-rwxr-xr-x 1 mam mam 7920 Oct  2 12:14 libmymath.so
-rw-r--r-- 1 mam mam   80 Oct  2 11:34 sub.c
-rw-r--r-- 1 mam mam   95 Oct  2 11:33 sub.h
-rw-r--r-- 1 mam mam 1240 Oct  2 12:14 sub.o
drwxr-xr-x 2 mam mam   33 Oct  2 12:10 test_liba
drwxr-xr-x 2 mam mam   20 Oct  2 12:05 test_libso

$ pwd
/mam/mylib
$ cd test_libso
$ cat main.c
#include <stdio.h>
#include "add.h"
#include "sub.h"

int main()
{
  int a = 10;
  int b = 20;

  printf("add(%d, %d)=%d\n", a, b, add(a, b));
  printf("sub(%d,%d)=%d\n", a, b, sub(a, b));

  return 0;
}

编译
$ gcc main.o –I.. -L../ -lmymath
或者
$ export LIBRARY_PATH=/mam/mylib
$ gcc main.c -I../ -lmymath

$ ll
total 16
-rwxr-xr-x 1 mam mam 8552 Oct  2 12:18 a.out
-rw-r--r-- 1 mam mam  264 Oct  2 12:05 main.c

运行前需指定动态库路径
$ export LD_LIBRARY_PATH=/mam/mylib
$ ./a.out
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值