【Linux技术】Windows与Linux系统下的库·初探
库的定义
库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的。它们通常由一组互相关联的用来完成某项常见工作的函数构成,从本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
无论在Windows 平台还是Linux平台下都存在大量的库,但由于Windows 和Linux 的本质不同,因此二者的库的二进制是不兼容的。
库的分类
- Windows 下的库有两种:静态库(.lib)和动态链接库(.dll)。
- Linux 下的库有两种:静态库(.a)和共享库(.so)。
- Linux 下的静态库的名字一般为libxxxx.a,其中xxxx 是该lib 的名称
- Linux 下的动态库的名字一般为libxxxx.so.major.minor,xxxx 是该lib 的名称,major 是主版本号,minor 是副版本号。
Windows与Linux下库的异同
Linux 的共享库(.so)就象Windows 的动态链接库(.dll),它里面包含有很多程序常用的函数。为了方便程序开发和减少程序的冗余,程序当中就不用包 含每个常用函数的拷贝,只是在需要时调用共享库中常函数即可。这种方式我们称之为动态链接(Dynamically Linked)。
而有时我们不希望叫程序去调用共享库的函数,而是把库函数代码直接链接进程序代码中,也就是说,在程序本身拥有一份共享库中函数的副本。 这种方式我们称之为静态链接(Statically Linked)。
所以,简单的讲静态库和共享库(动态库)的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
Windows下的动态链接库(dll)与Linux下的共享库(.so)的差别
.dll 文件事实上和.exe 文件一样,同属 PE格式的执行文件。对于隐式的引用外部符号,需要把外部符号所在的位置写在PE 头上。PE 加载器将从PE 头上找到依赖的符号表,并加载依赖的其它.dll 文件。
而在Linux 上并非如此!.so 文件大多为elf 执行文件格式。当它们需要的外部符号,可以不写明这些符号所在的位置。也就是说,通常.so 文件本身并不知道它依赖的那些符号在哪些.so 里面。这些符号是由调用dlopen 的进程运行时提供的。
我们在Windows 下做一个.dll 文件时还需要携带一个.lib 文件;而在Linux 下一般只需要有相应的头文件就够了。对于编写新的.so,找不到的 符号可以就让它在那里,直到最终执行文件来把所有需要的符号联合到一起。windows可以存在一个.dll 对另一个.dll 的隐式依赖;而Linux 下一般不需要让.so 和.so 有隐式依赖关系。
Windows与Linux系统的动态库差异分析
动态链接库技术实现和设计程序常用的技术,在 Windows 和Linux 系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提 高效率,增加程序的可扩展性,便于模块化管理。但不同操作系统的动态库由于格式 不同,在需要不同操作系统调用时需要进行动态库程序移植。
1. 引言
动态库(Dynamic Link Library abbr,DLL)技术是程序设计中经常采用的技术。其目的减少程序的大小,节省空间,提高效率,具有很高的灵活性。采用动态库技术对于升级软件版本更加 容易。与静态库(Static Link Library)不同,动态库里面的函数不是执行程序本身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。
在Windows 和Linux 操作系统中,都可采用这种方式进行软件设计,但他们的调用方式以及程序编制方式不尽相同。
2. Windows 动态库技术
动态链接库是实现Windows 应用程序共享资源、节省内存空间、提高使用效率的一个重要技术手段。常见的动态库包含外部函数和资源,也有一些 动态库只包含资源,如Windows 字体资源文件,称之为资源动态链接库。通常动态库以.dll,.drv、.fon 等作为后缀。相应的windows 静 态库通常以.lib 结尾,Windows 自己就将一些主要的系统功能以动态库模块的形式实现。
Windows 动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地址空间分配的内存,成为调用进程的一部分。DLL 也只能被 该进程的线程所访问。DLL 的句柄可以被调用进程使用;调用进程的句柄可以被DLL 使用。DLL 模块中包含各种导出函数,用于向外界提供服务。DLL 可以 有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL 在内存中只有一个实例;DLL 实现了代码封装性;DLL的编制与具 体的编程语言及编译器无关,可以通过 DLL 来实现混合语言编程。DLL 函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。
根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。
- 静态调用,也称为隐式调用,由编译系统完成对DLL 的加载和应用程序结束时DLL卸载的编码(Windows 系统负责对DLL 调用次数的 计数),调用方式简单,能够满足通常的要求。通常采用的调用方式是把产生动态连接库时产生的.LIB 文件加入到应用程序的工程中,想使用DLL 中的函数 时,只须在源文件中声明一下。 LIB 文件包含了每一个DLL导出函数的符号名和可选择的标识号以及 DLL 文件名,不含有实际的代码。Lib 文件包含的信息进入到生成的应用程序中,被调用的 DLL文件会在应用程序加载时同时加载在到内存中。
- 动态调用,即显式调用方式,是由编程者用API 函数加载和卸载DLL 来达到调用 DLL 的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。
在Windows 系统中,与动态库调用有关的函数包括:
- LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。
- GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL 内部地址。
- FreeLibrary(或MFC 的AfxFreeLibrary),释放动态链接库。
在windows 中创建动态库也非常方便和简单。在Visual C 中,可以创建不用MFC 而直接用C 语言写的DLL 程序,也可以创建基于MFC 类库的DLL 程序。每一个DLL 必须有一个入口点,在VC中,DllMain 是一个缺省的入口函数。DllMain 负责初始化(Initialization)和结束(Termination)工作。动态库输出 函数也有两种约定,分别是基于调用约定和名字修饰约定。DLL 程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调用。
通常可以有下 面几种方法导出函数:
- 采用模块定义文件的EXPORT 部分指定要输入的函数或者变量。
- 使用MFC 提供的修饰符号_declspec(dllexport)。
- 以命令行方式,采用/EXPORT 命令行输出有关函数。
在windows 动态库中,有时需要编写模块定义文件(.DEF),它是用于描述DLL 属性的模块语句组成的文本文件。
3. Linux 共享对象技术
在Linux 操作系统中,采用了很多共享对象技术(Shared Object),虽然它和Windows里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so 作为后缀。
Linux 系统的/lib 以及标准图形界面的/usr/X11R6/lib等目录里面,就有许多以so 结尾的共享对象。同样,在Linux下,也有静态函数库这种调用方式,相应的后缀以.a 结束。Linux 采用该共享对象技术以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活性。Linux 还可以通过LD-PRELOAD 变量让开发人员可以使用自己的程序库中的模块来替换系统模块。
同Windows 系统一样,在Linux 中创建和使用动态库是比较容易的事情,在编译函数库源程序时加上-shared 选项即可,这样所生成的执行程序就是动态链接库。通常这样的程序以 so为后缀,在Linux 动态库程序设计过程中,通常流程是编写用户的接口文件,通常是.h 文件,编写实际的函数文件,以.c 或.cpp 为后缀,再编写makefile 文件。对于较小的动态库程序可以不用如此,但这样设计使程序更加合理。
编译生成动态连接库后,进而可以在程序中进行调用。在Linux 中,可以采用多种调用方式,同Windows 的系统目录 (..\system32等)一样,可以将动态库文件拷贝到/lib 目录或者在/lib 目录里面建立符号连接,以便所有用户使用。
下面看看Linux 调用动态库经常使用的函数,但在使用动态库时,源程序必须包含dlfcn.h 头文件,该文件定义调用动态链接库的函数的原型。
- 打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag); dlopen 用于打开指定名字(filename)的动态链接库,并返回操作句柄。
- 取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol); dlsym 根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。
- 关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle); dlclose 用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
- 动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror 可以返回出错信息,返回值为NULL 时表示操作函数执行成功。
除了采用这种方式编写和调用动态库之外,Linux 操作系统也提供了一种更为方便的动态库调用方式,也方便了其它程序调用,这种方式与 Windows 系统的隐式链接类似。其动态库命名方式为“lib*.so.*”。在这个命名方式中,第一个*表示动态链接库的库名,第二个* 通常表示该动态库的版本号,也可以没有版本号。在这种调用方式中,需要维护动态链接库的配置文件/etc/ld.so.conf 来让动态链接库为系统所使用,通常将动态链接库所在目录名追加到动态链接库配置文件中。
如具有 X window 窗口系统发行版该文件中都具有/usr/X11R6/lib,它指向X window 窗口系统的动态链接库所在目录。为了使动态链接库能为系统所共享,还需运行动态链接库的管理命令./sbin/ldconfig。
在编译所引用的动态库时,可以在 gcc采用 -l 或-L 选项或直接引用所需的动态链接库方式进行编译。在 Linux 里面,可以采用ldd 命令来检查程序依赖共享库。
4. 两种系统动态库比较分析
Windows 和Linux 采用动态链接库技术目的是基本一致的,但由于操作系统的不同,他们在许多方面还是不尽相同。
- 动态库程序编写,在Windows 系统下的执行文件格式是PE 格式,动态库需要一个DllMain函数作为初始化的人口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。Linux 下的gcc 编译的执行文件默认是ELF 格式,不需要初始化入口,亦不需要到函数做特别声明,编写比较方便。
- 动态库编译,在windows 系统下面,有方便的调试编译环境,通常不用自己去编写makefile 文件,但在linux 下面,需要自己动手去编写makefile文件,因此,必须掌握一定的makefile 编写技巧,另外,通常Linux 编译规则相对严格。
- 动态库调用方面,Windows 和Linux 对其下编制的动态库都可以采用显式调用或隐式调用,但具体的调用方式也不尽相同。
- 动态库输出函数查看,在Windows 中,有许多工具和软件可以进行查看DLL 中所输出的函数,例如命令行方式的dumpbin 以及VC 工具中的DEPENDS 程序。在Linux 系统中通常采用nm 来查看输出函数,也可以使用ldd 查看程序隐式链接的共享对象文件。
- 对操作系统的依赖,这两种动态库运行依赖于各自的操作系统,不能跨平台使用。因此,对于实现相同功能的动态库,必须为两种不同的操作系统提供不同的动态库版本。
【Linux技术】Windows与Linux系统下的库·初探的更多相关文章
- 【转帖】Windows与Linux系统下的库介绍
Windows与Linux系统下的库介绍 http://embeddedlinux.org.cn/emb-linux/entry-level/200903/12-553.html 库的定义 库文件是一 ...
- Linux和Windows的遍历目录下所有文件的方法对比
首先两者读取所有文件的方法都是采用迭代的方式,首先用函数A的返回值判断目录下是否有文件,然后返回值合法则在循环中用函数B直到函数B的返回值不合法为止.最后用函数C释放资源. 1.打开目录 #inclu ...
- [转]Windows与Linux系统下的库文件介绍
什么是库 库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的.它们通常由一组互相关联的用来完成某项常见工作的函数构成,从本质上来说库是一种可执行代码的二进制形式,可以被操作系 ...
- 安装 Linux 与 Windows 10 双系统,你需要了解的一切
该选Windows 10还是Linux Mint?鱼与熊掌当然可以兼得,但咱们得掌握点小技巧才能顺利搞定. Windows 10绝不是唯一一款值得我们安装在自己计算机之上的免费操作系统.Linux只靠 ...
- 安装Linux和Windows的双系统
平时使用较多的操作系统是Windows,想玩玩Linux平时也是在虚拟机上,强迫症的怎么能忍,一直想装个双系统,也能强迫自己练习Linux命令,之前重装系统的时候也试着装了一下,但是准备不够充分.结果 ...
- 【Linux】Windows与Linux之间的文件共享(基于网络)
切记:Linux的安全机制的存在--iptables和selinux. 一.操作前提 1.1 从Windows能够ping通Linux 1.2 关闭Linux防火墙 command1:/etc/ini ...
- Windows和Mac系统下安装Docker
在windows和mac系统中使用Docker Desktop安装Docker对系统的要求是很高的. 对于 Windows 系统来说,安装 Docker for Windows 需要符合以下条件: 必 ...
- Windows 64位操作系统下安装和配置MySQL
一安装方式 MySQL安装文件分为两种,一种是MSI格式的,一种是ZIP格式的.下面来看看这两种方式: MSI格式的可以直接点击安装,按照它给出的安装提示进行安装,Windows操作系统下一般MySQ ...
- Linux入门(12)——解决双系统下Ubuntu16.04不能访问Windows分区
解决办法一: 进入windows系统,关闭快速启动,关机. 解决办法二: 如果办法一不能解决问题,用这个办法. 查看盘符: sudo fdisk -l 需要在查看盘符后记下目标盘符的数字,比如想解除C ...
随机推荐
- ios中地图定位
#import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface ViewController ...
- 给我一对公钥和私钥,我就能破解此RSA
RSA密码系统如果暴露了一套公钥和私钥,那么这套密码系统就全部失效了.因为根据公钥和私钥可以完成大整数的分解.暴露了两个质数. 记公钥为e,私钥为d,因为ed%phi=1,所以就得到了一个k=ed-1 ...
- Cordova+jQuery Mobile+Spring REST
Cordova可以方便地建立跨平台的移动应用,使用jQuery Mobile做手机界面,后台使用rest提供数据交互. 首先,使用jQuery Mobile建立一个页面: <!DOCTYPE h ...
- NSNotificationCenter实现原理
# 前言 Cocoa中使用NSNotification.NSNotificationCenter和KVO来实现观察者模式,实现对象间一对多的依赖关系. 本篇文章主要来讨论NSNotification和 ...
- iOS配置SSO授权
禁止/激活SSO授权 用于控制平台是否使用SSO方式进行授权(目前只支持新浪微博.Facebook.QQ空间.腾讯微博.人人网.Pocket.默认情况下是激活SSO授权方式.),代码如下: //激活S ...
- 百度地图 ijintui以及七牛、百度编辑器、kindeditor
密码是明文存储的 sig错误是因为params没拼接上md5后的秘钥,测试时候可以在 Api\Controller\CommonController\_initialize 方法里注释掉效验的代码 代 ...
- SpringMvc4中获取request、response对象的方法
springMVC4中获取request和response对象有以下两种简单易用的方法: 1.在control层获取 在control层中获取HttpServletRequest和HttpServle ...
- Html插入Flash.object.embed.swf各个参数值详解介绍[等比例缩放]
http://www.dayku.cn/space-3-do-blog-id-544.html 目也在此列出. Internet Explorer 可识别用于 object 标签的参数:Netscap ...
- oracle下导出某用户所有表的方法
oracle下导出某用户所有表的方法 scott/tiger是用户名和密码,handson是导出的实例名 按用户方式导出数据(owner当中写的是用户名) exp scott/tiger@handso ...
- 用copy 还是 strong?
NSArray与NSMutableArray用copy修饰还是strong 这个是原文 http://blog.csdn.net/winzlee/article/details/51752354 一 ...