在windows下常见的动态链接库文件:
.DLL, .ocx, .CPL
dll与exe都是PE格式的二进制文件,只是PE头部的一个符号位来表示是exe或者是dll
dll的共享数据段------为了实现进程通信。但是为了安全起见,一般不使用共享数据段。
DLL中导出,导入机制:
关于符号的导入,导出在编程时常用的几种办法:
1.程序中定义函数或者变量时候,用下面的c/c++扩展来修饰
使用_declspec(export) 函数名或者变量
_declspec(import) 函数名或者变量
2.使用模块定义文件.def
关于编译,使用cl /LDd simple.c
会产生四个文件:
simple.dll :动态链接文件
simple.obj :编译后的目标文件
simple.exp:临时文件,它仍然是个标准的pe/coff目标文件,用来存放链接器第一遍扫描后得到的符号信息。
simple.lib:这个.lib比较诡异,它不包含真正的代码和数据,它用来描述simple.dll的导出符号,它包含了user.o 链接simple.dll所需要的导入符号以及一部分“桩代码”,以便于将程序与dll粘在一起。 这样的文件又被称为导入库(import library).
关于dll的显示运行时链接:
支持的函数:
LoadLibrary(),GetProcAddress(),FreeLibrary()
2010-2-27 22:50---------------------------------------------------end
一个进程中,多个dll不可以被装载到同一个虚拟地址,每个dll所占用的虚拟地址区域之间不可以重叠。
PE DLL 中的代码段不是地址无关的。
解决共享对象地址冲突的问题时,windows采用了“装载时重定位的”方法,当加载dll时候,若目标地址被占用,操作系统会为它分配一块新的空间,将dll装载到该地址。dll涉及到的绝对地址引用的时候,对每个绝对地址引用都进行重定位。
DLL内部内部的地址都是基于基地址的,或者都是相对于基地址的RVA。所以重定位的过程比较简单,只要加上(新的加载地址与旧的加载地址的差值)。速度比一般的重定位速度要快。
当然也可以改变dll的默认基地址(加载地址0x10010000),这样可以省去每次装载时重定基址的过程。这样可以让程序运行的更快。
link /BASE:0x10010000, 0x10000-------------------------------------连接时设置 *.dll的基地址。
起始地址 长度
PE里面这种特殊的重定位过程被叫做Rebasing重定基地址。
如果一个PE DLL被多个进程共享,且该DLL被这些进程装载到不同的位置,那么每个进程都需要有一份单独的DLL代码段的副本。这样就浪费了内存。但是这样做的好处PE dll对数据段的访问速度比ELF的PIC方案更快。这是以空间换时间。
系统DLL:
windows系统就在进程空间中专门划出一块0x70000000~0x80000000区域用于映射常用的系统DLL (如kernel32.dll,ntdll.dll,shell32dll,user32.dll,msvcrt.dll