现在的位置: 首页 > 综合 > 正文

《深入解析Windows操作系统第4版》随笔记录03

2018年02月07日 ⁄ 综合 ⁄ 共 7564字 ⁄ 字号 评论关闭

条目1、所谓陷阱处理器(trap handler),是指与某个特殊的中断或异常相关联的一个函数。中断时一个异步事件,主要由I/O设备、处理器时钟,或者定时器产生的。异常是一个同步条件,它是一个特殊指令执行的结果,具有可再现性(即:同样的条件下可重现原来的异常),异常有:内存访问违例、除零错误等等。(P85)

条目2、无论是硬件还是软件都能够产生异常和中断,当一个硬件异常或者中断产生时,Windows在被中断的线程的内核栈上创建一个陷阱帧(trap frame),并且把线程的执行状态保持到陷阱帧里。在内核调试器中输入dt nt!_ktrap_frame可以看到陷阱帧的定义。(P86)

条目3、在大多数情况下,内核安装了前端陷阱处理函数,在内核将控制权转交给与该陷阱相关的其他函数之前或者之后,由这些前端陷阱处理函数来执行一些常规的陷阱处理任务。

条目4、硬件产生的中断往往是由I/O设备激发的,当这些设备需要服务的时候,它们以中断的方式通知处理器。系统软件也可能产生中断。(P87)

条目5、内核安装了中断陷阱处理器(如上图)来响应设备的中断。中断陷阱处理器或者将控制权传递给一个负责处理该中断的外部例程(ISR),或者传递给一个响应该中断的内部内核例程。如:设备驱动程序提供了ISR来处理设备中断,而内核则为其他类型的中断提供了中断处理例程。(P87)

条目6、在系统引导的时候,Windows会填充中断分发表(Interrupt Dispatch Table IDT),其中包含了指向内核中负责处理每个中断和异常的例程指针。利用!idt内核调试器命令,可以查看IDT的内容。(P87)

条目7、Windows将硬件IRQ映射至IDT中的中断号上,同时它也利用IDT来为异常配置陷阱处理器。(P88)

条目8、每个处理器都有单独的IDT,不同的处理器可以运行不同的ISR。(P89)

条目9、x86系统或者依赖于i8259A可编程中断控制器(PIC),或者依赖于i82489高级可编程中断控制器(APIC)。APIC实际上是由几个部件构成的:一个专门接收设备中断的I/O APIC,以及一些本地APIC,和一个与i8259A兼容的中断控制器。本地APIC在一条私有的APIC总线上接收来自I/O APIC的中断,而与i8259A兼容的中断控制器则负责将APIC输入转换成与PIC等价的信号。I/O APIC负责实现中断传送算法以平衡各个处理器之间的设备中断负载。(P89)

条目10、x64体系结构与x86兼容,提供与x86同样的中断控制器APIC。IA64体系结构依赖于改进的高级可编程中断控制器(SAPIC)。APIC与SAPIC体系结构的区别:(P90)

 (1)APIC利用私有的总线将中断递交给本地APIC,SAPIC利用I/O和系统总线将中断进行更快速的提交。

 (2)在APIC系统上,中断转送和负载均衡是由APIC总线来处理的,SAPIC则将中断转送和负载均衡的功能直接编入到固件中。

条目11、利用内核调试明了!pic或!apic查看一个单处理器系统上有关PIC的配置情况,或者一个多处理器上有关APIC的配置情况。!命令ioapic查看I/O APIC(即连接至设备的中断控制器部件)。(P91)

条目12、在x86系统中,内核在内部使用从0至31的数值来代表IRQL(中断请求级别);而在x64和IA64系统中,内核采用从0至15的数值来代表IRQL。内核为软件中断定义了一组标准的IRQL,而HAL则将硬件中断号映射为IRQL。(P91)中断是按照优先级处理的,高优先级的中断会抢占低优先级中断的执行权。(P92)

条目13、每个处理器的IRQL设置决定了该处理器可以接收哪些中断。IRQL也被用来实现对一些内核模式数据结构的同步访问。(P93)

条目14、利用命令!irql可查看一个处理器的IRQL(Windows Server 2003 +)。使用命令!pcr可以查看PCR(处理器控制区)的内容。使用命令!prcb可以查看PCR的扩展结构PRCB(处理器控制块)。(P94)

条目15、只能在内核模式中改变一个处理器的IRQL,用户模式线程不能改变处理器的IRQL。(P95)

