静态链接库.a,OBJ文件.o,动态链接库.so都是啥?(待补充)

转自https://www.cnblogs.com/king-lps/p/7757919.html

1.obj文件,.o

也就是用户自己写的用于连接的文件,是特殊的二进制文件。根据里面不只有程序指令,还有一些相关信息,告诉连接器如何根据多个.o文件及链接库文件.a及.so进行修改从而形成最后的可执行二进制文件。

2.静态链接库文件,.a

静态链接库文件本质上为.o的打包,连接器会将其复制(应该是用到了那个库函数就copy哪个)到可执行二进制文件中。与.o文件不同的是,.a一定要放在引用它的.o文件后面,函数定义才能被找到,而.o并不会这样。

特点:

l 静态库对函数库的链接是放在编译时期完成的。

l 程序在运行时与函数库再无瓜葛,移植方便。

l 浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。

问题:

clip_image021[4]

另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)

3.动态链接库文件,.so(没看太懂)

相对于静态链接(static link)拷贝原有的程序代码进可执行文件,动态链接不那样做,link editor把一些信息写进可执行文件而已。

例如,需要的程序库名、函数名等,最后执行的时候,必须呼叫dynamic linker來做program intepreter(程序直译器?),dynamic linker会根据需要的函数库名称,把想要的函数名字创造一个可执行的image放到内存,所以执行有动态链接的执行文件,最后通常都是由OS的exec系列的system call与dynamic linker如ld.so联合完成。(一个显示调用的系统调用和动态链接库配合运行实现动态链接库函数的调用)
dynamic linker通常会做如下工作:

(1)把可执行文件的内容加载到process image
(2)把shared obj需要的东西加载到process image
(3)完成relocation(再布置)
       本来这些obj文件里面的虚拟地址应该和文件的地址有相对应的偏移(offset),而文件首地址通常是0x08040800,这是绝对虚拟地址,但它只适合可执行文件,例如Linux extuable file通常是:
          file offset         virtual  address
          -----------         ----------------
          0x0                 0x08048000
          0x100             0x08048100
       shared obj函数库里的程序代码必须为位置无关代码Position
Independent Code (PIC),也就是说它的地址可能会随不同process而有不同,例如,一个程序只用了libc.so、
ld-linux.so,通常这时候lib.so是从0x40017000开始的,但如果另一个程序多用一个libm.so,那么libc.so从
0x40034000开始两个的printf参照(reference),就会有不同的地址,所以这种动态函数库的内部资料就要说明这些codePIC。

动态库特点总结:

l 动态库把对一些库函数的链接载入推迟到程序运行的时期。

l 可以实现进程之间的资源共享。(因此动态库也称为共享库,不重复载入)

l 将一些程序升级变得简单。

l 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

Window与Linux执行文件格式不同,在创建动态库的时候有一些差异。

l 在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字

l Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。

与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Makefile文件的编写: ```makefile # Makefile for ParseConfig # 定义编译器 CC = gcc # 定义编译选项 CFLAGS = -Wall -Wextra -Werror -I./lib # 定义链接选项 LDFLAGS = -L./lib -lParseConfig # 定义动态库名字和静态库名字 LIBNAME = ParseConfig DYNLIBNAME = lib$(LIBNAME).so STALIBNAME = lib$(LIBNAME).a # 定义源文件和目标文件 SRC = ./src/main.c ./src/ParseConfig.c OBJ = $(SRC:.c=.o) # 定义可执行文件名字 TARGET = ParseConfig # 默认生成静态库、动态库和可执行文件 all: $(DYNLIBNAME) $(STALIBNAME) $(TARGET) # 链接生成动态库 $(DYNLIBNAME): ./src/ParseConfig.o $(CC) -shared -o $@ $^ # 链接生成静态库 $(STALIBNAME): ./src/ParseConfig.o ar rcs $@ $^ # 编译生成目标文件 %.o: %.c $(CC) $(CFLAGS) -fPIC -c -o $@ $< # 链接生成可执行文件 $(TARGET): $(OBJ) $(CC) $(LDFLAGS) -o $@ $^ # 生成strip后的可执行文件 static_release: $(TARGET) strip $(TARGET) # 生成不strip的可执行文件 debug_release: CFLAGS += -g debug_release: $(TARGET) # 清除生成的目标文件、库文件和可执行文件 clean: rm -f $(OBJ) $(DYNLIBNAME) $(STALIBNAME) $(TARGET) .PHONY: all static_release debug_release clean ``` 上面的Makefile文件分别定义了编译器、编译选项、链接选项、动态库名字和静态库名字、源文件和目标文件、可执行文件名字等。同时,还定义了生成动态库、静态库和可执行文件的规则,以及生成strip后的可执行文件和不strip的可执行文件的规则。最后,还定义了清除生成的目标文件、库文件和可执行文件的规则。 执行make命令即可生成静态库libParseConfig.a,动态库libParseConfig.so和ParseConfig程序;执行make static_release命令,会生成strip后的ParseConfig可执行文件;执行make debug_release命令,会生成不strip的ParseConfig可执行文件。 注意:Makefile文件中的缩进需要使用Tab键,而不能使用空格键。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值