文档章节

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

wangxuwei
 wangxuwei
发布于 2016/05/08 08:31
字数 923
阅读 22
收藏 0
点赞 2
评论 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
粉丝 20
博文 306
码字总数 109514
作品 0
杭州
其他
linux下so动态库一些不为人知的秘密(中)

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

wangxuwei ⋅ 2016/05/08 ⋅ 0

Linux 目录结构:/lib 分析

我们在之前的文章中已经分析了其他重要系统目录,比如 、、、 等。可以根据自己的兴趣进入下列链接了解更多信息。本文中,让我们来看看 目录都有些什么。 目录结构分析:/bin 文件夹 目录结构...

作者: Surendra Anne ⋅ 04/26 ⋅ 0

Linux 中如何快速查看 C 库函数的头文件、库文件

Linux 中如何快速查看 C 库函数的头文件以及相应的函数信息? 使用man帮助或grep 1)man命令 函数名,则能够打印该函数的所有说明,当然这个函数必须是Linux-C本身就有的函数。 2)grep "key...

byxdaz ⋅ 05/20 ⋅ 0

Wine中PE格式文件的加载(一):Wine初始化过程

首先了解下Wine初始化过程。 我们执行”wine WeChat.exe”命令,发生的过程是怎么样的?接下来从wine源码一步步分析函数调用过程。 在loader/目录下的源码编译,由main.c生成了“wine”Linux...

chrisnotfound ⋅ 04/16 ⋅ 0

Java使用nanomsg消息中间件

一,引用的包 二,nanomsg的使用,需要针对不同的平台编译并得到动态库,然后引入项目。当前自己在window10-x86-64 和 linux-x86-64的环境下编译了两个动态库。(本次使用的是nanomsg5.1.0) w...

mybabe0312 ⋅ 06/18 ⋅ 0

Eclipse Debug不为人知的秘密

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

i33 ⋅ 2012/03/29 ⋅ 0

浅入浅出 Android 安全:第一章 Android

第一章 Android 来源:Yury Zhauniarovich | Publications 译者:飞龙 协议:CC BY-NC-SA 4.0 Android 安全架构的理解不仅帮助我了解 Android 的工作原理,而且为我开启了如何构建移动操作系...

apachecn_飞龙 ⋅ 2016/11/27 ⋅ 0

Unix一些实用但不为人知的命令

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

1169334005 ⋅ 2014/05/05 ⋅ 0

Linux GCC编译使用动态、静态链接库

在windows下动态链接库是以.dll后缀的文件,二在Linux中,是以.so作后缀的文件。 动态链接库的好处就是节省内存空间。 1、Linux下创建动态链接库 在使用GCC编译程序时,只需加上-shared选项即...

rivsidn ⋅ 05/09 ⋅ 0

设置基于Web的Guacamole(鳄鱼)工具以访问远程Linux / Windows计算机

作为系统管理员,你会发现自己(现在或将来)的环境下Windows和Linux共存工作。 这不是秘密,一些大公司喜欢(或必须)在Windows机箱和其他Linux服务器上运行他们的一些生产服务。 如果是这样...

yzy121403725 ⋅ 05/31 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CENTOS7防火墙命令记录

安装Firewall命令: yum install firewalld firewalld-config Firewall开启常见端口命令: firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --zone=public --add-po......

cavion ⋅ 17分钟前 ⋅ 0

【C++】【STL】利用chromo来测量程序运行时间与日志时间打印精确到微秒

直接上代码吧,没啥好说的。头疼。 #include <iostream>#include <string>#include <ctime>#include <sstream>#include <iomanip>#include <thread>#include <chrono>using ......

muqiusangyang ⋅ 20分钟前 ⋅ 0

Mac环境下svn的使用

在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还需做一下简...

故久呵呵 ⋅ 30分钟前 ⋅ 0

破解公司回应苹果“USB限制模式”:已攻破

本周四,苹果发表声明称 iOS 中加入了一项名为“USB 限制模式”的功能,可以防止 iPhone 在连接其他设备的时候被破解,并且强调这一功能并不是针对 FBI 等执法部门,为的是保护用户数据安全。...

六库科技 ⋅ 31分钟前 ⋅ 0

MyBtais整合Spring Boot整合,TypeHandler对枚举类(enum)处理

概要 问题描述 我想用枚举类来表示用户当前状态,枚举类由 code 和 msg 组成,但我只想把 code 保存到数据库,查询处理,能知道用户当前状态,这应该怎么做呢?在 Spring 整合MyBatis 的时候...

Wenyi_Feng ⋅ 50分钟前 ⋅ 0

synchronized与Lock的区别

# <center>王梦龙的读书笔记第一篇</center> ## <center>-synchronized与Lock的区别</centre> ###一、从使用场景来说 + synchronized 是能够注释代码块、类、方法但是它的加锁是和解锁使用一......

我不想加班 ⋅ 今天 ⋅ 0

VConsole的使用

手机端控制台打印输出,方便bug的排查。 首先需要引入vconsole.min.js 文件,然后在文件中创造实例。就能直接使用了。 var vConsole = new VConsole(); vConsole的文件地址...

大美琴 ⋅ 今天 ⋅ 0

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 今天 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 今天 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部