Windows内核学习笔记(一)
前言
此随笔为本人笔记,并非系统学习应当使用
内核
ntoskrnl.exe 是 Windows 操作系统的核心内核程序文件,全称为 Windows NT Operating System Kernel。它是 Windows 操作系统正常运行的基础
内核层级
R0是内核层,R3是应用层,而R1、R2不使用
这样就解决了我之前不理解R1、R2是什么应用的问题
Windows内核中主要可以分成三层:硬件抽象层(HAL),内核层(也称微内核micro-kernel),执行体层。
Ntdll.dll的功能
- 作为桥梁:Ntdll.dll是用户模式代码和内核模式系统服务之间的连接纽带。它使得用户模式的应用程序能够方便地调用内核提供的系统服务,而无需直接与内核进行交互,从而保证了系统的稳定性和安全性。
- 提供存根函数:对于内核提供的每一个系统服务,Ntdll.dll都对应提供一个存根函数。这些存根函数的名称以“Nt”作为前缀,例如NtCreateProcess(用于创建进程)、NtOpenFile(用于打开文件)等。存根函数的作用是为用户模式代码提供一个接口,当用户模式代码调用这些存根函数时,Ntdll.dll会将调用请求转发给相应的内核模式系统服务。
- 提供系统级支持函数:除了存根函数,Ntdll.dll还提供了许多系统级的支持函数,用于实现各种系统功能。这些支持函数按照功能不同有不同的前缀,例如:
- 映像加载器函数(以“Ldr”为前缀):用于加载和管理程序的映像文件,例如LdrLoadDll(加载动态链接库)等。
- 系统时间函数(以“Etw”为前缀):用于与系统时间相关的操作,例如EtwStartTrace(开始跟踪事件)等。
- 一般的运行支持函数(以“Rtl”为前缀):提供各种运行时支持功能,例如RtlAllocateHeap(分配堆内存)等。
- 字符串支持函数:用于字符串操作,例如RtlCompareString(比较字符串)等。
中断请求级别
在Windows操作系统中调用内核函数时,必须关注中断请求级别(IRQL,Interrupt Request Level),原因如下:
IRQL的定义与作用
IRQL是一个表示中断优先级的数字,用于确定中断处理的优先顺序。它确保处理器在处理不同任务时维持正确的操作顺序和安全性。Windows内核通过IRQL管理对硬件资源的访问,以及处理不同级别的中断和异常。
不同IRQL级别对内核函数调用的限制
- PASSIVE_LEVEL:最低的IRQL级别,大多数线程操作和内核函数在此级别运行。可以访问分页内存,且不会被中断。
- APC_LEVEL:禁止异步过程调用(APC),某些内核函数在此级别不可用。
- DISPATCH_LEVEL:禁止调度器操作,只能访问非分页内存,许多内核函数在此级别无法调用。
- DIRQL(设备IRQL):用于硬件中断处理,几乎无法调用普通内核函数。
- 高IRQL(HIGH_LEVEL):这是最高的IRQL级别,用于系统关键操作,此时几乎所有的中断都被禁止。
调用内核函数时IRQL的重要性
- 内核函数通常对IRQL有明确的要求,调用时必须确保当前IRQL与函数要求的级别相符。如果不遵守这一规则,可能导致系统崩溃或数据损坏。
- 驱动程序开发中,合理管理IRQL至关重要。例如,某些函数只能在低IRQL下运行,而当前IRQL较高时,直接调用这些函数会导致系统不稳定。
- 避免死锁和性能问题
- 在高IRQL级别下,系统资源的访问和同步机制受到严格限制。开发者需要确保在高IRQL级别下尽量减少资源持有时间,避免复杂操作,以防止死锁和性能问题。
因此,调用内核函数时必须关注IRQL,以确保系统的稳定性和数据一致性。
疑问
作者在阅读资料后提出:
何时应当处理中断级别?何时应当修改中断级别?
何时应当处理中断级别?
处理中断级别通常是指在内核模式代码中,开发者需要明确当前的IRQL级别,并根据当前IRQL级别调整代码逻辑。以下是一些需要特别关注IRQL的场景:
-
调用内核函数时
- 每个内核函数都有其允许运行的IRQL级别范围。在调用内核函数之前,必须确认当前IRQL是否符合函数的要求。例如:
- 大多数内核函数只能在
PASSIVE_LEVEL
运行。 - 一些函数可以在
APC_LEVEL
或DISPATCH_LEVEL
运行,但不能访问分页内存。 - 在
DIRQL
或HIGH_LEVEL
下,几乎无法调用普通内核函数。
- 大多数内核函数只能在
- 如果当前IRQL不符合要求,直接调用这些函数可能导致系统崩溃。
- 每个内核函数都有其允许运行的IRQL级别范围。在调用内核函数之前,必须确认当前IRQL是否符合函数的要求。例如:
-
访问硬件资源时
- 当驱动程序需要访问硬件设备时,通常需要将IRQL提升到
DIRQL
级别,以确保在访问硬件资源时不会被其他中断打断。 - 硬件中断处理例程(ISR)通常运行在
DIRQL
级别,此时需要特别注意代码的执行效率和安全性。
- 当驱动程序需要访问硬件设备时,通常需要将IRQL提升到
-
执行同步操作时
- 在高IRQL级别下(如
DISPATCH_LEVEL
或更高),系统不允许线程切换,因此需要特别注意同步机制的使用。例如:- 在
DISPATCH_LEVEL
下,可以使用自旋锁(Spin Lock)来保护共享资源。 - 在
PASSIVE_LEVEL
下,可以使用互斥锁(Mutex)或其他同步原语。
- 在
- 在高IRQL级别下(如
-
异常处理时
- 当系统发生异常(如除零错误、访问违规等)时,异常处理例程会运行在特定的IRQL级别。此时需要根据异常的类型和优先级调整IRQL,以确保异常处理的正确性。
何时应当修改中断级别?
修改中断级别是指通过内核函数(如KeRaiseIrql
或KeLowerIrql
)显式地提升或降低当前处理器的IRQL。以下是需要修改IRQL的典型场景:
-
进入硬件中断处理
- 当硬件设备发出中断请求时,内核会自动将IRQL提升到对应的
DIRQL
级别,并执行中断服务例程(ISR)。 - 在ISR中,开发者可能需要进一步提升IRQL以执行某些高优先级操作(如处理关键硬件中断)。
- 当硬件设备发出中断请求时,内核会自动将IRQL提升到对应的
-
执行高优先级任务
- 当需要执行某些高优先级任务时(如系统关键操作),可以将IRQL提升到
HIGH_LEVEL
,以屏蔽所有中断。 - 例如,在执行某些原子操作或访问关键链表时,可能需要将IRQL提升到
HIGH_LEVEL
。
- 当需要执行某些高优先级任务时(如系统关键操作),可以将IRQL提升到
-
延迟过程调用(DPC)
- DPC用于延迟处理某些非紧急任务,通常运行在
DISPATCH_LEVEL
以下的IRQL级别。 - 在DPC中,开发者可能需要将IRQL提升到
DISPATCH_LEVEL
,以确保DPC的正确执行。
- DPC用于延迟处理某些非紧急任务,通常运行在
-
退出中断处理
- 当中断处理完成时,需要将IRQL降低到之前的级别,以恢复正常的系统运行。
- 例如,在ISR或DPC执行完成后,使用
KeLowerIrql
将IRQL降低到PASSIVE_LEVEL
。
-
避免死锁和性能问题
- 在高IRQL级别下,系统资源的访问受到严格限制。如果需要访问某些资源,可能需要将IRQL降低到较低的级别。
- 例如,如果需要访问分页内存,必须将IRQL降低到
PASSIVE_LEVEL
。
总结
- 处理中断级别:在调用内核函数、访问硬件资源、执行同步操作或处理异常时,必须明确当前的IRQL级别,并根据函数或操作的要求调整代码逻辑。
- 修改中断级别:通过
KeRaiseIrql
或KeLowerIrql
显式地提升或降低IRQL,通常用于进入硬件中断处理、执行高优先级任务、处理DPC或退出中断处理。
合理管理IRQL是确保内核模式代码稳定性和性能的关键。开发者需要根据当前的IRQL级别和操作需求,谨慎地处理和修改IRQL,以避免系统崩溃或性能问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具