C语言底层原理(二):动态库、静态库

库的概念

库:实现了某一类功能的若干函数和二进制代码的集合。库的后缀名在不同平台上表现不同:
Windows:静态库:xxx.lib && 动态库:xxx.dll
Linux:静态库:xxx.a && 动态库:xxx.so

库分为静态库和动态库,与之对应的操作是静态链接和动态链接,静态库不能采用动态链接,同理,动态库也不能采用静态链接。

静态库:在链接的时候,函数库被完整的拷贝到可执行文件中,对应的链接方式成为静态链接,采用gcc -static指令。这里的可执行文件可以使单纯的一个a.out,也可以是一整个app或者程序。

动态库:相对于静态库,动态库并没有将库中所有的数据复制到可执行文件中,在程序运行的时候才会被动态载入。

备注
动态链接可以理解成只是将声明文件复制到了程序中。在运行时根据预先设置的动态库的位置和这部分声明来调用对应的库。所以说动态库也叫共享库,共享在整个系统中。对于iOS系统而言,所有系统提供的.framework都是动态库且在各个app之间共享。但是iOS基于沙盒模式,其不允许用户自己创建动态的.framework。即使在iOS8之后可以创建动态framework,但其本质还是将动态库放入了app的沙盒中。iOS不允许包含自定义动态库的app上架到app store,所以iOS中的动态库只能应用在不上架app store的企业应用中。

静态库和动态库的区别和特点

静态库:
1、一旦链接完成,执行程序就和函数库没有任何关联
2、占用空间和资源,拷贝多次就会占用多份资源
3、会导致升级不便,一个地方修改就需要全量更新

