内核与系统中的Windows进程

时间:2009-09-03 18:15:32

标签: windows operating-system kernel interrupt dispatcher

我在内核和用户模式中有一些与Windows进程相关的问题。

如果我有一个hello world应用程序,以及一个公开新系统调用的hello world驱动程序foo(),我很好奇我在内核模式下能做什么,不能做什么。

对于初学者来说,当我编写新的hello world应用程序时,我会获得一个新进程,这意味着我拥有自己的用户模式VM空间(让它保持简单,32位窗口)。所以我有2GB的空间,我“拥有”,我可以偷看,直到我心中的内容。但是,我受到我的程序的约束。我不能(不要把共享的记忆带入这个)触摸任何人的记忆。

如果,我编写这个hello world驱动程序,并从我的用户应用程序调用它,我(驱动程序代码)现在处于内核模式。

首先澄清/问题: 我仍然在与用户模式应用程序相同的过程中,对吗?仍然有相同的PID?

记忆问题: 内存作为VM提供给我的进程,即使我有1GB的RAM,我仍然可以访问4GB内存(2GB用户/ 2GB内核 - 不关心服务器上的交换机细节,或具体细节,这里只是一般假设)。 作为一个用户进程,我无法窥视任何内核模式的内存地址,但我可以做任何我想要的用户空间,对吗?

如果我调用我的hello world驱动程序,从驱动程序代码中,我是否仍然拥有相同的用户模式内存视图?但是现在我还可以在内核模式下访问任何内存?

此内核模式内存是否为SHARED(与用户模式不同,这是我自己的进程副本)?也就是说,编写驱动程序更像是为单个进程编写一个线程化应用程序(操作系统除外?)

下一个问题。作为驱动程序,我可以更改正在运行的进程吗?说,我知道另一个应用程序(比如用户模式的web服务器),并为该进程加载VM,更改它的指令指针,堆栈,甚至将不同的代码加载到进程中,然后切换回我自己的应用程序? (我不想在这里做任何邪恶的事情,我只是好奇它真的意味着处于内核模式)?

此外,一旦进入内核模式,我可以阻止操作系统抢占我吗?我认为(在Windows中)您可以设置您的IRQL级别来执行此操作,但即使在阅读Solomons书籍(Inside Windows ...)之后,我也不完全理解这一点。我将问另一个与IRQL / DPC直接相关的问题但是,现在,我想知道内核驱动程序是否有能力将IRQL设置为High并接管系统。

更多内容,但这些问题的答案会有所帮助。

2 个答案:

答案 0 :(得分:8)

每个进程都有一个“上下文”,其中包含特定于该进程的VM映射(通常在32位模式下<2 GB)。当在用户模式下执行的线程进入内核模式时(例如,来自系统调用或IO请求),同一线程在此过程中仍在使用相同的上下文执行。 PsGetCurrentProcessId此时将返回与GetCurrentProcessID之前用户模式相同的内容(与线程ID相同)。

进入内核模式后,上下文附带的用户内存映射仍然存在:您可以直接从内核模式访问用户内存。为了安全起见,需要做一些特别的事情:Using Neither Buffered Nor Direct I/O。特别是,用户空间范围内的无效地址访问尝试将引发需要捕获的SEH异常,并且由于该进程中另一个线程的操作,用户内存的内容可能随时发生变化。访问内核地址范围中的无效地址会导致错误检查。在用户模式下执行的线程无法访问任何内核内存。

内核地址空间不是进程上下文的一部分,因此在所有进程之间映射相同。但是,任何时候任何数量的线程都可能在内核模式下处于活动状态,因此它不像单线程应用程序。通常,线程在进入内核模式时服务于它们自己的系统调用(而不是使用专用的内核工作线程来处理所有请求)。

保存线程和进程状态的底层结构在内核模式下都可用。通过从该进程创建MDL并将其映射到系统地址空间,最好从另一个进程映射另一个进程的VM。如果您只想更改另一个线程的上下文,可以完全从user mode完成。请注意,必须挂起一个线程才能在没有竞争条件的情况下更改其上下文。不建议将模块从内核模式加载到进程中;所有加载器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

答案 1 :(得分: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