文档章节

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

wangxuwei
 wangxuwei
发布于 2016/05/08 08:31
字数 923
阅读 27
收藏 0

  linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名。二者都使用广泛。本文主要讲动态库方面知识。

   

   基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库,使用ldd命令查看 

  1. # ldd /bin/ls

  2. linux-vdso.so.=> (0x00007fff597ff000)

  3. libselinux.so.=> /lib64/libselinux.so.(0x00000036c2e00000)

  4. librt.so.=> /lib64/librt.so.(0x00000036c2200000)

  5. libcap.so.=> /lib64/libcap.so.(0x00000036c4a00000)

  6. libacl.so.=> /lib64/libacl.so.(0x00000036d0600000)

  7. libc.so.=> /lib64/libc.so.(0x00000036c1200000)

  8. libdl.so.=> /lib64/libdl.so.(0x00000036c1600000)

  9. /lib64/ld-linux-x86-64.so.(0x00000036c0e00000)

  10. libpthread.so.=> /lib64/libpthread.so.(0x00000036c1a00000)

  11. libattr.so.=> /lib64/libattr.so.(0x00000036cf600000)

   这么多so,是的。使用ldd显示的so,并不是所有so都是需要使用的,下面举个例子

main.cpp

  1. #include <stdio.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main ()
    {
       cout << "test" << endl;
       return 0;
    }

   使用缺省参数编译结果

  1. # g++ -o demo main.cpp

  2. # ldd demo

  3.     linux-vdso.so.=> (0x00007fffcd1ff000)

  4.         libstdc++.so.=> /usr/lib64/libstdc++.so.(0x00007f4d02f69000)

  5.         libm.so.=> /lib64/libm.so.(0x00000036c1e00000)

  6.         libgcc_s.so.=> /lib64/libgcc_s.so.(0x00000036c7e00000)

  7.         libc.so.=> /lib64/libc.so.(0x00000036c1200000)

  8.         /lib64/ld-linux-x86-64.so.(0x00000036c0e00000)

   如果我链接一些so,但是程序并不用到这些so,又是什么情况呢,下面我加入链接压缩库,数学库,线程库

  1. # g++ -o demo -lz -lm -lrt main.cpp

  2. # ldd demo

  3.         linux-vdso.so.=> (0x00007fff0f7fc000)

  4.         libz.so.1 => /lib64/libz.so.1 (0x00000036c2600000)

  5.         librt.so.1 => /lib64/librt.so.1 (0x00000036c2200000)

  6.         libstdc++.so.=> /usr/lib64/libstdc++.so.(0x00007ff6ab70d000)

  7.         libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)

  8.         libgcc_s.so.=> /lib64/libgcc_s.so.(0x00000036c7e00000)

  9.         libc.so.=> /lib64/libc.so.(0x00000036c1200000)

  10.         libpthread.so.=> /lib64/libpthread.so.(0x00000036c1a00000)

  11.         /lib64/ld-linux-x86-64.so.(0x00000036c0e00000)

  看看,虽然没有用到,但是一样有链接进来,那看看程序启动时候有没有去加载它们呢

  1. # strace ./demo

  2.     execve("./demo", ["./demo"], [/* 30 vars */]) = 0

  3.     ... = 0

  4.     open("/lib64/libz.so.1", O_RDONLY) = 3

  5.     ...

  6.     close(3) = 0

  7.     open("/lib64/librt.so.1", O_RDONLY) = 3

  8.     ...

  9.     close(3) = 0

  10.     open("/usr/lib64/libstdc++.so.6", O_RDONLY) = 3

  11.     ...

  12.     close(3) = 0

  13.     open("/lib64/libm.so.6", O_RDONLY) = 3

  14.     ...

  15.     close(3) = 0

  16.     open("/lib64/libgcc_s.so.1", O_RDONLY) = 3

  17.     ...

  18.     close(3) = 0

  19.     open("/lib64/libc.so.6", O_RDONLY) = 3

  20.     ...

  21.     close(3) = 0

  22.     open("/lib64/libpthread.so.0", O_RDONLY) = 3

  23.     ...

  24.     close(3) = 0

  25.     ...

  看,有加载,所以必定会影响进程启动速度,所以我们最后不要把无用的so编译进来,这里会有什么影响呢?

   大家知不知道linux从程序(program或对象)变成进程(process或进程),要经过哪些步骤呢,这里如果详细的说,估计要另开一篇文章。简单的说分三步:

    1、fork进程,在内核创建进程相关内核项,加载进程可执行文件;

    2、查找依赖的so,一一加载映射虚拟地址

    3、初始化程序变量。

  可以看到,第二步中dll依赖越多,进程启动越慢,并且发布程序的时候,这些链接但没有使用的so,同样要一起跟着发布,否则进程启动时候,会失败,找不到对应的so。所以我们不能像上面那样,把一些毫无意义的so链接进来,浪费资源。但是开发人员写makefile 一般有没有那么细心,图省事方便,那么有什么好的办法呢。继续看下去,下面会给你解决方法。

  先使用 ldd -u demo 查看不需要链接的so,看下面,一面了然,无用的so全部暴露出来了吧

  1. # ldd -u demo

  2. Unused direct dependencies:

  3.         /lib64/libz.so.1

  4.         /lib64/librt.so.1

  5.         /lib64/libm.so.6

  6.         /lib64/libgcc_s.so.1

  使用 -Wl,--as-needed 编译选项

  1. # g++ -Wl,--as-needed -o demo -lz -lm -lrt main.cpp

  2. # ldd demo

  3.         linux-vdso.so.=> (0x00007fffebfff000)

  4.         libstdc++.so.=> /usr/lib64/libstdc++.so.(0x00007ff665c05000)

  5.         libc.so.=> /lib64/libc.so.(0x00000036c1200000)

  6.         libm.so.=> /lib64/libm.so.(0x00000036c1e00000)

  7.         /lib64/ld-linux-x86-64.so.(0x00000036c0e00000)

  8.         libgcc_s.so.=> /lib64/libgcc_s.so.(0x00000036c7e00000)

  9. # ldd -u demo

  10. Unused direct dependencies:


  呵呵,办法很简单省事吧,本文主要讲so依赖的一些问题,下一篇将介绍so的路径方面一些不为人知的小秘密


