我在接受采访时被问到这样一个问题:
在Windows中,假设有一个exe,它依赖于某些dll,当你开始时 exe,然后依赖的dll将被加载,这些dll 在内核模式或用户模式下加载?
我对这个问题不太确定,而不是提及答案 - 你能帮忙解释一下吗?
感谢。
答案 0 :(得分:3)
我不是Windows内部工作原理的专家,但我知道正确的答案是用户模式,因为只有与操作系统相关的进程才被允许进入内核空间http://en.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode
基本上,如果它不是操作系统进程,它将在用户空间中分配。
答案 1 :(得分:2)
这个问题非常不精确/含糊不清。“在Windows中”暗示了一些东西,但不清楚是什么。可能面试官指的是Win32子系统 - 也就是Windows通常被视为最终用户的部分。问题的最后部分更加含糊不清。
现在,当进程和部分对象(在MSDN中称为MMF,加载的PE图像,如.exe
和.dll
和.sys
) 确实< strong>内核对象并需要来自底层执行程序(和内存管理器等)的一些帮助,DLL中的相应代码(包括DllMain
中的相应代码)的行为与任何其他用户模式进程完全相同,从用户模式进程调用时。也就是说,从DLL运行代码的每个线程都将转换到内核模式以最终使用OS服务(打开文件,加载PE文件,创建事件等),或者只要足够就在用户模式下执行一些操作。
也许采访者甚至对内存范围感兴趣,这些内存范围有时被称为“内核空间”和“用户空间”,传统上是32位的2 GB边界。是的,DLL通常最终低于2 GB边界,即“用户空间”,而其他共享内存(内存映射文件,MMF)通常最终高于该边界。
面试官甚至有可能成为对DLL的常见误解的牺牲品。 DLL本身只是一个休眠的内存,它没有自己运行任何东西永远(是的,DllMain
也是如此)。当然,加载器将处理各种事情,例如重定位,但最终没有任何事情会在没有被显式或隐式调用的情况下运行(在加载DLL的进程的某个线程的上下文中)。因此,出于所有实际目的,问题需要您回复。
我想知道面试官是否清楚了解他/她所询问的概念。
让我补充一些信息。从另一个答案的评论来看,似乎人们对DLL也有关于驱动程序存在同样的误解。驱动程序更接近DLL的概念而不是EXE(或最终“进程”)的概念。问题是驱动程序在大多数情况下自己没有做任何事情(尽管它可以创建系统线程来改变它)。 驱动程序不是进程,也不会创建进程。
答案 2 :(得分:0)
对于任何为Windows进行任何重要应用程序开发的人来说,答案显然是用户模式。让我解释两件事。
<强> DLL 强>
动态链接库与常规旧链接库或.lib非常相似。当您的应用程序使用.lib时,它会在编译时间之后粘贴到函数定义中。您通常使用.lib来存储API并修改函数而不必重新构建整个项目,只需将旧的.lib粘贴在旧的和只要接口(函数名称和参数)上。还没有改变它仍然有效。很棒的模块化。
.dll完全相同,但它不需要重新链接或任何编译。您可以将.dll视为基本上是.lib,它被编译为.exe,与使用它的应用程序相同。简单地说,新的.dll共享名称和功能签名,这一切都正常。您只需更换.dll即可更新应用程序。这就是为什么大多数Windows软件包含.dll和一些exe文件的原因。
.dll的使用以两种方式完成
隐式链接
如果你有一个.dll userapplication.dll
,你可以使用userapplication.lib
定义dll中的所有入口点。您只需链接到静态链接库,然后在工作目录中包含.dll。
明确链接
Alernatively你可以通过首先调用LoadLibrary(userapplication.dll)
来编程加载.dll,它会返回.dll的句柄。然后GetProcAddress(handle, "FunctionInUserApplicationDll")
返回一个你可以使用的函数指针。这样,您的应用程序可以在尝试使用之前检查内容。 c#
有点不同但更容易。
用户/内核模式
Windows有两种主要的执行模式。用户模式和内核模式(内核进一步分为系统和会话)。对于用户模式,物理内存地址是不透明的。用户模式使用映射到实际内存空间的虚拟内存。用户模式驱动程序也巧合.dll's。用户模式应用程序通常可以使用4Gb的虚拟寻址空间。两个不同的应用程序无法有意义地使用这些地址,因为它们与该应用程序或进程的上下文有关。用户模式应用程序无法通过回退到内核模式驱动程序来了解它的物理内存地址。基本上你用来编程的一切(除非你开发驱动程序)。
内核模式受到保护,不受用户模式应用程序的影响。大多数硬件驱动程序在内核模式的上下文中工作,并且通常所有windows api都分为用户和内核两类。内核模式驱动程序使用内核模式api,并且不使用用户模式api,因此不会使用用户.dll(你甚至不能打印到控制台导致是用户模式api set)。相反,他们使用.sys文件作为驱动程序,并且在用户模式下基本上以相同的方式工作。一个.sys是一种pe格式,所以基本上.exe就像.dll就像一个带有main()入口点的.exe。
所以从askers的角度来看,你有两个小组
[kernel / .sys]和[user / .dll或.exe]
内核中确实没有.exe,因为操作系统完成的所有操作都不是用户。当系统或其他内核组件启动时,他们通过调用DriverEntry()方法来执行它,所以我猜这就像main()。
所以这个问题在这个意义上很简单。