动态库:
1、可以实现进程之间的资源共享
2、动态库把对一些库函数的链接载入推迟到程序运行的时期
3、将一些程序升级变得简单
4、可以通过显示调用做到链接载入完全由程序员在程序代码中控制
5、动态库的创建直接使用编译器即可创建动态库,不需要打包工具(ar、lib.exe

示例代码

文件夹结构:



mymath.h文件:

// mymath.h
#ifndef MYMATH_H
#define MYMATH_H
int xkadd(int a, int b);
int xksum(int a, int b);
#endif

mymath.c文件:

// mymath.c
int xkadd(int a, int b){
    return a+b;
}
int xksum(int a, int b){
    return a-b;
}

test.c文件:

// test.c
#include <stdio.h>
#include "mymath.h"// 自定义头文件
int main(){
    int a = 2;
    int b = 3;
    int sum = xkadd(a, b);
    printf("a=%d, b=%d, a+b=%d\n", a, b, sum);
}

静态库的生成和使用

// 进入函数库所在文件夹
caoxkdembp:static-lib caoxk$ cd /Users/caoxk/Demo/static-lib/lib 
// 将函数库编译成.o文件
caoxkdembp:lib caoxk$ gcc -c mymath.c
// 将.o文件使用ar工具生成.a静态库
caoxkdembp:lib caoxk$ ar -crv libmymath.a mymath.o
// 这一行是上一行命令执行结果的输出
a - mymath.o
caoxkdembp:lib caoxk$ cd ..
caoxkdembp:static-lib caoxk$ gcc test.c -L ./lib/ -lmymath
// 未告知编译器对应的头文件地址,执行命令后报错
test.c:4:10: fatal error: 'mymath.h' file not found
#include "mymath.h"// 自定义头文件
         ^~~~~~~~~~
1 error generated.
// 使用-I执行告诉编译器libmymath.a对应的头文件所在的地址
caoxkdembp:static-lib caoxk$ gcc test.c -L ./lib/ -lmymath -I ./lib/
// 执行可执行文件
caoxkdembp:static-lib caoxk$ ./a.out 
a=2, b=3, a+b=5

最终的文件夹结构:


Static-Lib End

总结
静态库的使用需要结合头文件,比如上面直接gcc主文件和mymath库时,没有使用-I path告知头文件的地址,所以会找不到头文件。而iOS中的framework其实包含三种文件:.h头文件、.a静态库、资源文件,如图片等

动态库/共享库的生成

caoxkdeMacBook-Pro:lib caoxk$ cd /Users/caoxk/Demo/dynamic-lib 
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ls
lib test.c
caoxkdeMacBook-Pro:dynamic-lib caoxk$ cd lib/
// 生成费共享的目标文件.o
caoxkdeMacBook-Pro:lib caoxk$ gcc -c -fpic mymath.c
// 使用gcc -shared的第二层意义来生成动态链接库
caoxkdeMacBook-Pro:lib caoxk$ gcc -shared -o libmymath.so mymath.o
caoxkdeMacBook-Pro:lib caoxk$ cd ..
caoxkdeMacBook-Pro:dynamic-lib caoxk$ pwd
/Users/caoxk/Demo/dynamic-lib
// -I:在./lib中寻找头文件;-L:在./lib中寻找;lmymath:连接libmymath.so动态库
caoxkdeMacBook-Pro:dynamic-lib caoxk$ gcc test.c -I ./lib/ -L ./lib/ -lmymath
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ./a.out 
dyld: Library not loaded: libmymath.so
  Referenced from: /Users/caoxk/Demo/dynamic-lib/./a.out
  Reason: image not found
Abort trap: 6
caoxkdeMacBook-Pro:dynamic-lib caoxk$ 

以上执行后,找不到动态库。因为mac中不能使用ldd指令,所以使用otool -L指令来查询执行文件中动态库的路径,如下:

caoxkdeMacBook-Pro:dynamic-lib caoxk$ ldd a.out 
-bash: ldd: command not found
caoxkdeMacBook-Pro:dynamic-lib caoxk$ otool -L a.out 
a.out:
    libmymath.so (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
caoxkdeMacBook-Pro:dynamic-lib caoxk$ 

以上结果表明:存在两个库,一个是文件路径为/usr/lib/libSystem.B.dylib的库,另一个是没有路径的libmymath.so库,也就是我们自定义的动态库没有设置路径,或者说是和a.out同级,将libmymath.so复制到a.out同级目录后运行:

caoxkdeMacBook-Pro:dynamic-lib caoxk$ cp lib/libmymath.so ./
caoxkdeMacBook-Pro:dynamic-lib caoxk$ ./a.out 
a=2, b=3, a+b=5
caoxkdeMacBook-Pro:dynamic-lib caoxk$ 

那么这个问题如何解决呢?首先我们知道动态库的寻址顺序是:
1、编译目标代码时指定的动态库搜索路径
2、环境变量LD_LIBRARY_PATH指定的动态库搜索路径
3、配置文件/etc/ld.so.conf中指定的动态库搜索路径
4、默认的动态库搜索路径/lib
5、默认的动态库搜索路径/usr/lib

也就是说我们需要告诉ld我们自定义的动态库的地址。这里引入一个指令:-Wl,-rpath=xxx(mac 中需要使用-Wl,rpath xxx或者-Wl,rpath,dir1,dir2,dir3)。这个指令的意思是指定runtime时的动态库寻址地址。而-L xxx是指定链接时库的寻址地址。

网上有几种方法:
1、将自动以的动态库复制到到/usr/lib中(权限不允许)
2、使用export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:《your_lib_path》设置临时增加链接动态库的路径(无效)
3、通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变(未测试)
4、使用-Wl -rpath(无效)

所以这种情况如何解决?-WL -rpath的正确用法是什么?问题暂时留存

动态库和静态库相关的指令

-fpic:生成非共享模式的目标文件
-static:一般来讲,很多函数库会有静态库和动态库两个版本。这个-static是编译阶段的链接选项,只在链接时不链接动态库,全部链接静态库,所以生成的可执行文件会比较大。
-shared:这个指令有两个意思。不作为链接选项时,是告诉gcc生成一个动态库,使用格式是gcc -shared xxx.o -o libxxx.so 。作为编译选项时,和-static对立,尽量使用动态库,只有在没有动态库时才链接静态库。是默认选项
比如:

// 生成非共享模式的机器码文件
caoxkdembp:lib caoxk$ gcc -fpic -c mymath.c
// 生成动态库
caoxkdembp:lib caoxk$ gcc -o libmymath.so mymath.o
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这里报错的原因是不加-shared,gcc默认执行的指令时编译并链接最终生成可执行文件,而mymath.c是一个函数库,当然没有main函数。没用main函数当然不能生成可执行文件

更多文章
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容