条目16、在Windows中,总线型驱动程序确定总线(PCI、USB等等)上有哪些设备,以及哪些中断可以分配给某一个设备,并将这些信息汇报给即插即用管理器,即插即用管理器在考虑了所有其他设备的可接受的中断分配方案以后,确定为每个设备分配哪个中断。然后,它调用HAL函数HalpGetSystemInterruptVector将中断映射到对应的IRQL。(P95)

条目17、在单处理器x86系统上,HAL执行直接翻译一个给定的中断向量:用27减去中断向量值,就是它的IRQL。在x86多处理器系统上,HAL按照循环方式,在设备IRQL(DIRQL)的范围内循环利用,将IRQL分配给中断向量。在x64和IA64系统上,HAL将IRQ对应的中断向量除以16,作为它的IRQL。(P96)

条目18、使用内核性能剖析程序(Kernrates)来分析性能,跟踪单个进程所消耗的CPU比率,以及内核模式下独立于进程的时间消耗。下载地址:http://www.microsoft.com/whdc/system/sysperf/krview.mspx(P97)

条目19、运行在DPC/Dispatch级别或者更高级别上的代码,一个重要的限制是它不能等待一个对象,另一个限制是,只能访问非换页的内存。(P99)

条目20、中断对象包括ISR地址、设备中断时所在的IRQL级别、自定义分发代码,以及内核中与该ISR关联的IDT项。当中断发生时,一份驻留在中断对象中的代码将调用实际的中断分发器(KiInterruptDispatch或KiChainedDispatch例程),并将该中断对象的指针传递给它。(P99)

条目21、在一个多处理器系统中,内核为每个CPU分配一个中断对象,并对它进行初始化,使该CPU上的本地APIC能够接受特定的中断。(P99)

条目22、检查与中断关联的中断对象的内容。(P101)

 (1)获取所有IDT信息:

 (2)查看IDT为895db76c VIDEOPRT!pVideoPortInterrupt的中断对象的内容:

条目23、将一个ISR与某个特定的中断级别关联起来,称为连接一个中断对象,而将一个ISR与IDT项断开关联,则称为断开一个中断对象。这些操作分别由内核函数IoConnectInterrupt和IoDisconnectInterrupt来完成。(P102)

条目24、当一个线程不能继续运行的时候,内核就会直接调用分发器,从而立即导致一个环境切换。(P103)

条目25、为了给硬件中断提供及时的服务,Windows让设备驱动程序ISR执行最少最必要的工作来响应它们的设备,将易变的中断状态保存起来,并且将数据传输I/O或者其他并非时间紧迫的中断处理活动推迟到一个位于DPC/Dispatch IRQL级别上的DPC中再执行。(P103)

条目26、DPC是通过一个DPC对象来表示的。DPC对象是一种内核控制对象,其所包含的最重要信息是,当内核处理该DPC中断时将要调用的那个系统函数的地址。每个处理器都有一个DPC队列,用于存放等待执行的DPC对象。(P104)

条目27、当处理器的IRQL将要从DPC/Dispatch或者更高级的IRQL降低到某个更低级的IRQL(APC或者被动级别)时,内核就会处理DPC。(P104)

条目28、监视中断和DPC活动。(P106)

条目29、当一个DPC例程运行的时候,它不会考虑自己当前被映射到哪个进程地址空间中。DPC例程可以调用内核函数,但是它们不能调用系统服务、产生分页错误、或者创建或等待分发器对象。(P106)

条目30、追踪特定的中断服务例程和延迟的过程调用的执行情况。(P107)

 (1)启动事件捕捉功能:tracelog -start -f kernel.etl -b 64 -useperfCounter -eflag 8 0x307 0x4084 0 0 0 0 0 0

 (2)停止捕捉事件: tracelog -stop

 (3)为事件捕捉过程生成报告:tracerpt kernel.etl -df -o -report

 (4)步骤(3)生成两个文件:workload.txt  和 dumpfile.csv。

 (5)打开workload.txt将会看到在每个驱动程序类型的ISR和DPC上所花的时间的摘要信息。打开dumpfile.csv文件,搜索第二列值为“DPC”或“ISR”的行。用内核命令ln <其第8列的值>,即可显示出执行相应DPC或ISR的函数名字。

条目31、异步过程调用(APC)提供了一种在特定用户线程环境中执行用户程序和系统代码的途径。APC例程可以分为资源(对象)、等待对象句柄、引发页面错误,以及调用系统服务。(P108)

