命令和程序如何与 Window OS 通信
Posted
技术标签:
【中文标题】命令和程序如何与 Window OS 通信【英文标题】:How do commands and programs communicate with the Window OS 【发布时间】:2011-09-06 10:21:32 【问题描述】:为 Windows 编写的程序如何与 Windows NT 内核交互或向其发出命令?
内核如何返回任何数据?
【问题讨论】:
【参考方案1】:为了回答这个问题,了解用户模式和内核模式之间的区别很重要。内核模式是特权最高的 CPU 模式,执行代码可以完全访问硬件。它用于最低级别的操作系统功能。用户模式是一种更受限制的 CPU 模式。它可以防止代码直接访问硬件。应用程序在用户模式下运行。当然,他们仍然需要以某种方式访问硬件,所以他们需要调用内核。
这就是您的问题所在。为了允许用户模式代码调用内核,Windows 内核设置了一个入口点。在基于 x86 的系统上,此入口点是软件中断 (int 2e) 或 sysenter/syscall 指令。执行这些指令会导致 CPU 模式切换,将 CPU 从用户模式转换为内核模式。一旦 CPU 切换了模式,它就会调用内核指定的函数。在 Windows 中,这个函数就是系统服务调度器。
系统服务调度器负责调用用户态代码想要的内核服务。它获取由用户模式代码指定的功能编号,并在系统服务描述符表 (SSDT) 中查找它。 SSDT 基本上是指向每个内核服务的函数指针列表。一旦它识别出正确的内核服务,它就会使用用户模式应用程序也指定的参数调用它。内核服务完成后,CPU 通过 iret 指令(如果来自软件中断)或 sysexit/sysret(如果来自 sysenter/syscall)返回到应用程序。
所有这些听起来都相当复杂,这就是 Windows 对程序员隐藏这些细节的原因。 Windows 不要求他们通过内核设置的入口点直接与内核通信,而是为程序员提供了几个 DLL,它们为他们执行此操作。
现在这里再次变得更加复杂。从用户态调用内核服务的过程是在ntdll.dll中实现的,但是ntdll.dll并不是大多数程序员直接使用的。相反,它导出了一组称为 Native API 的通用内核服务。在此之上,Win32 API 在 kernel32.dll 中实现。 kernel32.dll 中的大多数函数只是 ntdll.dll 中函数的封装。
您可能会问为什么要这样做。为什么不让 kernel32.dll 直接调用内核函数呢?这样做的原因是允许不同的多用户模式 API。 Windows NT 旨在支持多种 API,不仅是 Win32,还支持 POSIX 和 OS/2。每个用户态API调用ntdll.dll实现自己的API,无需自己直接调用内核服务。
【讨论】:
【参考方案2】:伙计,这是一个非常广泛的问题。
如果你真的想了解这一点,我推荐这本书Windows Internals By Mark Russinovich et ag。另一本好书是经典的Operating Systems by Deitel et al。
不过从Inside Windows NT by Helen Custer(第 1 版)开始——这是一本非常基础的书(请注意,最后一个链接有第 2 版封面的图片——更详细)。
简而言之,好的。
Windows 组件之间有多种通信协议。他们中的大多数将在一天结束时通过一些共享内存(例如缓冲区、堆栈等)使用传递数据。但是协议可能非常复杂,并且对于不同的通信是不同的。
我给你的建议是看看上面的书,确定 Windows 操作系统的体系结构是如何结合在一起的。从这里您将看到各种组件如何通信。
(装出一副书呆子的表情)- 相信我,这些都是了解 Windows 和一般操作系统的好书,如果这就是你的船的话。
【讨论】:
【参考方案3】:尝试阅读:Chapter 5 - Windows NT 4.0 Workstation Architecture。应该可以开始了。
最后,一些 API 直接构建在一些用户态 DLL 中。这些是直接执行的。其他需要内核模式帮助/服务。
对于这些(我从上面的链接中引用)
应用程序使用 API 对用户模式进行图形调用 动态链接库。实现调用的组件生成一个 内核模式陷阱调用执行以切换其线程并复制 它的调用参数从它的用户模式堆栈到它的内核模式堆栈。 然后,处理器的堆栈寄存器切换为指向内核 模式。现在线程可以在Executive中运行了。
应用程序使用本地与受保护的子系统进行通信 过程调用 (LPC),一种独立于应用程序的方法 同一台计算机上的组件之间的通信。之后 线程切换到内核模式,微内核调度 LPC 送货上门。
使用快速 LPC,一种优化的通信方法,微内核 识别出来自应用程序的调用涉及 环境子系统。它考虑调用应用程序线程和 要配对的接收子系统线程。接收线程可以 现在使用发送线程中的未过期时间。
图形调用参数传递给接收子系统 线。接收线程切换回用户模式以完成 图形请求。
子系统完成其任务,然后将控制权返回给 用同样的方法在应用程序中等待调用线程。
调用线程(来自 DLL)在切换回用户模式之前 将控制权返回给应用程序。
Microsoft 操作系统工程师也使用了共享的概念 内存窗口以加快通信速度。数据被放置在一个临时的 由进程管理器管理的共享内存窗口 管理人员。这让应用程序可以查看子系统的内存 并在不使用 LPC 的情况下共享数据。但是,由于应用 线程必须仍然在执行、内核/用户模式转换中运行 和线程切换仍然是必需的。
这里有一些关于 exactly
是如何完成调用的注释(使用的 ASM 命令是什么):The system call dispatcher on x86 如果需要的话。
【讨论】:
以上是关于命令和程序如何与 Window OS 通信的主要内容,如果未能解决你的问题,请参考以下文章