Windows内核读书笔记——Windows异常分发处理机制

IDT是处理异常,实现操作系统与CPU的交互的关口。

系统在初始化阶段会去填写这个结构。

IDT的每一个表项都成为门描述符,因为IDT的功能就像大门一样,从一个空间跳到另一个空间去执行。

IDT中包含三种门描述符

  • 任务门描述符:用于任务切换
  • 中断门描述符:用于描述中断处理例程
  • 陷阱们描述符:用于描述异常处理例程

CPU如何使用IDT

cpu首先根据IDTR找到IDT,再利用向量号码找到门描述符。再去判断门描述符的类型,如果是任务描述符,CPU会执行硬件方式的任务切换,切换到描述符所定义的线程。

如果是陷阱或中断描述符,那么会去调用处理例程。X64架构不支持硬件方式的任务切换,也就不再存在任务门了。

在调用处理例程之前,CPU会把EFLAGS、CS、EIP压入栈,如果发生的异常有错误代码则把错误代码也压入堆栈。

windows系统使用EXCEPTION_RECORD结构描述异常。

1 typedef struct _EXCEPTION_RECORD {
2   DWORD                    ExceptionCode;//异常代码
3   DWORD                    ExceptionFlags;//异常标志
4   struct _EXCEPTION_RECORD  *ExceptionRecord;//相关的另一个异常
5   PVOID                    ExceptionAddress;//异常发生的地址
6   DWORD                    NumberParameters;//参数数组中的参数个数
7   ULONG_PTR                ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];//参数数组
8 } EXCEPTION_RECORD, *PEXCEPTION_RECORD;

异常代码,可以认为是异常的别称,有的异常有异常代码有的则没有。

CommonDispatchException函数会在栈中生成一个EXCEPTION_RECORD结构,把当前的数据情况写入到这个结构中。

然后会以这个结构为参数调用KiDispatchException来分发异常。

软件异常,软件异常是通过直接或间接调用内核函数NtRaiseException产生的,用户层也可调用这个函数,用户层导出了一个RaiseException函数在kernel32.dll中,供用户产生一个自定义的异常。

RaiseException函数的实现原理是把相应的参数放入EXCEPTION_RECORD结构中,调用RtlRaiseException函数,这个函数把当前的线程上下文放入CONTEXT结构中,然后调用NtRaiseException。

NtRaiseException内部实现函数是KiRaiseException

 1   //来自WRK1.2
 2    NTSTATUS
 3    KiRaiseException (
 4        IN PEXCEPTION_RECORD ExceptionRecord,//异常记录
 5        IN PCONTEXT ContextRecord,//线程上下文结构
 6        IN PKEXCEPTION_FRAME ExceptionFrame,//不使用,为空
 7        IN PKTRAP_FRAME TrapFrame,//栈帧基地址
 8        IN BOOLEAN FirstChance//表示是第一轮还是第二轮处理
 9       )
10
11 {
12     //省略了部分内容
13     //把ContextRecord复制到当前线程的内核栈中
14     KeContextToKframes(TrapFrame,
15                        ExceptionFrame,
16                        ContextRecord,
17                        ContextRecord->ContextFlags,
18                        PreviousMode);
19     //把异常记录中的异常代码最高位清零,这样可以分辨出软件异常和CPU异常
20     ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
21     //调用分发异常的函数
22     KiDispatchException(ExceptionRecord,
23                         ExceptionFrame,
24                         TrapFrame,
25                         PreviousMode,
26                         FirstChance);
27
28     return STATUS_SUCCESS;
29 }
时间: 2024-10-29 19:11:50

Windows内核读书笔记——Windows异常分发处理机制的相关文章

Windows内核读书笔记——SEH结构化异常处理