本文转载自:http://blog.chinaunix.net/uid-27105712-id-3313293.html

共有 人打赏支持
wangxuwei
粉丝 24
博文 332
码字总数 115454
作品 0
杭州
其他
私信 提问
linux下so动态库一些不为人知的秘密(中)

上一篇(linux下so动态库一些不为人知的秘密(上))介绍了linux下so一些依赖问题,本篇将介绍linux的so路径搜索问题。 我们知道linux链接so有两种途径:显示和隐式。所谓显示就是程序主动调...

wangxuwei
2016/05/08
17
0
Eclipse Debug不为人知的秘密

Debug视图 认识debug视图,红色部分框为线程堆栈视图,黄色部分框为表达式、断点、变量视图,蓝色部分为代码视图。 线程堆栈视图 分别介绍一下这几个按钮的含义: 1.表示当前实现继续运行直到...

i33
2012/03/29
0
0
国内十个奇葩网站,你去过几个?

1、毛毛网 http://www.mvomvo.com/ 还在为送礼发愁吗?在这里和你一起发现礼物.分享礼物.收藏礼物 2、心理网-改变从这里开始 http://www.xinli001.com/        一个简单、温暖的心理网站...

刘磊磊
2013/01/23
928
6
windows平台开发,在eclipse中使用java如何调用.so文件,试了半天还是不行:

windows平台开发,在eclipse中使用java如何调用.so文件,试了半天还是不行: 1、java工程项目不是安卓项目,是web项目, 2、.so是linux下生成的动态库,.dll是windows下生成的动态库,网上几...

hhl3136
2017/11/21
537
7
[动态库]深入分析Windows和Linux动态库应用异同

摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理。 ...

龙宝宝
2011/08/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

设计模式之工厂模式

本篇博文主要翻译这篇文章: https://www.journaldev.com/1392/factory-design-pattern-in-java 由于翻译水平有限,自认为许多地方翻译不恰当,欢迎各位给出宝贵的建议,建议大家去阅读原文。...

firepation
15分钟前
2
0

中国龙-扬科
18分钟前
1
0
简单谈谈vue的过渡动画

在vue中,实现过渡动画一般是下面这样: `<``transition` `name``=``"fade"``>``<``div``></``div``>``</``transition``>` 用一个transition对元素或者组件进行封装. 在过渡的时候,会......

嫣然丫丫丫
24分钟前
2
0
文件及目录处理

file_get_contents file_put_contens fopen r/r+ 只读打开,指针开头 w/w+ 写入打开,指针开头,清空文件,不存创建 a/a+ 追加打开,指针末尾,不存创建 x/x+ 创建模式打开 b 二进制打开 t 文本打开...

关元
26分钟前
1
0
如何在Angular中使用better-scroll插件

由于需要在一个固定的的高度做无限滚动,本来css的overflow-y也可以完成的,奈何安卓不是很流畅,还很生硬,就是用了第三方库better-scroll,配合angular的ng-content。angular的ng-content和...

前端攻城老湿
32分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部