【Linux--Lv4--Day4】静态库、共享库的创建以及使用

Day4
库的概念,特点以及分类

库的概念:库其实就是一个二进制文件,里面包含的都是一些已经编译好的代码,可以直接供函数调用
根据库的功能,可以划分为:标准C库、数学库、线程库等等
系统默认的库的搜索路径为:/lib or /usr/lib

库的特点

  • 库是事先编译好的,可以复用的代码
  • 在OS上运行的程序基本都需要库。使用库可以提高开发效率
  • 不同的操作系统下,库的文件格式不兼容,例如Windows 和 Linux下的库文件的格式就不兼容
  • Linux下包含静态库和共享库。
静态库

特点:使用到静态库时,在编译(链接时)把静态库中的相关代码复制到可执行文件中

优点程序中已包含代码,运行时不再需要加载库,运行速度更快

缺点

  1. 由于静态库中的文件是直接复制到可执行程序中,所以占用更多的磁盘空间,运行时占的内存更大
  2. 静态库升级后,原来用到静态库的程序都需要重新编译链接
静态库的创建及使用
  1. 首先确定库中函数的功能和接口
  2. 编写库源码 hello.c bye.c
  3. 分别编译生成目标文件 gcc -c hello.c -o hello
  4. 创建静态库 libstatic.a ar crs libstatic.a hello.o bye.o 其中:ar 命令,专门用来生成静态库文件,crs 是对应的选项,libstatic.a是生成的库文件的名称,Linux中要求库的名称 以lib 开头+库名称+.a ;后面的hello.o bye.o 即为要添加到库中的目标文件
  5. 编写应用程序 test.c (在此程序中 调用静态库中的函数 hello() 和 bye() )
  6. 编译test.c 并链接静态库 libhello.a gcc test.c -o test -L. -lstatic 这里的 -L 选项是 指定添加一个库的搜索路径 . 代表当前路径;因为库一般是调用系统中的lib库中的函数,一般不会搜索当前路径的库,因此在这个示例中,由于我们是在当前路径下创建的一个静态库,因此要用到-L 命令添加一个新的库的搜索路径, -l 指定库的名称 static,这里注意不是库文件名libstatic.a
  7. 执行程序,观察结果 ./test 就可以出结果,不用再加载库
  8. 查看静态库中的信息

总之 先编译函数生成目标文件 --> 生成静态库 --> 编写程序,用到了静态库中的函数 --> 编译、链接静态库 --> 执行

示例如下:

linux@linux:~/test/lv4/static$ vi hello.c
linux@linux:~/test/lv4/static$ gcc -c hello.c -o hello.o
linux@linux:~/test/lv4/static$ vi name.c
linux@linux:~/test/lv4/static$ gcc -c name.c -o name.o
linux@linux:~/test/lv4/static$ ls
hello.c  hello.o  name.c  name.o
linux@linux:~/test/lv4/static$ ar crs libstatic.a hello.o name.o
linux@linux:~/test/lv4/static$ ls
hello.c  hello.o  libstatic.a  name.c  name.o
linux@linux:~/test/lv4/static$ vi test.c
linux@linux:~/test/lv4/static$ gcc test.c -o test -L. -lstatic
linux@linux:~/test/lv4/static$ ./test
hello
My name is: Zdd
linux@linux:~/test/lv4/static$ cat -s hello.c
#include <stdio.h>

void hello()
{
	printf("hello\n");
	return;
}
linux@linux:~/test/lv4/static$ cat -s name.c
#include <stdio.h>

void name()
{
	printf("My name is: Zdd\n");
	return;
}
linux@linux:~/test/lv4/static$ cat -s test.c
#include <stdio.h>
void hello();
void name();

int main()
{
	hello();
	name();
	return 0;
}
共享库

特点:程序编译(链接)时仅记录用到了哪个共享库中的哪个符号,不复制共享库中的代码,程序运行时需要加载库

