转自http://www.2cto.com/os/201404/289687.html
《程序员面试宝典》一书中写到,windows搜索dll文件的顺序为:(1)内存(2)knowndlls(3)清单与.local(4)应用程序目录(5)当前工作目录(6)系统目录(7)路径变量
总觉得不太明白,遂查资料确认一下。
查msdn如下:http://msdn.microsoft.com/zh-cn/library/7d83bc18.aspx
通过隐式和显式链接,Windows 首先搜索“已知 DLL”,如 Kernel32.dll 和 User32.dll。Windows 然后按下列顺序搜索 DLL:
当前进程的可执行模块所在的目录。
当前目录。
Windows 系统目录。GetSystemDirectory 函数检索此目录的路径。
Windows 目录。GetWindowsDirectory 函数检索此目录的路径。
PATH 环境变量中列出的目录。
隐式链接有时称为静态加载或加载时动态链接。显式链接有时称为动态加载或运行时动态链接。
在隐式链接下,使用 DLL 的可执行文件链接到该 DLL 的创建者所提供的导入库(.lib 文件)。使用 DLL 的可执行文件加载时,操作系统加载此 DLL。客户端可执行文件调用 DLL 的导出函数,就好像这些函数包含在可执行文件内一样。
//msdn
为隐式链接到 DLL,可执行文件必须从 DLL 的提供程序获取下列各项:
-
包含导出函数和/或 C++ 类的声明的头文件(.h 文件)。类、函数和数据均应具有 __declspec(dllimport),有关更多信息,请参见 dllexport、dllimport。
-
要链接的导入库(.LIB files)。(生成 DLL 时链接器创建导入库。)
-
实际的 DLL(.dll 文件)。
使用 DLL 的可执行文件必须包括头文件,此头文件包含每个源文件中的导出函数(或 C++ 类),而这些源文件包含对导出函数的调用。 从编码的角度讲,导出函数的函数调用与任何其他函数调用一样。
若要生成调用可执行文件,必须与导入库链接。 如果使用的是外部生成文件,请指定导入库的文件名,此导入库中列出了要链接到的其他对象 (.obj) 文件或库。
操作系统在加载调用可执行文件时,必须能够定位 DLL 文件。
在显式链接下,使用 DLL 的可执行文件必须进行函数调用以显式加载和卸载该 DLL,并访问该 DLL 的导出函数。客户端可执行文件必须通过函数指针调用导出函数。
//msdn
在显式链接下,应用程序必须进行函数调用以在运行时显式加载 DLL。 为显式链接到 DLL,应用程序必须:
-
调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。
-
调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。 由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。
-
使用完 DLL 后调用 FreeLibrary。
“已知的 DLL”(非正式名称)的功能指由内核的模块加载器进行特殊处理的 DLL(动态链接库)列表。当加载器发现具有指向已知的 DLL 的加载时动态链接的程序时,就会立即使用已知的副本,而忽略通常情况下应用于模块加载的搜索算法。
那上面所写的内存是什么道理呢?搜索动态库首先是内存,如果内存中存在就不需要加载,否则需要搜索到后加载到内存中。dll的主要优点也是节省内存和减少交换操作。很多进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本。相反,对于每个用静态链接库生成的应用程序,Windows 必须在内存中加载库代码的一个副本。
感觉.local文件像是配置之类的,没查到相关资料,不清楚。
当前工作目录 (Current Working Directory), 一般来说,每个进程都有一个与之相关联的分级文件系统(hierarchical file system)下的目录,称之为该进程的当前工作目录。如果程序刚进入main入口处的时候,当前工作目录其实就是程序启动的目录,但是当前工作目录是可以通过程序进行设置或者随着OpenFileDialog、SaveFileDialog等对象所确定的目录而改变。
应用程序所在的目录, 该进程从中启动的目录,即程序文件自身所在的目录。和当前工作目录是不同的。