博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LinuxDLL加载优化方案
阅读量:6670 次
发布时间:2019-06-25

本文共 3722 字,大约阅读时间需要 12 分钟。

作者:zhanhailiang 日期:2014-10-26

linux程序动态库载入流程简单介绍

linux从程序(program或对象)变成进程(process或进程),简单说来须要经过三步:

  1. fork进程,在内核创建进程相关内核项,载入进程可运行文件;
  2. 查找依赖的.so,逐一载入映射虚拟地址;
  3. 初始化程序变量;

例如以下例通过strace查看pwd命令运行过程:

[root@~/wade/codeReview/learningc]# strace pwdexecve("/bin/pwd", ["pwd"], [/* 24 vars */]) = 0brk(0)                                  = 0x1c77000mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb011000access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY)      = 3fstat(3, {
st_mode=S_IFREG|0644, st_size=29690, ...}) = 0mmap(NULL, 29690, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f06eb009000close(3) = 0open("/lib64/libc.so.6", O_RDONLY) = 3read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\356\1\0\0\0\0\0"..., 832) = 832fstat(3, {
st_mode=S_IFREG|0755, st_size=1921096, ...}) = 0mmap(NULL, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f06eaa5f000mprotect(0x7f06eabe9000, 2097152, PROT_NONE) = 0mmap(0x7f06eade9000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x7f06eade9000mmap(0x7f06eadee000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f06eadee000close(3) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb008000mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb007000mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb006000arch_prctl(ARCH_SET_FS, 0x7f06eb007700) = 0mprotect(0x7f06eade9000, 16384, PROT_READ) = 0mprotect(0x7f06eb012000, 4096, PROT_READ) = 0munmap(0x7f06eb009000, 29690) = 0brk(0) = 0x1c77000brk(0x1c98000) = 0x1c98000open("/usr/lib/locale/locale-archive", O_RDONLY) = 3fstat(3, {
st_mode=S_IFREG|0644, st_size=99158576, ...}) = 0mmap(NULL, 99158576, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f06e4bce000close(3) = 0getcwd("/root/wade/codeReview/learningc", 4096) = 32fstat(1, {
st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb010000write(1, "/root/wade/codeReview/learningc\n", 32/root/wade/codeReview/learningc) = 32close(1) = 0munmap(0x7f06eb010000, 4096) = 0close(2) = 0exit_group(0) = ?

由此可见。假设仅仅载入必须的动态库对程序性能有非常重要的意义。

最佳实践

1. 程序test.c:

#include 
#include
#include
 main () {
("1"); (0);}

2. 编译test.c

[root@~/wade/codeReview/learningc/16]# gcc -lm -lpthread -o test test.c

3. 通过ldd test命令查看程序执行时须要载入哪些动态库:

[root@~/wade/codeReview/learningc/16]# ldd test	linux-vdso.so.1 =>  (0x00007fff6b5ff000)	libm.so.6 => /lib64/libm.so.6 (0x00007f394cefa000)	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f394ccdd000)	libc.so.6 => /lib64/libc.so.6 (0x00007f394c948000)	/lib64/ld-linux-x86-64.so.2 (0x00007f394d187000)

4. 通过ldd -u test命令查看程序载入了哪些不必要的动态库:

[root@~/wade/codeReview/learningc/16]# ldd -u testUnused direct dependencies: 	/lib64/libm.so.6	/lib64/libpthread.so.0

5. 通过-Wl,–as-needed编译选项仅仅载入必须的动态库:

[root@~/wade/codeReview/learningc/16]# gcc -Wl,--as-needed -lm -o test test.c [root@~/wade/codeReview/learningc/16]# ldd test	linux-vdso.so.1 =>  (0x00007fffdf5ff000)	libc.so.6 => /lib64/libc.so.6 (0x00007f5d862cd000)	/lib64/ld-linux-x86-64.so.2 (0x00007f5d8666a000)

參考文章:

  • linux下so动态库一些不为人知的秘密(上):
  • linux下so动态库一些不为人知的秘密(中):
  • linux下so动态库一些不为人知的秘密(中二):

版权声明:本文博主原创文章,博客,未经同意不得转载。

你可能感兴趣的文章
Facebook 调试工具Stetho配置入门
查看>>
win7安装ruby on rails开发环境
查看>>
.Net程序员安卓学习之路6:等待条
查看>>
[CareerCup] 6.3 Water Jug 水罐问题
查看>>
jQ效果:地址栏链接与a标签链接匹配
查看>>
poj 3180 The Cow Prom(tarjan+缩点 easy)
查看>>
【开源】Ionic项目实例《Ionic中文社区》
查看>>
求两个对角向上、列索引是偶数的元件和。
查看>>
ASP.NET农历时间显示(两)
查看>>
Java,JSP,JavaScript三和差异
查看>>
MySQL 调优基础(二) Linux内存管理
查看>>
netperf 而网络性能测量
查看>>
java反思reflect 分析Object物
查看>>
Java语法糖4:内部类
查看>>
android 消息推送
查看>>
Web Service Error wsse:InvalidSecurity Policy Requires Integrity (Doc ID 1370736.1)
查看>>
Android学习笔记之AndroidManifest.xml文件解析
查看>>
libpomelo 增加编译静态库cocos2d-x xcode 工程
查看>>
Spring1:Spring简介、环境搭建、源码下载及导入MyEclipse
查看>>
Java系列:报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path...
查看>>