linux动态库与静态库

动态库与静态库

​ 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始。尽量不重复做别人已经做过的事,“站在巨人的肩膀上”做事情。

​ 根据链接时期的不同,库又有:静态库和共享库(动态库)。

​ 二者的不同点在于代码被载入的时刻不同, 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

​ 一般gcc在编译的时候默认使用动态库,可以直接添加-static强制使用静态库。

​ 静态库的名字一般是libxxx.a(Linux).

​ 动态库的名字一般是libxxx.so(Linux),有时候也是 libxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号。

1 file命令

​ file程序是用来判断文件类型的,并且可以查看文件是否使用了动态库。

where@ubuntu:~$ file /bin/ls
/bin/ls: ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=de9c5af34773e23cf554e0da78320e76a3b85120, stripped

2 ldd命令

​ ldd是英文List dynamic dependencies的缩写,用来查看动态库,如果目标程序没有链接动态库,则打印“not a dynamic executable” (不是动态可执行文件)

where@ubuntu:~$ ldd /bin/ls
Linux-gate.so.1 =>  (0xb7765000)
libseLinux.so.1 => /lib/i386-Linux-gnu/libseLinux.so.1 (0xb772a000)
libacl.so.1 => /lib/i386-Linux-gnu/libacl.so.1 (0xb7721000)
libc.so.6 => /lib/i386-Linux-gnu/libc.so.6 (0xb7572000)
libpcre.so.3 => /lib/i386-Linux-gnu/libpcre.so.3 (0xb7534000)
libdl.so.2 => /lib/i386-Linux-gnu/libdl.so.2 (0xb752f000)
/lib/ld-Linux.so.2 (0x800d3000)
libattr.so.1 => /lib/i386-Linux-gnu/libattr.so.1 (0xb7529000)

3 编译动态库
  • 编写mylib.h

 #ifndef __MYLIB_H__
 #define __MYLIB_H__
 int test();
 #endif
  • 编写mylib.c

 #include <stdio.h>
 #include "mylib.h"
 int test()
 {
         printf("mytest\n");
 }
  • 编译成mylib.o文件

gcc -fPIC -c mylib.c

​ -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),  则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意  位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

  • 链接成动态库libmy.so

gcc  -shared  mylib.o -o libmy.so

  • 编译跟链接一起执行

gcc -shared -fPIC mylib.c -o libmy.so

4 调用动态库
  • 调用动态库,编写调用代码test.c

 #include "mylib.h"
 int main()
 {
         test();
         return 0;
 }
  • 编译时带上库路径

gcc -o test test.c libmy.so 

  • 或者指定链接路径

gcc -o test test.c -L./ -lmy
  • 设置环境变量LIBRARY_PATH

export LIBRARY_PATH=$LIBRARY_PATH/homw/where/lib   #/home/where为我当前库路径
gcc -o test test.c -lmy
  • 或者把库拷贝到系统库路径中

mv libmy.so /usr/lib #或者 /lib /usr/local/lib 
gcc -o test test.c -lmy

gcc默认查找动态的顺序:

1、-L参数指定的路径

2、LIBRARY_PATH环境变量指明库搜索路径

3、gcc内定库/lib、/usr/lib、/usr/local/lib

5 头文件引用
gcc test.c -o test -lmy
  • 指定包含的文件路径

 gcc test.c -o test -I./
  • 修改C_INCLUDE_PATH

export C_INCLUDE_PATH=$C_INCLUDE_PATH:/home/where/lib
gcc test.c -o test

  • gcc默认查找头文件的顺序

1、当前编译路径
2、-I 指定的路径
3、C_INCLUDE_PATH,CPLUS_INCLUDE_PATH环境变量等路径
4、再找系统内定目录如/usr/include、/usr/local/include

6运行时库查找

1、在配置文件/etc/ld.so.conf中指定动态库搜索路径

sudo vi /etc/ld.so.conf.d/mylib.conf #新建mylib.conf写入你自己的库路径,如/home/where/lib
sudo ldconfig                           #更新一下缓存才能生效

2、通过环境变量LD_LIBRARY_PATH指定动态库搜索路径

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/where/lib

3、默认的动态库搜索路径/lib、/usr/lib

7 编译静态库
  • 编写mylib.h

 #ifndef __MYLIB_H__
 #define __MYLIB_H__
 int test();
 #endif
  • 编写mylib.c

 #include <stdio.h>
 #include "test.h"
 int test()
 {
         printf("mytest\n");
 }
  • 编译成mylib.o文件

gcc -c mylib.c
  • 使用ar生成静态库

ar rcs libmy.a mylib.o 
参数r:#在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。
参数c:#创建一个库。不管库是否存在,都将创建。
参数s:#创建目标文件索引,这在创建较大的库时能加快时间。

8 调用静态库
  • 使用静态库编译

 gcc -o test test.c libmy.a 
  • 或者

gcc -o test test.c -L. -lmy
  • 在静态动态库都存在的情况,强制使用静态库

gcc -o test test.c -L. -lmy -static

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值