9

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

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

对于初学者,当我编写新的 hello world 应用程序时,我得到了一个新进程,这意味着我有自己的用户模式 ​​VM 空间(让我们保持简单,32 位窗口)。所以我有 2GB 的空间是我“拥有的”,我可以偷看看,直到心满意足。但是,我受制于我的过程。我不能(暂时不要将共享内存带入其中)触及其他任何人的内存。

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

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

内存问题:内存作为 VM 呈现给我的进程,也就是说,即使我有 1GB 的 RAM,我仍然可以访问 4GB 的内存(2GB 用户/2GB 内核 - 不介意服务器上的开关细节或细节,只是一个这里的一般假设)。作为用户进程,我无法查看任何内核模式内存地址,但我可以对用户空间做任何我想做的事情,对吗?

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

这个内核模式内存是共享的吗(与用户模式不同,它是我自己的进程副本)?也就是说,编写驱动程序更像是为操作系统的单个进程编写线程应用程序(调度?)

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

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

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

4

2 回答 2

8

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

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

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

保存线程和进程状态的底层结构在内核模式下都是可用的。映射另一个进程的 VM 最好从另一个进程提前完成,方法是从该进程创建一个 MDL 并将其映射到系统地址空间。如果您只想更改另一个线程的上下文,则可以完全从user mode完成。请注意,必须挂起线程才能更改其上下文,而不会出现竞争条件。不建议从内核模式将模块加载到进程中;所有加载程序 API 都设计为仅在用户模式下使用。

每个 CPU 都有一个当前运行的IRQL。它决定了哪些事情可以中断 CPU 当前正在做的事情。只有来自更高 IRQL 的事件才能抢占 CPU 的当前活动。

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

我推荐阅读调度、线程上下文和 IRQL

于 2009-09-04T15:05:46.637 回答
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

于 2009-09-03T18:38:43.847 回答