优点

  1. 程序不包含库中代码,尺寸小
  2. 多个程序可以共享一个库
  3. 库升级方便,不需要重新编译用到该共享库的程序
  4. 使用更加方便
共享库的创建及使用
  1. 确定库中的函数的功能,接口
  2. 编写库源码 hello.c bye.c
  3. 编译生成目标文件 gcc -c -fPIC hello.c bye.c -o hello bye 这里-fPIC 是指生成位置无关代码,即生成的目标文件代码可以被加载到任意位置执行,而不是在固定的地址才能执行(用到的是相对寻址,而不是绝对寻址),这是由共享库的特点决定的,必须要加此选项
  4. 创建共享库 gcc -shared -o libcommon.so.1 hello.o bye.o 共享库的名字必须 lib开头+库名+.so+.1(这通常是版本号)后面是添加的目标代码文件
  5. 为共享文件创建链接文件(目的: 是让编译器在编译时能够找到这个共享库)ln -s libcommon.so.1 libcommon.so 生成的 链接文件必须由.so结尾,不能再有版本号什么的后缀
  6. 编写应用程序 test.c
  7. 编译应用程序 并链接共享库libcommon.so gcc test.c -o test -L. -lcommon
  8. 加载共享库 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. 由于对于共享库来说,它并不是直接将库中的代码复制过来,它在执行的时候需要加载这个库,而它的搜索路径默认是在缺省路径下,而这里我们创建的共享库就在当前文件夹下,因此需要添加共享库的加载路径(这是方式之一)
  9. 执行程序 ./test 就可以出结果

总之
编译函数生成目标文件 --> 创建共享库 -->链接共享库 -->编写程序,用到了共享库中的函数 --> 编译、链接共享库 -->加载共享库–> 执行
相比静态库的创建和使用,多了链接共享库 和 加载共享库 这两个步骤

示例如下:

linux@linux:~/test/lv4/common$ vi hello.c
linux@linux:~/test/lv4/common$ gcc -c -fPIC hello.c -o hello.o
linux@linux:~/test/lv4/common$ vi name.c
linux@linux:~/test/lv4/common$ gcc -c -fPIC name.c -o name.o
linux@linux:~/test/lv4/common$ ls
hello.c  hello.o  name.c  name.o
linux@linux:~/test/lv4/common$ gcc -shared -o libcommon.so.1 hello.o name.o
linux@linux:~/test/lv4/common$ ls
hello.c  hello.o  libcommon.so.1  name.c  name.o
linux@linux:~/test/lv4/common$ ln -s libcommon.so.1 libcommon.so
linux@linux:~/test/lv4/common$ ls
hello.c  hello.o  libcommon.so  libcommon.so.1  name.c  name.o
linux@linux:~/test/lv4/common$ vi test.c
linux@linux:~/test/lv4/common$ vi common.h (通常将共享库中的函数声明都放在一个单独的头文件中,方便使用)
linux@linux:~/test/lv4/common$ gcc test.c -o test -L. -lcommon
linux@linux:~/test/lv4/common$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
linux@linux:~/test/lv4/common$ ./test
hello!
my name is xdz!
linux@linux:~/test/lv4/common$ cat -s hello.c
#include <stdio.h>
void hello()
{
	printf("hello!\n");
	return;
}
linux@linux:~/test/lv4/common$ cat -s name.c 
#include <stdio.h>
void name()
{
	printf("my name is xdz!\n");
	return;
}
linux@linux:~/test/lv4/common$ cat -s common.h
void hello();
void name();
linux@linux:~/test/lv4/common$ cat -s test.c
#include <stdio.h>
#include "common.h"

int main()
{
	hello();
	name();
	return 0;
}
如何找到共享库

为什么需要加载共享库,上面已经解释过了。
为了让系统找到要加载的共享库,有三种方法:

  • 把库拷贝到/usr/lib 和 /lib 目录下。(不推荐)
  • 在LD_LIBRARY_PATH环境变量中添加库所在路径(缺点就是下次还需要再次添加)
  • 添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值