DLL_基础2

 

什么是 DLL?

动态链接库 (DLL) 是包含函数和数据的模块的集合。程序文件(如 .exe 文件或 .dll 文件)在运行时加载这些模块(亦即所需的模块映射到调用进程的地址空间)。下面两类函数定义了 DLL:
导出函数:这些函数由其他模块调用。
内部函数:这些函数仅从定义它们的 DLL 中调用。
DLL 还导出数据。不过,这些数据由相应的函数使用。
动态链接和静态链接
动态链接包括系统在加载或运行时查找导出的 DLL 函数的代码所需的信息。

在静态链接中,链接器将库函数的代码复制到调用 DLL 的每个模块。

可以通过下列方式调用 DLL 中的函数:
加载时动态链接:调用方模块执行显式调用以导出 DLL 函数。为 DLL 创建导入库,然后将 DLL 链接到应用程序。在加载应用程序时,导入库提供加载 DLL 和查找导出的 DLL 函数所需的信息。
运行时动态链接:在运行时加载 DLL 时,调用方模块使用 LoadLibrary 函数或 LoadLibraryEx 函数。调用方模块调用 GetProcAddress 函数以获取导出的 DLL 函数的地址。
在链接时,Windows 搜索预安装的一组 DLL,例如性能库 (Kernel32.dll) 和安全库 (User32.dll)。然后,Windows 按以下顺序搜索 DLL:
1.当前进程的可执行程序所在的目录。
2.当前目录。
3.Windows 系统目录。(GetSystemDirectory 函数获取 Windows 系统目录的路径。)
4.Windows 目录。(GetWindowsDirectory 函数获取 Windows 目录的路径。)
5.PATH 环境变量中列出的目录。

注意:LIBPATH 环境变量不用于搜索。
返回页首

DLL 和静态库

DLL 可节省内存并减少交换。 通过在内存中共享 DLL 的单个副本,多个进程可以同时使用一个 DLL。相比之下,对于使用静态链接库构建的每一个应用程序,Windows 都要在内存中为其加载库代码的一个副本。
DLL 可节省磁盘空间。 多个应用程序可以共享磁盘上的一个 DLL 副本。相比之下,使用静态链接库构建的每一个应用程序都需要让链接到程序文件映像的库代码作为一个单独的专用副本。
DLL 可节省时间。 更改 DLL 中的函数时,只要函数的参数和返回值不变,就不必重新编译或重新链接使用这些函数的应用程序。但是,如果您使用静态链接的对象代码,则在更改函数后必须重新链接应用程序。
DLL 可以共享函数。 在 Win32 中,DLL 可以共享函数。默认情况下,数据对于每个进程来说是独立的。但是,静态库包含针对每一个进程的单独的数据副本和函数。
返回页首

DLL 入口点

DLL 有一个特殊的入口点( DllMain 函数),它在附加和分离进程和线程时运行。此行为允许根据需要创建和销毁数据结构。文件扩展名为 .ocx.cpl.drv 的文件类型也是 DLL,尽管文件扩展名已改变。在 Windows 2. x 和 Windows 3. x 中,每个 DLL 都只有一个数据段实例,而不管有多少应用程序。在 Windows 32 中,可以将 DLL 标记为共享以导致相同的行为。但是,每个进程的默认设置是拥有 DLL 数据的专用副本。
您可以通过创建 DLL 实现以下目的:
将程序划分为可按需加载的单独模块。
存储特定于语言或特定于区域的资源。
使您自己的应用程序能够使用核心代码库。
生成进程内 COM 对象或 ActiveX 控件 (OCX)。
将 OLE 对象用作进程内 DLL。这一用法可改进 OLE 链接的性能。
使用控制面板扩展或使用某些类型的驱动程序。
要生成 DLL,请使用 DllMain 函数(而不是程序文件)替换 WinMain 函数。

要在 Win16 中导出函数,请将 FAR EXPORT 添加到所有导出的 DLL 函数(在 Win32 中不要求这样做)。许多 32 位编译器提供了函数声明符,例如 __declspec(dllexport)__declspec(dllimport)。这些函数声明符出现在函数声明之前以代替调用。不过,定义必须仅指定 dllexport 属性。

返回页首

DLL 问题和故障排除工具

