操作系统实验五——动态链接库的建立与调用

操作系统实验五——动态链接库的建立与调用

一、 实验目的

(1)理解动态链接库的实现原理。
(2)掌握Windows系统动态链接库的建立方法。
(3)掌握Windows环境下动态链接库的调用方法。

二、 实验准备

动态链接库(Dynamic Link Library DLL)是一个可执行模块,它包含的函数可以由Windows应用程序调用以提供所需功能,为应用程序提供服务。
动态链接库文件在Windows系统中的扩展名为.dll,它由全局数据结构、若干函数组成,运行时被系统加载到进程的虚拟地址空间中,成为调用进程的一部分。如果与其他的动态链接库没有冲突,该文件通常映射到进程虚拟地址空间地址上。

相关API函数介绍
1.动态链接库入口函数
DllMain()函数是动态链接库的入口函数,当Windows系统加载动态链接库时调用该函数,DllMain()函数不仅在将动态链接库加载到进程地址空间时被调用,在动态链接库进程分离时也被调用。在Windows系统的动态链接库中,DllMain()是默认的入口函数。
函数原型:

BOOL  APIENTRY  DllMain(
HANDLE  hModule,
DWORD  ul_reason_for_call, 
LPVOID  lpReserved
	)
{
   
return  TRUE;
}

参数说明:
hModule:为动态链接库的句柄,其值与动态链接库的地址相对应。
ul_reason_for_call:指明系统调用该函数的原因。
lpReserved:说明动态链接库是否需要动态加载或卸载,lpReserved为NULL表示需要动态加载或使用FreeLibrary()卸载,即运行时用到该动态库链接库时才将其装入内存,当进程不用该动态链接库时,可以使用FreeLibrary()将动态链接库卸载。lpReserved为非NULL表示静态加载,进程终止时才卸载,即进程装入内存时同时将其动态链接库装入,进程终止时动态链接库与进程同时被卸载。
使用入口函数还能使动态链接库在被调用时自动做一些初始化工作,如分配额外的内存或其他资源;在撤销时做一些清除工作,如回收占用的内存或其他资源。需要做初始化或清除工作时,DllMain()函数格式如下:

BOOL  APIENTRY  DllMain(
	HANDLE  hModule,
	DWORD  ul_reason_for_call,
	LPVOID  lpReserved
	)
{
   
	Switch (ul_reason_for_call)
	{
   
		case DLL_PROCESS_ATTACH:
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

初始化或清除工作分以下几种情况:
DLL_PROCESS_ATTACH当动态链接库被初次映射到进程的地址空间时,系统将调用该动态链接库的DllMain()函数,给它传递 参数ul_reason_for_call的值DLL_PROCESS_ATTACH。当处理DLL_PROCESS_ATTACH时,动态链接库应执行动态链接库函数要求的任何与进程相关的初始化工作,如动态链接库堆栈的建立等。当初始化成功时,DllMain()返回TRUE,否则返回FALSE,并终止整个程序的执行。
DLL_PROCESS_DETACH当动态链接库从进程的地址空间被卸载时,系统将调用该动态链接库的DllMain()函数,给 它 传 递 参 数ul_reason_for_call的 值DLL_PROCESS_DETACH。 当处理DLL_PROCESS_DETACH时,动态链接库执行与进程相关的清除操作,如堆栈的撤销等。
DLL_THREAD_ATTACH当在一个进程中创建进程时,系统查看当前映射进程的地址空间中的所有动态链接库文件映像,并调用每个带有DLL_THREAD_ATTACH 值的DllMain()函数文件映像。这样,动态链接库就可以执行每个线程的初始化操作。 新创 建的线程负责自行动态链接库的所有DllMain()函数中的代码。
当一个新动态链接库被映射到进程地址空间时,如果该进程内已经有若干个线程正在执行,那么系统将不为现有的线程调用带DLL_THREAD_ATTACH值的DllMain()函数。只有当新线程创建,动态链接库被映射到进程地址空间时,它才可以调用带有DLL_THREAD_ATTACH值的DllMain()函数。另外,系统并不为主线程调用带DLL_THREAD_ATTACH值的DllMain()函数。进程初次启动时映射到进程的地址空间中的任何动态链接库均接收DLL_PROCESS_ATTACH通知,而不是DLL_THREAD_ATTACH通知。
DLL_THREAD_DETACH终止线程的方法是系统调用ExitThread()函数撤销该线程, 但如果ExitThread()函数要终止动态链接库所在的线程,系统不会立即将该线程撤销,而是取出这个即将被撤销的线程,并让它调用已映射的动态链接库中所有带有DLL_THREAD_DETAC值的DllMain()函数。通知所有的动态链接库执行每个线程的清除操作,只有当每个动态链接库都完成了对DLL_THREAD_DETACH通知的处理时,操作系统才会终止线程的运行。
如果当动态链接库被撤销时仍然有线程在运行,那么带有DLL_THREAD_DETACH值的DllMain()函数就不会被任何线程调用。所以在处理DLL_THREAD_DETACH时,要根据具体情况进行。
2.动态链接库导入/导出函数
动态链接库文件中包含一个导出函数表,这些导出函数有他们的符号名和标识名被唯一地确认,导出函数表中还包含了动态链接库中函数的地址。当应用程序加载动态链接库时,通过导出函数表中各个函数的符号名和标识名找到该函数的地址。如果重新编译动态链接库文件,并不需要修改调用动态链接库的应用程序,除非改变了导出函数的符号 名和其它参数。
在动态链接库源程序文件中声明导出函数的代码如下:

_declspec(dllexport)  MyDllFunction(int x,int y);

其中关键字_declspec(dllexport)表示要导出其后的函数MyDllFunction()。如果一个动态链接库文件中的函数还需要调用其他动态链接库,此时,动态链接库文件除了导出函数外还需要一个导入函数,声明导入函数的代码如下:

_declspec(dllimport)  DllAdd(int x,int y);

其中关键字_declspec(dllimport) 表示要导入其 后的函数DllAdd(),在生成动态链接库时,链接程序会自动生成一个与动态链接库相对应的导入/出库文件(.lib文件),下面的例子中建立一个名为SimpleDll的动态链接库工程文件,在SimpleDll工程的Debug目录下,可以 看到 SimpleDll.dll和 S

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值