条目32、DPC队列是系统范围的,而APC队列是与特定线程相关的,即每个线程有它自己的APC队列。(P108)I/O完成机制是通过在发起的I/O的线程里插入一个APC来实现的。(P109)只有当一个线程处于可警告的等待状态时,用户模式APC才可以交付给该线程。(P109)

条目33、在x86平台上,所有的异常都有预定义的中断号,这些中断号直接对应于IDT中的表项,每个表项指向了某一个特定异常的陷阱处理器。所有的异常,除了那些简单到通过陷阱处理器就可以解决的以外,都是由一个称为异常分发器的内核模块来服务的。(P110)

条目34、系统服务分发器KiSystemService将调用者的参数从线程的用户模式栈中拷贝到内核模式栈中,然后指向该系统服务。

条目35、Windows有两个内置的系统服务表,它最多可以支持4个系统服务表。系统服务分发器将32位系统服务号中的其中一个2位域解释成一个表索引。系统服务号的低12位被用于在该表索引所指定的表中进行索引。(P121)

条目36、Windows的内部有两种类型的对象:执行体对象内核对象。所谓执行体对象,是指由执行体的各个组件(如进程管理器、内存管理器、I/O子系统等等)所实现的对象。内核对象是指由Windows内核实现的一组更为基本的对象。许多执行体对象包含(封装)了一个或者多个内核对象。(P126)

条目37、执行体对象往往或者是由一个环境子系统代表一个用户应用程序而创建的,或者是由操作系统的各个组件作为它们常规操作的一部分而创建的。Windows子系统使用执行体对象来导出它自己的对象集合,其中许多对象直接对应于执行体对象。(P127)

条目38、每个对象都有一个对象头和一个对象体。对象管理器控制了对象头,而执行体组件则控制了由它们创建的对象类型的对象体。(P128)

条目39、对象管理器使用对象头(dt nt!_object_header)中保存的数据来管理这些对象,而无须关心它们的类型。(P129)

条目40、实验:查看对象头和类型对象。(P131)

 (1)使用!process命令查找一个进程对象。

 (2)执行!object命令,使用以上进程对象(体)的地址作为参数。

 (3)由于对象头地址 + 0x18 = 对象体地址,因此对象头地址为: 8982d9e8,命令dt _object_header 8982d9e8 查看对象头内容。

 (4)命令dt _object_type 8982d040 查看类型对象的内容。

 (5)查看该对象类型的所有对象都公共的属性,以及方法指针。

条目41、用户模式下不能操纵类型对象,因为对象管理器并没有提供任何有关类型对象的服务。(P133)

条目42、同步指的是,一个线程通过等待某个对象从一种状态改变成另一种状态,从而达到同步其执行过程的能力。一个对象是否有能力支持同步,取决于该对象是否包含了一个内嵌的分发器对象,这是一种内核对象。(P133)

条目43、对象方法是指在一个对象的生命期的特定点上,对象管理器自动调用的一个或者多个例程,对象管理器支持的方法如下。(P133)

条目44、除了对象管理器的名字空间外,在Windows中还有两个名字空间:注册表名字空间和文件系统名字空间。注册表名字空间是配置管理器实现的,而文件系统名字空间则是I/O管理器在文件系统驱动程序的帮助下实现的。(P134)

条目45、所有的用户模式进程在其线程使用一个对象以前,必须先拥有一个指向该对象的句柄。句柄被用做指向系统资源的间接指针,避免了直接与系统数据结构打交道。(P135)

条目46、对象句柄是一个索引,指向与进程相关的句柄表(handle table)中的表项,进程块(EPROCESS)中有一个域指向进程的句柄表。一个进程的句柄表包含了所有已被该进程打开的那些对象的指针。(P137)

条目47、在x86系统上,每个句柄项是一个包含2个32位成员的结构:一个指向对象的指针(以及一些标志),一个准许的访问掩码。在64位系统上,每个句柄项12字节长:一个64位指针指向对象头,以及一个32位访问掩码。(P139)

条目48、一个内核模式的函数可以在任何一个进程环境中访问其在内核句柄表中创建的句柄;用户模式应用程序无法访问内核句柄表中的句柄。(P139)内核句柄表中句柄的引用值大于0x80000000。(P140)

条目49、句柄表可以采用内核调试器!handle命令查看(可参考Windbg帮助)。

条目50、当一个进程创建一个对象或者打开一个指向已有对象的句柄时,该进程必须要指定一组期待的访问权限。(P140)对象管理器调用安全引用监视器检查该对象的安全描述符是否允许该进程所请求的访问类型。(P141)

