Linux共享库两种加载方式简述
动态库技术通常能减少程序的大小,节省空间,提高效率,具有很高的灵活性,对于升级软件版本也更加容易。与静态库不同,动态库里面的函数不是执行程序本身 的一部分,而是在程序执行时按需载入,其执行代码可以同时在多个程序中共享。由于在编译过程中无法知道动态库函数的地址,所以需要在运行期间查找,这对程 序的性能会有影响。
共享库
对于共享库来讲,它只包括2个段:只读的代码段 和可修改的数据段。堆和栈段,只有进程才有。如果你在共享库的函数里,分配了一块内存,这段内存将被算在调用该函数的进程的堆中。代码段由于其内容是对每 个进程都是一样的,所以它在系统中是唯一的,系统只为其分配一块内存,多个进程之间共享。数据段由于其内容对每个进程是不一样的,所以在链接到进程空间 后,系统会为每个进程创建相应的数据段。也就是说如果一个共享库被N个进程链接,当这N个进程同时运行时,同时共享一个代码段,每个进程拥有一个数据段,系统中共有N个数据段。PIC即position independent code,使.so文件的代码段变为真正意义上的共享。如果编译时不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy。
加载方式
1. 静态加载
在程序编译的时候加上“-l”选项,指定其所依赖的动态库,这个库的名字将记录在ELF文件的.dynamic节。在程序运行时,loader会预先将程序所依赖的所有动态库都加载在进程空间中。
优点:动态库的接口调用简单,可以直接调用。
缺点:动态库的生存周期等于进程的生存周期,其加载时机不灵活。
2. 动态加载
在程序中编码来指定加载动态库的时机,经常使用的函数dlopen和dlclose。
优点:动态库加载的时机非常灵活,可以非常细致的定义动态库的生存周期。
缺点:动态库的接口调用起来比较麻烦,同时还要关注动态库的生存周期。
=====================================================
#include <dlfcn.h>
void * dlopen( const char * pathname, int mode );
函数描述:
在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL 不允许导出符号
RTLD_GLOBAL 允许导出符号
RTLD_NODELETE
RTLD_NOLOAD
RTLD_DEEPBIND //具体含义可通过man查看dlopen函数说明
返回值:
打开错误返回NULL
成功,返回库引用
编译时候要加入 -ldl (指定dl库)
int dlclose (void *handle);
函数描述:
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
在dlopen一个共享库时,
a、进程会加载该共享库的代码段和数据段,同时为这个共享库计数加1。
b、进程查找该共享库的dynamic节,查看其所依赖的共享库。
c、首先检查所依赖库是否已经被加载,如果已被加载,则为这个共享库计数加1。如果未被加载,则加载其代码段和数据段,然后为这个共享库计数加1。
d、再查找这些库所依赖的库。最终进程会为每个加载的共享库维护一个依赖的计数。
在dlclose共享库时:
a、首先将该共享库的计数减1,如果该共享库依赖计数为0,则卸载该共享库。
b、在dynamic节中,查找其所依赖的共享库。
c、为每个共享库的计数减1,如果该共享库依赖计数为0,则卸载该共享库。
d、重复上面的步骤。
- 优点:
a、可以在程序启动的时候,减少加载库的数量,这样可以加快进程的启动速度和减少加载库的内存使用。
b、为进程提供了卸载共享库的机会,这样就可以回收共享库代码段和数据段所占用的内存。
- 缺点:
对于程序员编码来讲,会产生一定的疑惑。一个static的对象的生存周期是贯穿在进程始终的,实际上不是这样。在动态库中的static对象,其生命周期等于该动态库的生命周期。采用静态链接的方式,动态库的生命周期等于进程的生命周期;而采用动态加载的方式,则是不同的。
参考:
《嵌入式Linux内存与性能详解》
Linux共享库两种加载方式简述的更多相关文章
- Linux驱动的两种加载方式过程分析
一.概念简述 在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载. 静态加载就是把驱动程序直接编译进内核,系统启动后可以直接调用.静态加载的缺点是调试起来比较麻烦,每次修改一个地方都要重新 ...
- Xamarin Android Fragment的两种加载方式
android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...
- ios 图片的两种加载方式
控件加载图片,plist,懒加载,序列帧动画,添加动画效果. IOS中有2种加载图片的方式. 方式一:有缓存(图片所占用的内存会一直停留在程序中) + (UIImage *)imageNamed:(N ...
- dll的两种加载方式(pend)+ delayload
看过关于动态库的调用例子,于是决定动手做一做:dll的对外接口声明头文件,Mydll.h: //Mydll.h #include <stdio.h> #include <stdlib ...
- 渐进式jpeg(progressive jpeg)图片及其相关 --图片的两种加载方式
渐进式jpeg(progressive jpeg)图片及其相关 一.基本JPEG(baseline jpeg)和渐进JPEG 网络上那些色色的照片都是.jpg格式的("色色"指 ...
- Qml文件的两种加载方式
一种是QQmlApplicationEngine搭配Window,例如: #include <QGuiApplication> #include <QQmlApplicationEn ...
- Android Activity四种加载方式
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
- Android学习笔记_50_(转 四种加载方式详解(standard singleTop singleTask singleInstance)
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
- Android 四种加载方式详解(standard singleTop singleTask singleInstance) .
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
随机推荐
- windows和linux双系统删除linux
装了Windows和linux双系统的朋友,在后期要删除linux是个比较头痛的问题,因为MBR已经被linux接管,本文的目的是如何在windows 和linux双系统下,简单,完美地卸载linux ...
- 『零行代码』解决键盘遮挡问题(iOS)
关注仓库,及时获得更新:iOS-Source-Code-Analyze https://github.com/draveness/iOS-Source-Code-Analyze Follow: Dra ...
- ZYKeyboardUtil 全自动处理键盘遮挡事件
键盘遮盖输入控件或按钮在日常app开发中避之不及,考虑各种情况下UI各种嵌套,最后还要注册监听再获取指定键盘信息.我们可以通过键盘处理工具类ZYKeyboardUtil避繁就简,利用Block的方式处 ...
- 【bzoj2938】[Poi2000]病毒
题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...
- JAVA 生成PDF报表()
许多应用程序都要求动态生成 PDF 文档.这些应用程序涵盖从生成客户对帐单并通过电子邮件交付的银行到购买特定的图书章节并以 PDF 格式接收这些图书章节的读者.这个列表不胜枚举.在本文中,我们将使用 ...
- iOS 事件处理机制与图像渲染过程(转)
iOS 事件处理机制与图像渲染过程 iOS RunLoop都干了什么 iOS 为什么必须在主线程中操作UI 事件响应 CALayer CADisplayLink 和 NSTimer iOS 渲染过程 ...
- ios里面如何压缩图片
在iOS里面,压缩图片跟在其他环境里面差不多,都和累死, 就是对当前图片从新画图,制定一个尺寸的问题 UIImage* image = [UIImage imageNamed:@"cat.j ...
- VisualStudio2013&VS2015内置SQLServer入门 (三)
关于LocalDB的部署(publish): 使用本机做服务器(目测不可行) 双击项目的Properties-->Publish-->Application Files,你会发现没有.md ...
- Jmeter软件测试1--webservice测试
写在前言 程序猿一枚,原本就是负责安安静静的撸代码,后来公司让兼任下测试的工作,还得照顾下面的几个测试兄弟,无奈本人毫无软件测试理论知识,下面的测试兄弟也是初级水平,又面临公司要求做webservic ...
- IBM服务器 IMM日志收集
在IBM X系列服务器背板上有一个" SYS MGMT"接口,用网线将此接口与笔记本连接起来,然后将笔记本的 IP地址配置成 192.168.70.0/24 这个网段的地址,然后 ...