动态库和静态库浅析

来源:互联网 发布:攀枝花学院教务网络 编辑:程序博客网 时间:2024/06/04 18:47
动态链接库,这些库通常有文件扩展名 DLL,OCX(含库的ActiveX控件),或DRV(对遗留系统驱动程序)。该文件格式的DLL是一样的Windows EXE文件-也就是说,移植可执行(PE)为32位和64位 Windows和新的可执行文件(NE)的16位 Windows操作系统。DLL可以包含代码,数据,和资源,在任何组合。
数据文件具有相同的文件格式作为DLL,但具有不同的文件扩展名,可能只包含部分资源,可称为资源DLL。

DLL的特点
由于DLL是基本相同的EXE,选择其中产生作为连接过程的一部分,为清楚起见,由于能够从任一导出的功能和数据。


不可能直接执行一个DLL,因为它需要用于操作系统一个EXE通过进入点来加载它,因此,像RUNDLL.EXE或RUNDLL32.EXE公用事业其提供的入口点和最小框架的DLL的存在包含足够的功能没有多大的支持来执行。

DLL提供共享代码和数据的机制,允许共享的代码/数据的显影剂,而不需要应用被重新连接或重新编译升级功能。
执行的DLL调用进程中,并用相同的访问权限的内存空间,这意味着有其使用的小开销,而且还没有为EXE调用任何保护,如果DLL有任何类型的错误。


内存管理
在Windows API中DLL文件被组织成部分。每个部分都有其自己的一组属性,诸如被可写或只读,可执行文件(代码)或非可执行的(用于数据),等等。

在DLL中的代码通常是所有使用该DLL的进程之间共享的; 也就是说,它们占据的物理内存一个地方,不占用空间的页面文件。如果代码段占用的物理内存是要回收的,其内容将被丢弃,后来直接从DLL文件重新加载必要的。

相反,代码段,一个DLL的数据段通常是私有的。可制作数据段的共享,让进程间通信通过这个共享内存区域。然而,由于用户的限制并不适用于使用共享DLL内存,这将创建一个安全漏洞 ; 即一个进程可以破坏共享数据,这可能会导致所有其他共享进程行为异常。

如果DLL是由某些压缩可执行文件加壳(如UPX),它的所有代码段被标记为读写,并且将取消共享。读取和写入的代码段,很像私有数据段,是专用于每个过程。如果它们旨在被由多个程序同时使用,因为每个程序实例将不得不携带其自己的DLL拷贝,从而增加存储器消耗从而与共享数据段的DLL不应被压缩。


导入库
像静态库,对进口的DLL库由的.lib文件扩展名指出。

链接到动态库通常是通过建立或链接到创建一个可执行文件时,链接到导入库处理。创建的可执行文件然后包含所有DLL函数调用引用的导入地址表(IAT)(每个引用的DLL函数包含在IAT有自己的条目)。在运行时,IAT的填充有直接指向一个功能在单独加载的DLL适当地址。


符号解析和绑定
由DLL导出的每个功能是由一个数字序和任选的名称来标识。同样,函数可以从一个DLL或者通过序号或名称导入。序代表在DLL导出地址表中的函数的地址指针的位置。这是很常见的内部功能仅仅通过序数导出。对于大多数Windows API函数只有名字在不同的Windows版本保存; 序数可能有变动。因此,人们不能可靠可以通过序导入Windows API函数。

按顺序导入功能,提供了比按名称导入它们只是稍微更好的性能:DLL文件的导出表按名称排序,因此二进制搜索可以用于查找功能。然后根据发现的名字的索引来查找顺序在导出序表。

它也可以结合一个可执行到DLL的特定版本,也就是在编译时间来解决的进口函数的地址。对于绑定进口,链接保存到其进口势必DLL的时间戳和校验和。在运行时的Windows检查是否正在使用库的同一版本的,如果是这样,视窗绕过处理进口。否则,如果该库是从其中结合到所述一个不同,Windows处理以正常方式的进口。

绑定可执行负载稍快,如果它们在相同的环境中运行,他们编译,并准确地如果它们在不同的环境中运行的同时,所以有用于结合所述进口没有缺点。例如,所有的标准Windows应用程序绑定到其各自的Windows版本的系统DLL。对应用程序的进口绑定到其目标环境的好机会是应用程序的安装过程中。这样可以使图书馆的束缚“,直到下一次操作系统更新。它,然而,更改可执行文件的校验和,所以它是不是可以与由使用校验(如配置管理工具管理的签名的程序,或程序进行MD5校验)来管理文件版本。随着越来越多的新的Windows版本,实现了由每一个加载库(出于安全原因)固定地址,机遇,结合可执行正在减少值搬走。

