Windows中的内核进程与系统进程

9
我有一些与Windows内核和用户模式进程相关的问题。
如果我有一个hello world应用程序和一个公开新系统调用foo()的hello world驱动程序,我想知道一旦进入内核模式,我能够做什么和不能做什么。
首先,当我编写我的新的hello world应用程序时,我会得到一个新的进程,这意味着我有自己的用户模式VM空间(让我们保持简单,32位windows)。因此我拥有2GB的“自己”的空间,可以随心所欲地探测和查看。然而,我受到我的进程的限制。我不能(还没有涉及共享内存)触及任何其他人的内存。
如果我编写这个hello world驱动程序,并从我的用户应用程序中调用它,那么我(驱动程序代码)现在处于内核模式下。
首先是澄清/问题: 我仍然处于与用户模式应用程序相同的进程中,对吗?PID是否仍然相同?
内存问题: 内存被呈现为VM提供给我的进程,即使我有1GB的RAM,我仍然可以访问4GB的内存(2GB用户/2GB内核-不考虑服务器上的开关或细节,只是一般假设)。作为用户进程,我不能窥视任何内核模式内存地址,但我可以在用户空间做任何想做的事情,对吗?
如果我从驱动程序代码中调用我的hello world驱动程序,我是否仍然具有相同的用户模式内存视图?但现在我也能访问内核模式中的任何内存?
这个内核模式内存是共享的(不像用户模式,它是我的进程副本)吗?也就是说,编写驱动程序更像是为单个进程编写多线程应用程序(除调度之外)?
下一个问题。作为驱动程序,我能否更改正在运行的进程。比如说,我知道另一个应用程序(比如一个用户模式的Web服务器),并加载该进程的VM,更改其指令指针、堆栈或甚至加载不同的代码到该进程中,然后切换回我的应用程序?(我不打算做任何恶意的事情,我只是好奇到底什么是内核模式)
还有,在内核模式下,我能否防止操作系统抢占我?我认为(在Windows中),你可以将你的IRQL级别设置为这样做,但我仍然不完全理解这一点,即使在阅读Solomons的书(Inside Windows...)之后。我会问另一个与IRQL/DPC直接相关的问题,但现在,我想知道内核驱动程序是否有能力将IRQL设置为高并接管系统。

我不认为这是一个糟糕的问题,+1。 - Rob
2个回答

8
每个进程都有一个“上下文”,其中包含特定于该进程的VM映射(在32位模式下通常小于2 GB)。当运行在用户模式下的线程进入内核模式(例如从系统调用或IO请求中),同一线程仍在进程中以相同的上下文执行。在这一点上,PsGetCurrentProcessId 将返回与在用户模式下刚刚使用 GetCurrentProcessID 返回的相同的东西(线程ID也是如此)。
进入内核模式后,与上下文一起提供的用户存储映射仍然存在:您可以直接从内核模式访问用户存储器。但是,需要采取特殊措施才能确保安全:不使用缓冲或直接I/O。特别是,在用户空间范围内尝试访问无效地址将引发SEH异常,需要捕获,并且由于该进程中另一个线程的操作,用户存储器的内容可能随时变化。在内核地址范围内访问无效地址会导致错误检查。在用户模式下执行的线程无法访问任何内核存储器。
内核地址空间不是进程上下文的一部分,因此在所有进程之间映射方式相同。但是,在任何时候可能有任意数量的线程在内核模式下活动,因此它不像单线程应用程序。通常,在进入内核模式时,线程服务于其自己的系统调用(而不是拥有专用内核工作线程来处理所有请求)。

保存线程和进程状态的底层结构全部在内核模式下可用。最好提前从另一个进程创建一个MDL并将其映射到系统地址空间中,以便从其他进程映射VM。如果您只想更改另一个线程的上下文,这完全可以在用户模式下完成。请注意,为了避免竞争条件,必须暂停线程才能更改其上下文。从内核模式加载模块是不明智的;所有加载程序API都仅设计供用户模式使用。

每个CPU都有一个当前IRQL,它决定了什么事件可以打断CPU当前正在执行的操作。只有来自更高IRQL的事件才能抢占CPU的当前活动。

  • PASSIVE_LEVEL 是用户代码和大多数内核代码执行的地方。许多内核API要求IRQL为 PASSIVE_LEVEL
  • APC_LEVEL 用于内核APC
  • DISPATCH_LEVEL 用于调度程序事件(在NT术语中称为调度程序)。在此级别下运行将防止您被调度程序抢占。请注意,在此级别下具有任何类型的页面错误不安全;存在与内存管理器尝试检索页面相关的死锁可能性。如果在 DISPATCH_LEVEL 或更高级别上出现页面错误,则内核将立即发生故障检查。这意味着您无法安全地访问分页池、分页代码段或任何未被锁定的用户内存(例如通过MDL)。
  • 以上是与硬件设备中断级别相关联的级别,称为DIRQL
  • 最高级别是HIGH_LEVEL。没有什么可以抢占这个级别。它由内核在系统发生故障时使用以停止系统。

我建议阅读Scheduling, Thread Context, and IRQL


4
这个主题的好的入门资料可以在http://www.codinghorror.com/blog/archives/001029.html找到。
正如Jeff指出的那样,对于用户模式内存空间:
“在用户模式下,执行代码无法直接访问硬件或引用内存。在用户模式下运行的代码必须委托给系统API来访问硬件或内存。由于这种隔离提供的保护,用户模式中的崩溃总是可以恢复的。大多数在您的计算机上运行的代码将在用户模式下执行。”
所以你的应用程序将无法访问内核模式内存,事实上你与驱动之间的通信可能是通过IOCTL(即IRP)完成的。
然而,内核具有访问一切的权限,包括对您的用户模式进程映射的访问权限。这是一个单向道,用户模式不能映射到内核模式,因为这涉及安全和稳定性。即使通过内核模式驱动程序,也不建议映射到用户模式内存。
至少在WDF之前是这样的。我不确定用户模式驱动程序的内存映射能力。
另请参见:http://www.google.com/url?sa=t&source=web&ct=res&cd=1&url=http%3A%2F%2Fdownload.microsoft.com%2Fdownload%2Fe%2Fb%2Fa%2Feba1050f-a31d-436b-9281-92cdfeae4b45%2FKM-UMGuide.doc&ei=eAygSvfuAt7gnQe01P3gDQ&rct=j&q=user+mode+mapping+into+kernel+mode&usg=AFQjCNG1QYQMcIpcokMoQSWJlGSEodaBHQ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接