Linux:理解动态库和静态库


库文件的定义:

打包了一堆实现了常用功能的代码文件

静态库与动态库

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
测试程序
/////////////add.h///////////////// 
#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif // __ADD_H__ 

/////////////add.c///////////////// 
#include "add.h"
int add(int a, int b)
{
	return a + b; 
}

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

/////////////sub.c///////////////// 
#include "sub.h"
int sub(int a, int b)
{
	return a - b; 
}

///////////main.c//////////////// 
#include <stdio.h>
#include "add.h"
#include "sub.h"

int main()
{
    int a = 10;
    int b = 20;
    printf("add(10, 20)=%d\n", a, b, add(a, b));
    
    a = 100;
    b = 20;
    printf("sub(%d,%d)=%d\n", a, b, sub(a, b));

	return 0;
}

生成静态库

[root@localhost linux]# ls
add.c add.h main.c sub.c sub.h 
[root@localhost linux]# gcc -c add.c -o add.o 
[root@localhost linux]# gcc -c sub.c -o sub.o

生成静态库
[root@localhost linux]# ar -rc libmymath.a add.o sub.o 
ar是gnu归档工具,rc表示(replace and create)

查看静态库中的目录列表
[root@localhost linux]# ar -tv libmymath.a rw-r--r-- 0/0 1240 Sep 15 16:53 2019 add.o rw-r--r-- 0/0 1240 Sep 15 16:53 2019 sub.o t:列出静态库中的文件
v:verbose 详细信息

[root@localhost linux]# gcc main.c -L. -lmymath

-L 指定库路径
-l 指定库名 
测试目标文件生成后,静态库删掉,程序照样可以运行。
  • 静态库的打包gcc - -c child.c -o child.o -> ar -cr libchild.a child.o
  • 静态库的命名方式lib***.a

在生成可执行程序的时候链接使用: gcc main.c -o main -lmychild -l指定库的名称

  1. 将库文件放置到指定路径路径下, 库文件的搜索路径是默认的路径: /usr/lib64 /usr/lib
  2. 设置环境变量 LIBRARY_PATH,将库文件所在目录的路径添加到这个环境变量的值中 export LIBRARY_PATH=$LIBRARY_PATH:.
  3. 使用gcc -L选项,指定连接库的搜索路径,gcc main.c -o main -L ./ -lmychild

生成动态库

动态库的打包gcc -fPIC -c child.c -o child.o -> gcc -shared child.o -o libmychild.so;

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 动态库的命名方式:libxxx.so

示例:

[root@localhost linux]# gcc -fPIC -c sub.c add.c 
[root@localhost linux]# gcc -shared -o libmymath.so *.o 
[root@localhost linux]# ls 
add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o

使用动态库

编译选项

  • l:链接动态库,只要库名即可(去掉lib以及版本号)
  • L:链接库所在的路径.

示例: gcc main.o -o main –L. -lhello

运行动态库

在运行程序时加载使用:仅仅针对动态库才会在运行时加载库文件

  1. 将库文件放置到指定路径路径下 库文件的搜索路径是默认的路径 /usr/lib64 /usr/lib
  2. 设置环境变量 LIBRARY_PATH,将库文件所在目录的路径添加到这个环境变量的值中 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
[root@localhost linux]# export LD_LIBRARY_PATH=. 
[root@localhost linux]# gcc main.c -lmymath 
[root@localhost linux]# ./a.out
add(10, 20)=30
sub(100, 20)=80

静态库的链接:

通常我们在连接静态库的时候,并不使用-static去指定gcc进行静态链接,因为-static的功能是在生成可执行程序的时候,所有的依赖库都是用静态库,而不是仅仅指定的那个库
通常在链接一个静态库的时候,都是将这个静态库放到指定路径下,就会直接链接这个静态库,而其他的依赖库依然会使用动态链接

  1. 将静态库放到指定的路径下,然后使用-L指定静态库的位置:gcc main.c 0o main -L./lib -lmychild
  2. gcc -static main.c -o main -L./lib -lmychild

如有不同见解,欢迎留言讨论~~

猜你喜欢

转载自blog.csdn.net/AngelDg/article/details/106787425
今日推荐