条目51、对象保持力通过引用计数维持。当系统增减句柄计数的时候,它也会增减引用计数,即便对象的句柄计数达到了0,该对象的引用计数可能仍然是一个正数。只有当引用计数减到0的时候,对象管理器就会将对象从内存中删除。(P142)

条目52、执行体的对象名字空间是全局的,对于系统中的所有进程都是可见的。对象管理器查找对象的名称只发生在以下两种情况:(1)当进程创建一个命名对象时检查全局名字空间是否已存在该名称。(2)当进程打开一个命名的对象,对象管理器查找并返回对象句柄。(P144)

条目53、对象的名称存储在哪里取决于对象的类型。(P144)

条目54、对象目录对象是对象管理器支持这种层次命名结构的手段。无论是内核模式的代码,还是用户模式代码都可以创建对象目录,并在其中存储对象。(P146)

条目55、在Windows 2000上,符号链接位于/??对象目录下,在Windows XP和Windows Server 2003上位于/Global??目录下。(P146)

条目56、在名字空间中属于每个会话的局部部分包括/DosDevices、/Windows和/BaseNamedObjects。将名字空间中同样的部分做成独立的拷贝,这称为名字空间实例化。对象管理器在/Session/X(X是用户会话标识符)下创建上述三个目录的私有版本,从而实现局部的名字空间。(P147)

条目57、互斥指的是,保证任何时候只有一个线程可以访问某一特定的资源。(P149)如果一段代码区访问了一个不可共享的资源,则这样的代码区称为临界区(critical section)(P150)

条目58、同步机制的最简单形式,莫过于直接依赖硬件(X86的lock指令前缀)上对于多处理器安全操作整数值的支持,以及针对执行比较操作的支持。(P151)

条目59、内核用来实现多处理互斥的机制称为自旋锁,自旋锁是一个与某个全局数据结构相关联的锁原语。在许多系统结构上,自旋锁是通过硬件支持的test-and-set操作来实现的,即在一条原子命令内测试一个锁变量的值并且获得该锁。(P152)

条目60、对于不同的对象,信号状态的定义也有所不同。(P158)

条目61、与事件对象不同的是,互斥体对象有与之关联的所属权。(P160)

条目62、带键的事件,也是一个同步对象。它使得一个线程在等待的时候可以指定一个“键”,当同一个进程中的另外一个线程用同样的键给该事件发出信号时候,该线程就会被唤醒。(P160)

条目63、有两个数据结构对于搞清楚谁正在等待什么事至关重要的。这两个数据结构就是分发器头(ntdll!_DISPATCHER_HEADER)和等待块(ntdll!_KWAIT_BLOCK).(P161)

条目64、查看线程正在等待的对象列表。

 (1)通过!process命令,显示一个线程正在等待的一个事件对象。

 (2)使用dt命令来解释该等待对象的分发器头。

 (3)查看等待列表中的等待对象。

条目65、执行体资源是一种支持共享和独占访问的同步机制;如同快速互斥体一样,在获取执行体资源以前,它们要求普通的内核模式APC交付已被禁止。(P164)

条目66、内核调试器!locks命令在换页内存池中查找执行体资源对象,并转储出它们的状态。(P164)

条目67、设备驱动程序或者执行体组件通过调用执行体函数ExQueueWorkItem或者IoQueueWorkItem,可以请求一个系统辅助线程的服务。(P166)

条目68、系统辅助线程有三种类型:延迟型辅助线程,紧急型辅助线程、超紧急型辅助线程。通过执行体的ExpWorkerInitialization函数来创建的延迟型和紧急型辅助线程的数目取决于系统中内存的数量,以及该系统是否是服务器系统。(P167)

条目69、使用!exqueue内核命令来查看按类型分类的系统辅助线程列表。

条目70、本地过程调用(LPC)是一种用于高速传递休息的跨进程通信设施。它是一种内部机制,只能用于Windows操作系统组件。(P171)

条目71、LPC通常被用于在一个服务器进程和该服务器的一个或者多个客户进程之间进行通信。既可以在两个用户模式的进程之间建立起一个LPC连接,也可以在一个内核模式的组件和一个用户模式的进程之间建立起LPC连接。(P174)

条目72、Wow64是指允许在64位Windows上执行32位0x86应用程序的软件。(P178)在系统调用方面,Wow64钩住了所有从32位代码转变至原生64位系统的代码路径,也钩住了64位原生系统需要调用至32位用户模式代码的所有代码路径。(P179)异常分发方面,Wow64通过ntdll的kiUserExceptionDispatcher钩住了异常分发过程。(P179)

抱歉!评论已关闭.