SEH是对windows系统中的异常分发和处理机制的总称,其实现分布在很多不同的模块中. SEH提供了终结处理和异常处理两种功能. 终结处理保证终结处理块中的程序一定会被执行 1 __try 2 { 3 //要保护的代码 4 } 5 __finally 6 { 7 //终结处理块 8 } 退出保护块的方式:正常结束和非正常结束两种 1.正常结束 正常执行并顺序进入终结处理块称为正常结束 2.非正常结束 因为发生异常或是因为return.goto.break.continue等流程控制语句而离开被

C++windows内核编程笔记day07_day08,可视化建菜单、加速键使用、绘图等

可视化操作创建的菜单,加载到窗口. 方法1:注册时指定菜单 wce.lpszMenuName=MAKEINTRESOURCE(IDR_MENUMAIN);//数字形式的资源ID转换为字符串形式的资源 方法2: //创建窗口时加载菜单资源 HMENU menumain= LoadMenu(g_hinstance,MAKEINTRESOURCE(IDR_MENUMAIN)); menumain 传入 CreateWindowEx();//倒数第三个参数 窗口指定小图标: 1.注册时指定 wce.hI

C++windows内核编程笔记day09_day10,对话框和窗口基本控件等的使用

//设置字体颜色 SetTextColor(hdc,RGB(255,0,0)); //窗口背景 //wce.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); //wce.hbrBackground=CreateSolidBrush(RGB(0,0,255)); //设置字体背景 SetBkColor(hdc,RGB(0,0,200)); //设置字体背景模式 SetBkMode(hdc,TRANSPARENT);//字体背景透明 //创建字体,成功返回字体,失败返回

C++windows内核编程笔记day11 win32静态库和动态库的使用

windows库程序: 静态库: 源代码被链接到调用的程序或动态库,被调用时,代码最少有1份,文件后缀.LIB 动态库: 函数被程序或其他动态库调用,被调用时,代码只有1份,文件后缀.DLL 静态库(C语言): 创建时,选择文本类型文件,输入Clib.c,设置输出路径 ../lib/Clib.lib int Clib_add(int a,int b) { return a+b; } 同一上工作区,建立控制台程序(.c文件)调用静态库: #include<STDIO.H> #pragma com

C++windows内核编程笔记day13 进程、线程与信号量

Windows进程 进程是一个容器,包含程序执行需要的代码.数据.资源等信息, windows进程的特点: 每个进程都有自己的ID号 每个进程都有自己的地址空间,进程之间无法访问对方的地址空间. 每个进程都有自己的安全属性 每个进程至少包含一个线程. 获取和释放环境信息 GetEnvironmentStrings FreeEnvironmentStrings 获取或设置 本程序的环境变量 GetEnvironmentVariable SetEnvironmentVariable 示例: char

C++windows内核编程笔记day14 其他线程同步技术

线程同步技术: 原子锁 临界区(段) 互斥 事件 信号量(线程示例时已经使用过) 可等候定时器 使用范围:原子锁<临界区<互斥 效率:    原子锁>临界区(用户态)>互斥(内核态) 一般用临界区. //等候多个信号 DWORD WaitForMultipleObjects( DWORD nCount,             // number of handles in array CONST HANDLE *lpHandles,  // object-handle array

Windows内核学习笔记之浅析系统调用

在潘老师<Windows内核原理与实现>一书,解析了Windows应用程序发出的系统调用.图示如下. 从图可看出,系统调用所提供的服务(函数)是运行在内核中的,也就是说,在"系统空间"中. 用户空间与系统空间所在的内存区间不一样,同样,对于这两种区间,CPU的运行状态也不一样. 在用户空间中,CPU处于"用户态":在系统空间中,CPU处于"系统态". CPU从系统态进入用户态是容易的,因为可以执行一些系统态特有的特权指令,从而进入用户

c++windows内核编程笔记day12 硬盘逻辑分区管理、文件管理、内存管理

windows系统磁盘文件存储: 分区格式:NTFS / FAT32 GetSystemDirectory();//获取系统路径 GetWindowsDirectory();//获取windows路径 GetCurrentDirectory();//获取当前工作文件夹 SetCurrentDirectory();//改动当前工作文件夹 CreateFile/ReadFile/WriteFile/GetFileSize/SetFilePointer //返回文件大小的低32位 DWORD GetF

windows程序设计读书笔记3——字符显示2

由于显示的字符可能会不全,我们很容易想到的一个解决办法是使用滚动条. 先看一下代码,再进行分析: /*---------------------------------------------------- SYSMETS2.C -- System Metrics Display Program No. 2 (c) Charles Petzold, 1998 ----------------------------------------------------*/ #define WINVER