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

   
   基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库,使用ldd命令查看 
  1. # ldd /bin/ls
  2. linux-vdso.so.1 => (0x00007fff597ff000)
  3. libselinux.so.1 => /lib64/libselinux.so.1 (0x00000036c2e00000)
  4. librt.so.1 => /lib64/librt.so.1 (0x00000036c2200000)
  5. libcap.so.2 => /lib64/libcap.so.2 (0x00000036c4a00000)
  6. libacl.so.1 => /lib64/libacl.so.1 (0x00000036d0600000)
  7. libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  8. libdl.so.2 => /lib64/libdl.so.2 (0x00000036c1600000)
  9. /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)
  10. libpthread.so.0 => /lib64/libpthread.so.0 (0x00000036c1a00000)
  11. libattr.so.1 => /lib64/libattr.so.1 (0x00000036cf600000)

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

main.cpp

  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <string>
  4. using namespace std;
  5. int main ()
  6. {
  7. cout << "test" << endl;
  8. return 0;
  9. }

使用缺省参数编译结果

  1. # g++ -o demo main.cpp
  2. # ldd demo
  3. linux-vdso.so.1 => (0x00007fffcd1ff000)
  4. libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f4d02f69000)
  5. libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  6. libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  7. libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  8. /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)

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

  1. # g++ -o demo -lz -lm -lrt main.cpp
  2. # ldd demo
  3. linux-vdso.so.1 => (0x00007fff0f7fc000)
  4. libz.so.1 => /lib64/libz.so.1 (0x00000036c2600000)
  5. librt.so.1 => /lib64/librt.so.1 (0x00000036c2200000)
  6. libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007ff6ab70d000)
  7. libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  8. libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  9. libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  10. libpthread.so.0 => /lib64/libpthread.so.0 (0x00000036c1a00000)
  11. /lib64/ld-linux-x86-64.so.2 (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.1 => (0x00007fffebfff000)
  4. libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007ff665c05000)
  5. libc.so.6 => /lib64/libc.so.6 (0x00000036c1200000)
  6. libm.so.6 => /lib64/libm.so.6 (0x00000036c1e00000)
  7. /lib64/ld-linux-x86-64.so.2 (0x00000036c0e00000)
  8. libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000036c7e00000)
  9. # ldd -u demo
  10. Unused direct dependencies:

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

linux下so动态库一些不为人知的秘密(上)的更多相关文章

  1. linux下so动态库一些不为人知的秘密(中二)

    继续上一篇< linux下so动态库一些不为人知的秘密(中) >介绍so搜索路径,还有一个类似于-path,叫LD_RUN_PATH环境变量, 它也是把路径编译进可执行文件内,不同的是它只 ...

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

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

  3. linux下so动态库一些不为人知的秘密

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.    基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些 ...

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

    linux 下有动态库和静态库,动态库以.so为扩展名,静态库以.a为扩展名.二者都使用广泛.本文主要讲动态库方面知识.基本上每一个linux 程序都至少会有一个动态库,查看某个程序使用了那些动态库, ...

  5. linux下so动态库一些不为人知的秘密 系列

    http://blog.chinaunix.net/uid-27105712-id-3313293.html http://www.cnblogs.com/gulvzhe/archive/2012/0 ...

  6. linux下c++动态库的生成及使用

    文章来源于:http://hi.baidu.com/ablenavy/item/b498901c6826bbf587ad4e33 我的程序是一个类,在网上找了半天,都是c的例子,c++的类封装成静态库 ...

  7. Linux下创建动态库与使用

    参考文章:dll和so文件区别与构成:http://www.cnblogs.com/likwo/archive/2012/05/09/2492225.html 动态库路径配置- /etc/ld.so. ...

  8. linux下生成动态库和链接动态库

    1.生成动态库 src/test.h #ifndef _TEST_H_HH #define _TEST_H_HH void print(); #endif src/test.cpp #include ...

  9. Linux下设置动态库的方法

    库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的. 一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使 ...

随机推荐

  1. hdu 2489 Minimal Ratio Tree

    http://acm.hdu.edu.cn/showproblem.php?pid=2489 这道题就是n个点中选择m个点形成一个生成树使得生成树的ratio最小.暴力枚举+最小生成树. #inclu ...

  2. C 语言---漂亮的宏定义

    写好C 语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等.下面列举一些成熟软件中常用得宏定义. 1.防止一个头文件被重复包含 #ifndef COMDEF_H #de ...

  3. linux系统下,11款常见远程桌面控制软件

    linux系统下,11款常见远程桌面控制软件 一. Grdc 它是一个用GTK+编写的,适用于gnome桌面环境的远程桌面访问软件.看图: 常见功能: 1.提供全屏,窗口化的远程控制.支持高分辨率下的 ...

  4. Unity position和localposition

    1. position是根据世界原点为中心 2. localPosition是根据父节点为中心,如果没有父节点,localpositon和position是没有区别的 3.选中一个物体左上角Globa ...

  5. Oracle基础学习5-- Oracle权限之”角色”

    不论什么与权限相关的东西都少不了"角色"的概念,Java如此,.Net如此,Oracle当然也不例外. 角色事实上就是权限的集合,将多个权限打包到一个角色中,这样每一个角色有特定的 ...

  6. 标准linuxserver搭建

    一:针对大数据平台的linux例如以下搭建.为了方便截图,採用的虚拟机,与真实环境有点出入 二:过程例如以下 1. 在vmware中选择载入虚拟光盘iso文件,然后进入安装 2. 默认选择第一项 In ...

  7. ThreadPoolExecutor(转)

    让ThreadPoolExecutor的workQueue占满时自动阻塞submit()方法 By learnhard | 2015 年 09 月 04 日 0 Comment 转载请注明出处:htt ...

  8. java菜鸟篇<四> ZTree入门篇

    今天准备入手ZTree,于是在百度上搜了搜,找到了开源网址和一些大神们的教程,于是乎下午开始了组织树(ZTree)的练习 初步完整的作品是这个样子的: 1.咱们要去这个工具的开源网里找下载的东西: ( ...

  9. setlocal enabledelayedexpansion

    http://www.jb51.net/article/29323.htm 例1: 代码如下: @echo off set a=4 set a=5&echo %a% pause  结果:4 解 ...

  10. mysql存储过程调试方法

    有如下一个存储过程 ), i_length ),OUT o_result INT) BEGIN SET @a= NULL; SET @b= NULL; SELECT id INTO @a FROM t ...