显式运行时链接
DLL文件可以明确地装载在运行时,处理简称为运行时动态链接由Microsoft,通过使用LoadLibrary(或LoadLibraryEx)API函数。该GetProcAddressAPI函数由名称查找导出的符号,以及FreeLibrary-卸载DLL。这些功能类似于dlopen,dlsym和dlclose在POSIX标准API。

显式运行时链接的过程中,它支持任何语言相同的函数指针,因为它依赖于Windows API的,而不是语言结构。

延迟加载
通常情况下,这是对一个DLL的导入库链接的应用程序将无法启动,如果DLL无法找到,因为Windows将无法运行该应用程序,除非能找到所有的应用程序可能需要的DLL。然而,一个应用程序可能对一个导入库链接,使动态库的延迟加载。在这种情况下,操作系统将不会尝试应用程序启动时查找或加载DLL; 相反,存根包含在由链接器将尝试找到并通过调用LoadLibrary和GetProcAddress加载DLL时,其功能之一就是所谓的应用程序。如果DLL无法找到或加载,或者被调用的函数不存在时,应用程序将产生一个异常,其可以被适当地捕获和处理。如果该应用程序不处理该异常,它将由操作系统,这将与一个错误消息终止程序被捕获。

延迟装载机构还提供通知挂钩,允许应用程序执行额外的处理或错误处理,当DLL被加载和/或任何DLL函数被调用。


静态库
静态库或静态链接库是一组例程,外部函数和变量,它们在呼叫者解决编译时和被复制到一个目标应用程序的编译器,链接器,或粘合剂,产生一个对象文件和一个独立的可执行文件。可执行和编译它都被称为一个过程静电积聚的程序。从历史上看,图书馆只能是静态的。静态库或者与其他静态库合并,对象文件建立/链接以形成一个单一的过程中可执行,或者它们可在被加载运行时到地址空间加载的可执行的在静态存储器偏移在编译时决定/链接时。

优缺点
有几个优势,静态链接库与一个可执行文件,而不是动态链接他们。最显著的是,应用程序可以肯定的是它所有的位置存在,他们是正确的版本。这避免了依赖问题。静态链接还可以允许应用程序被包含在一个单一的可执行文件,从而简化了分布和安装。

与静态链接,它足以包括由目标可执行(或目标库)直接或间接引用的库的那些部分。用动态库,整个库加载的,因为它不预先哪个功能将被应用程序调用已知的。是否这样的好处是在实践中显著依赖于库的结构。

在静态链接的可执行文件的大小变得比在动态链接时,作为库代码被存储的可执行文件中,而不是在单独的文件。但是,如果库文件也被视为该应用程序的一部分,那么总规模将是相似的,甚至如果编译器消除了未使用的元件较小。在微软的Windows是很常见的包括库文件与应用程序的应用需求。在类Unix系统,这是不常见的包管理系统,可以用来确保正确的库文件可用。这允许许多应用导致节省空间之间共享的库文件。这也让库进行更新以修复bug和安全漏洞,而无需更新使用该库的应用程序。在实践中,许多可执行文件(特别是那些靶向微软Windows)的使用静态和动态库。


链接和加载
任何静态库函数可以调用在另一个静态库中的函数或过程。该连接器和加载器处理这个问题的方法为各种其他相同的目标文件。静态库文件可在以下链接运行时通过链接装入器(例如,X11模块加载器)。然而,这样的过程是否可以被称为静态链接是有争议的。


用C创建静态库/ C ++ 
静态库可以轻松创建C或C ++。这两种语言提供存储类说明符,用于指示外部或内部联动,除了提供其他功能。要创建这样一个图书馆,导出的函数/过程和其他对象的变量必须为指定外部链接(通过不使用C即static关键字)。静态库文件名 ​​通常有一个“。lib”扩展的类Unix系统和“的.lib” 微软的Windows。


例如,要创建一个档案从文件中class1.o,class2.o,class3.o,将使用以下命令:


AR RCS libclass.a class1.o class2.o class3.o
编译依赖于程序class1.o,class2.o和class3.o人可以这样做:


CC的main.c libclass.a
或者(如果libclass.a被放置在标准库路径,如在/ usr / local / lib目录)


CC的main.c -lclass
或(在连接时)


LD ... main.o中-lclass ...
代替:

CC的main.c class1.o class2.o class3.o


至于怎么导入动态库及其使用,由于网速不好,便不在给读者列出,读者可以去网上查些,谢谢。

在这里再给一个比较好的文章http://developer.51cto.com/art/201505/476344_all.htm

0 0
原创粉丝点击