初始化问题
在 DLL 初始化过程中,您可能会遇到下列一个或多个问题:
如果计划服务的服务帐户密码与域用户管理器帐户的密码不同,则您在计划服务时可能会收到以下初始化错误信息:
Initialization of dynamic link library c:/winnt/system32/KERNEL32.dll failed.Process is terminating abnormally
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
250265 使用 Cmd.exe 运行 AT 计划命令时出现 Kernel32.dll 动态链接库初始化错误
如果不断加载和卸载 Crypt32.dll,则在加载 Crypt32.dll 时将分配传输层安全性 (TLS),但在卸载 Crypt32.dll 时却不释放它。此行为可能导致一般性保护错误 (GPF) 错误,并且您可能会收到以下错误信息:
Initialization of the dynamic link library C:/WINNT40/System32/CRYPT32.dll failed.The process is terminating abnormally.
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
212825 SMS:一般性保护错误:Initialization of CRYPT32.DLL Failed(CRYPT32.DLL 初始化失败)
如果您将计算机升级到 McAfee VirusScan 6.0,则可能会在启动 Outlook 2000 后的三分钟内收到以下错误信息:
Outlook.exe. DLL initialization failed.Initialization of c:/winnt/system32/compstui.dll. Process is terminating abnormally.
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
310413 OL2000:升级到 McAfee VirusScan 6.0 后 Outlook 2000 发生 DLL 初始化错误
如果您将 Windows NT Mail 或 MSMail32.exe 设置为按计划启动,计划服务可能被记录为系统以外的其他内容,而且您可能会收到以下错误信息:
Initialization of the Dynamic Link Library OLECLI32.dll failed Abnormally
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
133476 Windows NT 邮件错误信息:Initialization of the Dynamic Link...(动态链接的初始化...)
如果远程访问服务 (RAS) 文件或调制解调器文件丢失或损坏,并且您试图打开控制面板,则可能会收到以下错误信息:
Explorer.exe - DLL Initialization Failed Initialization of the dynamic link library E:/WINNT/System32/RASSCRPT.dll failed.The process is terminating abnormally.
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
184443 错误信息:Explorer.exe - DLL Initialization Failed...(Explorer.exe — DLL 初始化失败...)
如果系统内存不足,无法为正在启动的服务创建新的桌面堆栈,您可能会收到以下错误信息:
ServiceName - DLL initialization failure Initialization of the dynamic link library c:/windows/system32/user32.dll failed.The process is terminating abnormally.
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
142676 解决 User32.dll 初始化失败错误
返回页首
依赖性问题
如果您没有等到所有系统服务开始运行就启动您的服务,可能会遇到依赖性问题。例如,服务依赖于其他服务或 驱动程序。这些服务或 驱动程序又转而依赖于另外一些服务或 驱动程序。更确切地说,RasApi32.dll 隐式依赖于 RAS 服务。使用 Rasapi32.dll 上的 LoadLibrary 的一个 Windows NT 服务使该服务依赖于 RAS 服务。

在您对项目进行更改时,定期通过“项目”菜单扫描所有依赖项以确保依赖性列表的准确性。如果您在执行依赖性扫描之前未保存对项目中文件所做的更改,新的依赖项不会显示在列表中。

返回页首
性能问题
如果加载应用程序的同时加载隐式链接到该应用程序的 DLL,则会出现性能问题。例如,当运行 Windows 2000 的计算机在内存中加载 Winmm.dll 文件时,可能会出现延迟。此延迟可能会在不同的时间发生,具体取决于 Winmm.dll 文件是如何加载的:
如果程序使用导入库来加载 Winmm.dll 文件,则 Winmm.dll 在程序启动时加载。在这种情况下,可能会在启动程序时出现延迟。因此,如果使用批处理文件多次启动此程序,性能会显著下降。
如果程序使用 LoadLibrary 加载 Winmm.dll 文件,则 Winmm.dll 仅在程序需要时才加载。例如,如果在您打开菜单时 Explorer.exe 播放声音,则在第一次播放声音时加载 Winmm.dll 文件。在这种情况下,可能会在程序加载 Winmm.dll 文件时出现延迟。
要提高性能,请在加载时使用 优化技巧。另外,可将 DLL 分为两个 DLL:
将调用应用程序在加载后立刻需要的所有函数放入一个 DLL,然后将该调用应用程序隐式链接到此 DLL。
将调用应用程序不立即需要的函数放入另一个 DLL,然后将该应用程序显式链接到此 DLL。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值