文档章节

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
不只能辨认人脸,Google 相册新推宠物辨识、品种分类功能

许多人家中都有毛小孩,但由于相册软件通常无法辨识猫狗,只能处理人脸,因此无法为宠物照片提供自动归类等方便的功能。 现在 Google 相册推出了宠物辨识的贴心功能。相册会自动帮你侦测宠物...

数码时代
2017/10/18
0
0
Unix一些实用但不为人知的命令

浮现在脑海的很多 Linux命令,其中一些不为人知,另一些则很常见,如下: xargs or parallel: 并行运行一些程序,命令有很多的选项 sed and awk: 广为人知并且非常有用的处理文本文件的命令,...

1169334005
2014/05/05
0
0
[动态库]深入分析Windows和Linux动态库应用异同

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

龙宝宝
2011/08/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

关于编程,你的练习是不是有效的?

最近由于工作及Solution项目的影响,我在重新学习DDD和领域建模的一些知识。然后,我突然就想到了这个问题,以及我是怎么做的? 对于我来说,提升技能的项目会有四种: 纯兴趣驱动的项目。即...

问题终结者
44分钟前
1
0
打开eclipse出现an error has occurred see the log file

解决方法: 1,打开eclipse安装目录下的eclipse.ini文件; 2,打开的文本文件最后添加一行 --add-modules=ALL-SYSTEM 3,保存重新打开Eclipse。...

任梁荣
昨天
4
0
搞定Northwind示例数据库,无论哪个版本的SQLServer都受用

Northwind数据库 从这里可以找到突破口: http://social.msdn.microsoft.com/Forums/zh-CN/Vsexpressvb/thread/8490a1c6-9018-40c9-aafb-df9f79d29cde 下面是MSDN: http://msdn2.microsoft......

QQZZFT
昨天
1
0
mysql主从同步,安装配置操作

准备 两台mysql服务,我这里准备了如下: 主库:192.168.176.128 从库:192.168.176.131 如何在Linux上安装mysql服务,请看https://blog.csdn.net/qq_18860653/article/details/80250499 操作...

小致dad
昨天
4
0
Redis的“死键”问题

大规模的数据库存储系统中,数据的生命周期管理是很有必要的;从业务角度发现过期数据,数据归档和数据碎片整理等。以MySQL为例,1个运行很久的TB级MySQL实例中,极有可能数百GB的数据,对业...

IT--小哥
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部