前言
前面一篇文章介绍了静态链接库,静态链接库会直接注入目标程序,随目标程序一起加载进内存,会造成空间的浪费。而动态链接库是在目标程序运行时加载的,同时解决了程序更新、部署等问题。
1. 概念
linux应用程序使用的主要函数库均存放于/lib,/usr/lib目录下,其中采用*.so.*方式命名的是动态链接库。
2. 特点
- 对库函数的链接推迟到程序运行时执行;
- 可以实现进程之间的资源共享;
- 便于程序升级;
3. 制作流程
- gcc -c test.c -o test.o
- gcc -fpic -shared test.o -o libtest.so
- 将制作好的libtest.so拷贝至/usr/lib
说明:
- -fpic:使输出的对象模块是按照可重定位地址方式生成的
- -shared:指明生成动态链接库
4. 示例
1. 制作动态链接库
[root@192 dynamicDll]# cat test.c
#include <stdio.h>
void test(void)
{
printf("This is a Dynamic Link Library!\n");
}
[root@192 dynamicDll]# gcc -fpic -shared test.c -o libtest.so
[root@192 dynamicDll]# ls
libtest.so main.c test.c
[root@192 dynamicDll]#
如图所示,生成了动态链接库libtest.so。
2. 拷贝动态链接库至/usr/lib
[root@192 dynamicDll]# cp libtest.so /usr/lib
[root@192 dynamicDll]# ls
libtest.so main.c test.c
[root@192 dynamicDll]# ls /usr/lib
audit gcc libanl-2.17.so libc.so.6 libm-2.17.so libnss_dns-2.17.so libnss_nis.so.2 libstdc++.so.6 modprobe.d sendmail
binfmt.d gconv libanl.so.1 libdl-2.17.so libmemusage.so libnss_dns.so.2 libpcprofile.so libstdc++.so.6.0.19 modules sendmail.postfix
cpp grub libBrokenLocale-2.17.so libdl.so.2 libm.so.6 libnss_files-2.17.so libpthread-2.17.so libstdc++.so.6.0.28 modules-load.d sse2
debug i686 libBrokenLocale.so.1 libfreebl3.chk libnsl-2.17.so libnss_files.so.2 libpthread.so.0 libtest.so NetworkManager sysctl.d
dracut kbd libc-2.17.so libfreebl3.so libnsl.so.1 libnss_hesiod-2.17.so libresolv-2.17.so libthread_db-1.0.so os-release systemd
firewalld kdump libcidn-2.17.so libfreeblpriv3.chk libnss_compat-2.17.so libnss_hesiod.so.2 libresolv.so.2 libthread_db.so.1 polkit-1 tmpfiles.d
firmware kernel libcidn.so.1 libfreeblpriv3.so libnss_compat.so.2 libnss_nis-2.17.so librt-2.17.so libutil-2.17.so python2.7 tuned
fontconfig ld-2.17.so libcrypt-2.17.so libgcc_s-4.8.5-20150702.so.1 libnss_db-2.17.so libnss_nisplus-2.17.so librt.so.1 libutil.so.1 rpm udev
games ld-linux.so.2 libcrypt.so.1 libgcc_s.so.1 libnss_db.so.2 libnss_nisplus.so.2 libSegFault.so locale rtkaio yum-plugins
[root@192 dynamicDll]#
3. 动态链接库的调用
一个应用程序:
[root@192 dynamicDll]# cat main.c
#include <stdio.h>
void test(void);
int main(void)
{
printf("Begin!\n");
test();
return 0;
}
[root@192 dynamicDll]#
编译运行:
[root@192 dynamicDll]# cat main.c
#include <stdio.h>
void test(void);
int main(void)
{
printf("Begin!\n");
test();
return 0;
}
[root@192 dynamicDll]#
[root@192 dynamicDll]# gcc -o main main.c ./libtest.so
[root@192 dynamicDll]# ls
libtest.so main main.c test.c
[root@192 dynamicDll]# ./main
Begin!
This is a Dynamic Link Library!
[root@192 dynamicDll]# readelf -d main
Dynamic section at offset 0xe18 contains 25 entries:
标记 类型 名称/值
0x0000000000000001 (NEEDED) 共享库:[./libtest.so]
0x0000000000000001 (NEEDED) 共享库:[libc.so.6]
0x000000000000000c (INIT) 0x4004c8
0x000000000000000d (FINI) 0x4006a4
0x0000000000000019 (INIT_ARRAY) 0x600e08
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x600e10
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x0000000000000004 (HASH) 0x400278
0x0000000000000005 (STRTAB) 0x4003a8
0x0000000000000006 (SYMTAB) 0x4002b8
0x000000000000000a (STRSZ) 115 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x601000
0x0000000000000002 (PLTRELSZ) 96 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x400468
0x0000000000000007 (RELA) 0x400450
0x0000000000000008 (RELASZ) 24 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x400430
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x40041c
0x0000000000000000 (NULL) 0x0
[root@192 dynamicDll]#