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

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

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

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

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

[root@~/wade/codeReview/learningc]# strace pwd
execve("/bin/pwd", ["pwd"], [/* 24 vars */]) = 0
brk(0) = 0x1c77000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb011000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=29690, ...}) = 0
mmap(NULL, 29690, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f06eb009000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY) = 3
read(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) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1921096, ...}) = 0
mmap(NULL, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f06eaa5f000
mprotect(0x7f06eabe9000, 2097152, PROT_NONE) = 0
mmap(0x7f06eade9000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x7f06eade9000
mmap(0x7f06eadee000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f06eadee000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb008000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb007000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb006000
arch_prctl(ARCH_SET_FS, 0x7f06eb007700) = 0
mprotect(0x7f06eade9000, 16384, PROT_READ) = 0
mprotect(0x7f06eb012000, 4096, PROT_READ) = 0
munmap(0x7f06eb009000, 29690) = 0
brk(0) = 0x1c77000
brk(0x1c98000) = 0x1c98000
open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=99158576, ...}) = 0
mmap(NULL, 99158576, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f06e4bce000
close(3) = 0
getcwd("/root/wade/codeReview/learningc", 4096) = 32
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f06eb010000
write(1, "/root/wade/codeReview/learningc\n", 32/root/wade/codeReview/learningc
) = 32
close(1) = 0
munmap(0x7f06eb010000, 4096) = 0
close(2) = 0
exit_group(0) = ?

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

最佳实践

1. 程序test.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
main () {
printf ("1");
exit (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 test
Unused 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)

參考文章:

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

最新文章

  1. 【Java EE 学习 17 上】【dbutils和回调函数】
  2. 如何在HTML5 Canvas 里面显示 Font Awesome 图标
  3. oracle免客户端安装 plsql连接
  4. 调用KEditor批量上传图片
  5. Android Studio 生成Jar包时遇到的gradlew下载问题
  6. [论文笔记] Methodologies for Data Quality Assessment and Improvement (ACM Comput.Surv, 2009) (1)
  7. Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】
  8. MySQL数据库系统概述
  9. 自定义Attribute 服务端校验 客户端校验
  10. NSKeyValueObserving(KVO)
  11. bin
  12. HDU-4861-Couple doubi(数学题,难懂!难懂!)
  13. Flask-WTF 入门使用P1
  14. System.ServiceModel.CommunicationException: 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。
  15. 使用 HttpRequester 更方便的发起 HTTP 请求
  16. python基础之函数式编程
  17. 【开发】iOS入门 - UIViewController学习笔记
  18. shell 批量删除所有指定名字的目录
  19. 象棋start
  20. Reboot-less node fencing in Oracle Clusterware 11g Release 2

热门文章

  1. SAE微信公众号PHP SDK, token一直验证失败
  2. hdu3804(树链剖分)
  3. 改动EditPlus默认模板
  4. 金色的 SQL注意事项(1)
  5. Android四个存储数据的SharedPreferences
  6. Android使用百度定位SDK方法及错误处理
  7. FS SIP呼叫的消息线程和状态机线程
  8. SpringSecutiry权限管理手册
  9. Java中动态代理技术生成的类与原始类的区别
  10. 【翻译自mos文章】回收 asm磁盘空间的方法