读《软件调试》第九章

news/2024/7/20 13:48:59 标签: 操作系统, 数据结构与算法, 内存管理

今日读了张银奎老师的《软件调试》,前面的CPU和硬件相关的部分离得比較远,所以从第九章操作系统读起,今天的读书笔记:

9.2採集调试消息
调试事件分为8种
typedef enum _DBGKM_APINUMBER
{
DbgkmExceptionApi = 0, // 异常
DbgkmCreateThreadApi = 1, // 创建线程
DbgkmCreateProcessApi = 2, // 创建进程
DbgkmExitThreadApi = 3, // 退出线程
DbgkmExitProcessApi = 4, // 进程退出
DbgkmLoadDllApi = 5, // 映射DLL
DbgkmUnloadDllApi = 6, // 反映射DLL
DbgkmErrorReportApi = 7, // 内部错误
DbgkmMaxApiNumber = 8, // 这组常量的最大值
} DBGKM_APINUMBER;


9.2.2 进程和线程创建消息
操作系统就支持向调试系统发送消息,这个我是没有想到的,详细步骤例如以下:
创建用户态windows线程时,首先为线程建立必要的内核对象和数据结构,并分配栈(stack)空间,这些工作完毕后,
该线程处于挂起状态(CREATE_SUSPEND), 而后进程管理器会通知环境子系统,环境子系统会作必要的设置和登记,最后
进程管理器会调用PspUserThreadStartup例程,准备启动该线程。
为了支持调试,PspUserThreadStartup总是会调用调试子系统的内核函数DbgkCreateThread,以便让调试子系统得到处理机会。


DbgkCreateThread会检查新创建线程所在的进程是否正在被调试(依据DebugPort是否为空),假设不是,便马上返回,
假设是,则会继续检查该进程的用户态执行时间(UserTime)是否为0,目的是推断该线程是否是进程中的第一个线程,假设是,
则通过DbgkSendApiMessage()函数向DebugPort发送DbgkmCreateProcessApi消息,假设不是,
则发送DbgkmCreateThreadApi消息。
调试器收到的进程创建(CREATE_PROCESS_DEBUG_EVENT,值为3)和线程创建(CREATE_THREAD_DEBUG_EVENT,值为2)事件就是源于这两个消息。


9.2.3 进程和线程退出消息 --- 与上面类似


9.2.4 模块映射和反映射消息 
DLL(Dynamic-link Library)是Windows中使用最多的技术之中的一个。如:
Windows内核文件NTOSKRNL.EXE尽管是EXE后缀,事实上质是一个DLL;
NTDLL.DLL是连接用户态和操作系统内核的桥梁,用户态代码通过它訪问内核服务;
Windows子系统DLL(KERNEL32.DLL,ADVAPI32.DLL,USER32.DLL,GDI32.DLL)是Windows API的载体;


观察进程中的DLL:
1.执行notepad.exe
2.启动VC6,通过Build>Start Debug>Attatch to Process...菜单弹出Attach Process对话框,然后选择notepad.
3. 通过Debug>Modules...菜单弹出模块列表,便能够看到notepad进程中的DLL了。
第二列是该模块在进程空间中的地址(虚拟地址,均小于0x80000000),可见这些模块都是位于用户空间中的。


存在于多个进程空间中的DLL,是否会反复占用内存?
否!当LoadLibrary()和LoadLibraryEx() API载入一个DLL时,会首先推断该DLL是否已经载入过,假设是,则不会反复载入,
仅仅是将该DLL相应的内存页面映射(map)到目标进程的内存空间,并把该DLL的引用次数加1.
当进程退出或调用FreeLibrary() API要卸载一个DLL时,Windows会从进程的虚拟内存空间中把该DLL的映射删除(unmap),
并递减该DLL的引用次数,假设引用次数变为0,那么该DLL会被彻底移出内存。


9.2.5 异常消息
为了支持调试,系统会把被调试程序中发生的全部异常发送给调试器。
内核中KiDispatchException函数是分发异常的枢纽,它会给每一个异常安排最多两轮被处理的机会,
对于每一轮处理机会,它都会调用调试子系统的DbgkForwardException函数来通知调试子系统。


总结:
系统的进程管理器、内存管理器和异常分发函数会调用调试子系统的Dbgk採集例程,来向调试子系统通报调试消息,
这些例程被调用后会依据当前进程的DebugPort字段来推断当前进程是否处于被调试状态。
假设不是,便忽略这次调用,直接返回;
假设是,便产生一个DBGKM_APIMSG结构,然后调用下一节将介绍的DbgkSendApiMessage函数来发送调试消息。

转载于:https://www.cnblogs.com/mfrbuaa/p/3777902.html


http://www.niftyadmin.cn/n/1318030.html

相关文章

ACL配置

ACL配置实验目的 通过本实验,可以掌握以下技能: 配置接口IP地址。配置访问控制列表。验证访问控制列表的配置。 设备需求 Cisco路由器3台,分别命名为R1、R2和R3。1台access server。1台PC机。 拓扑结构及配置说明 学院出口路由器R2与学校…

MAT(Memory Analyzer Tool)工具入门介绍

1.MAT是什么? MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出…

[Java] MAP、LIST、SET集合解析

在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系: java.util Collection 这个接口extends自 --java.lang.Iterable接口 List 接口 -ArrayList 类 -LinkedList 类 -Vector 类 …

EIGRP协议配置

EIGRP协议配置 实验目的 通过本实验,可以掌握以下技能: 配置接口IP地址。配置EIGRP协议。验证EIGRP协议配置。 设备需求 Cisco路由器4台,分别命名为twins、sa、gill和hua。其中twins具有两个串行接口和1个以太网接口;sa具有1…

C# winform控件 之 messagebox

DialogResult是枚举值 MessageBoxIcon是枚举值 DialogResult okcancelMessageBox.Show("确认更改数据?", "注意", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);if (okcancelDialogResult.OK){MessageBox.Show("刚才你选的是ok");}

jhat中的OQL(对象查询语言)

如果需要根据某些条件来过滤或查询堆的对象&#xff0c;这是可能的&#xff0c;可以在jhat的html页面中执行OQL&#xff0c;来查询符合条件的对象。 一.基本语法 select <javascript expression to select> [from [instanceof] <class name> <identifier>] …

Facebook 如何发布代码 (How Facebook Ships Code 译文)

http://www.ltesting.net/ceshi/ruanjianzhiliangbaozheng/pzgl/2014/0304/207117.html转载于:https://www.cnblogs.com/vivianlou/p/3786016.html

OSPF协议配置

OSPF协议配置 实验目的 通过本实验&#xff0c;可以掌握以下技能&#xff1a; 配置接口IP地址。配置OSPF协议。验证OSPF协议配置。 设备需求 Cisco路由器3台&#xff0c;分别命名为twins、sa和gill。其中twins具有2个串行接口&#xff1b;sa具有1个以太网接口和一个串行接…