Linux动态库与静态库

1. 测试代码

测试程序:

//////////////////test.h///////////////////
#ifndef __TEST_H__
#define __TEST_H__
#include <stdio.h>
#include <unistd.h>

void func();//声明函数

#endif


//////////////////test.c///////////////////
#include "test.h"
//作为库文件使用 编译动态库不能出现main函数
void func() //实现
{
  printf("I am dynamic\n"); //简单的打印
}

//////////////////main.c///////////////////
#include "test.h"

int main()
{
  func();//使用
  return 0;
}

2. 动态库与静态库初识
  • 静态库(.a): 程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
  • 动态库(.so): 程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
3. 动态库
3.1 库搜索路径
  • 从左到右搜索 -L 指定的目录
  • 由环境变量指定的目录(LD_LIBRARY_PATH),该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。
  • 由系统指定的目录
    • /usr/lib
    • /usr/local/lib

运行时动态库的搜索路径的先后顺序是:

  1. 编译目标代码时指定的动态库搜索路径
  2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
  3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径
  4. 默认的动态库搜索路径/usr/lib和/usr/local/lib
3.1 生成动态库
  • gcc / g++
  • -shared :表示生成共享库格式
  • -fPIC:产生位置无关码 (position independent code)
  • -o 后面跟生成的动态库的名字
    前缀:lib
    后缀:.so
    libfunc.so ==> func 称之为动态库的名字

示例:

[test@localhost dynamic]$ ls
main.c  test.c  test.h
[test@localhost dynamic]$ gcc -shared -fPIC test.c -o libfunc.so
[test@localhost dynamic]$ ls
libfunc.so  main.c  test.c  test.h
3.2 使用动态库

编译可执行程序的时候,一定要告诉编译器,我们链接的动态库是哪个
选项:

  • -L [path] —— 指定链接动态库所在的路径
  • -l [库的名称(去掉前缀和后缀的)] —— 链接动态库

输出结果:

[test@localhost dynamic]$ gcc main.c -o main -L . -l func 
[test@localhost dynamic]$ ls
libfunc.so  main  main.c  test.c  test.h
[test@localhost dynamic]$ ./main
I am dynamic
3.3 查看当前程序依赖的动态库
  • 命令:ldd [可执行程序] —— 查看当前程序依赖的动态库文件
    在这里插入图片描述
3.4 查看文件属性
  • 命令:file [可执行程序] —— 查看文件的属性
    在这里插入图片描述
3.5 移动或删掉动态库

可执行文件是依赖这个动态库的,那么删掉或着移动动态库文件,程序是不能运行的。
在这里插入图片描述
可以通过修改环境变量LD_LIBRARY_PATH,指定除了文件默认搜索路径以外的路径。像上面这种.so动态库文件没有在缺省目录下 /usr/local/lib 和/usr/lib,那么就需要指定环境变量
在这里插入图片描述
但是,这样设定的环境变量不是永久生效的,重新打开一个终端,照样是不可以运行的
在这里插入图片描述
永久性添加:
因为上面的方法是临时设置环境变量 LD_LIBRARY_PATH ,重启或打开新的 Shell 之后,一切设置将不复存在。可以将该 LD_LIBRARY_PATH 的 export 语句写到系统文件中,例如:~/.bash_profile
在这里插入图片描述
最后使配置生效,重新打开终端,就可以运行了。

source ~/.bash_profile 

在这里插入图片描述

4. 静态库
4.1 生成静态库
  • 前缀:lib
  • 后缀:.a
    libfunc.a ==> func就是静态库的名字
  • ar -rc lib[名字].a 依赖的文件
    注意:依赖文件不是源文件,而是gcc -c 以后生成的.o 目标文件

示例:

[test@localhost static]$ ls
main.c  test.c  test.h
#生成静态库需要的目标文件
[test@localhost static]$ gcc -c test.c -o test.o
[test@localhost static]$ ls
main.c  test.c  test.h  test.o
#生成静态库
# ar 是归档工具,rc表示(replace and create)
[test@localhost static]$ ar -rc libfunc.a test.o
[test@localhost static]$ ls
libfunc.a  main.c  test.c  test.h  test.o
#查看静态库的目录列表
[test@localhost static]$ ar -tv libfunc.a 
rw-rw-r-- 1001/1001   1496 Apr 16 16:01 2021 test.o
# t:列出静态库中的目录列表  
# v:verbose 详细信息
4.2 使用静态库
[test@localhost static]$ gcc main.c -o main -L . -l func
[test@localhost static]$ ls
libfunc.a  main  main.c  test.c  test.h  test.o
[test@localhost static]$ ./main
I am static

再次查看文件属性以及依赖的库:
在这里插入图片描述
使用静态链接静态库:

gcc -static main.c -o main -L . -l func

再次查看文件属性以及依赖的库:
在这里插入图片描述

4.3 移动或删掉静态库

和动态库不同,在测试目标文件生成后,将静态库删掉或者移动,程序可以照样运行
在这里插入图片描述

5. 使用外部库(延伸)

系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。

代码:

#include <math.h>
#include <stdio.h>

int main()
{
 	double x = pow(2.0, 3.0);
 	printf("The cubed is %f\n", x);
 	return 0;
}
//输出结果:
The cubed is 8.000000

链接外部库:

# -lm 表示要链接libm.so或者libm.a 库文件,即 m库
gcc calc.c -o calc -lm

查看文件属性以及依赖的库:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值