windows内核情景分析-毛德操(第一章)

微内核操作系统的特点内核尽量缩小

windows内核包括了两大部分

操作系统内核(ntoskrnl.exe),另一部分则是迁移到了内核中即系统空间中的视窗服务(win32k.sys)

用户空间和系统空间

8086 80186cpu在寻址技术上还只能支持"实模式",还不能支持现代意义上的内存管理,因而不能支持系统空间与用户空间的划分。

现代意义的操作系统

  • 首先 操作系统在内存中的映像必须受到保护,不会因为用户程序的不良行为而受到伤害。也就是说 ,必须让CPU有"系统态(内核态)"和用户态,使得当cpu运行用户态时只能访问预先配置用户态的内存区域,而不能访问操作系统内核所在的内存区域。
    用户态 和 系统态 是不对称的,二者之间不是"井水不犯河水"的关系,而是井水不能犯河水但河水可以犯井水。
    其次,不同的用户程序之间应该互相防护,不能因一个程序的不良行为或误操作而伤害另一个用户程序。这就是说,用户程序及其数据、堆栈都应该被保护起来,与其他用户的程序、数据和堆栈隔离开来,以防受到别的用户程序的伤害。
    最后,除保护之外,用户程序在物理内存的位置应该可以浮动。在多进程的系统中,一般都会有多个应用程序同时在运行,如果这些程序都只能被装载在固定的地址上运行,就会互相牵制,整个系统的运行就受到了限制。80年代中期的事(保护模式)

Windows内核

现代操作系统的一个明显特征就是用户空间和系统空间的划分

UNIX时代

人们一直把存在于系统空间的代码和数据的集合称为"内核",因此内核是有明确边界的。空间的不同,或者说CPU运行模式(系统态和用户态)的不同,是不会被混淆的本质区别。

Windows的术语

微软并不把系统空间的所有代码和数据的集合称为内核,而是把这里面的一部分,即比较低层、与硬件靠得最近而最为核心得一部分称为"内核"即Kernel

位于最高层的是应用软件,就是一般文件扩展名为.exe的可执行程序。除.exe可执行之外,应用软件的开发者和提供者可以(但并非必须)选择把其中的一部分基础性的功能放在若干"动态连接库"DLL里面,这就是文件扩展名为.dll的可执行程序。DLL也是分层次的,相对高的DLL依赖于相对低层的DLL,调用由低层DLL所提供的服务。
在windows操作系统中,整个4GB的虚拟地址空间被对半分成两块,从地址0x80000000开始向上是"系统空间",就是内核所在的地方,下面则是"用户空间",是应用程序所在的地方。系统空间是全局的,而用户空间只属于具体的进程,每个(用户)进程都有自己的用户空间。

Windows的应用程序二进制界面 ABI

ABI 一方面是系统 调用的界面,定义了所有系统调用函数界面的集合,并规定了系统 调用如何进行;另一方面也规定了可执行程序文件的结构和格式。Windows的系统调用界面是不公开的,现在人们所知道的有关信息基本上来自有关的研究和实现,特别是来自逆向工程的研究。

系统态访问权限

CPU必须进入"系统态"才能执行存放在系统空间的程序,访问存放在系统空间的数据。
对用户空间的数据则不论处于"系统态"或"用户态"都能访问。

cpu进入内核的方式三种途径

  • 系统调用
  • 中断
  • 异常。
    当CPU运行于内核中时,尽管都是在内核中,有些操作只允许在特定的层次上进行,或者只允许对特定的层次进行。例如在中断处理的内部就不允许线程切换,线程切换只有在完了中断处理以后才能进行。所以,Windows内核规定只有在从所谓的"内核"层(而不是整个内核)退出来才可以进行线程切换。

线程调度/切换的问题上

  • 剥夺式(Preemptive):只有优先级更高的线程就绪,哪怕CPU已经在为别的优先级低的线程所用而且无意主动让路,也要立即把它夺过来;
  • 非剥夺式(Non-Pressmptive):如果CPU已经在执行别的线程,就先忍一忍,等待适当的机会。什么是机会呢?就是等正在系统空间运行的线程返回用户空间的时候。可是,优先级较高的线程之所以变成就绪,其触发的条件也必为系统调用 、中断或异常其中之一,总之是在CPU运行于系统空间的时候变成就绪的。
    其实不是剥夺不剥夺的问题(那取决于调度策略),而是什么时候剥夺的问题

Windows内存管理即虚存技术的的重要内容之一是

windows的物理页面的倒换,就是可以将已有映射但是暂时不受到访问的页面倒换到外存中去,到实际受到访问时候再倒进来,使外存称为内存的扩充。
微软把图形操作系统/视窗服务的实现也搬到了内核中,这就使内核的体积增加了很多。再说每个线程的系统空间堆栈也因此增加了许多,当线程数量很多时也确实不可忽视。有些页面注定不可倒换。例如:与中断和异常有关的代码和数据所在的页面,以及与页面倒换有关的代码和数据,倒换出去,就无法把这些页面倒换回来了。
在Linux中,属于内核的页面无论是用于代码还是数据(用于文件内存缓存的除外),是不受倒换的。因为内核毕竟是全局的,所有进程都是公用同一个系统空间

运行级别

IRQ级别即IRQL。在任一时间中CPU总是运行于其中的某一个级别,这个级别就表明了什么事情可以做,什么事情不可以做

Windows内核函数的命名

Windows的内核函数在命名有一个好的特色,就是函数名都按其所在的层次或模块上加上了特定的前缀。了解了这些前缀,看到一个函数名就可以大致知道这个函数所属的层次和模块,主要的前缀有:

  • Ex:管理层,Ex是Executive的开头两个字母。
  • Ke: 核心层,Ke是Kernel的开头两个字母。
  • Hal:硬件抽象层,Hal是HardwareAbstraction Layer的缩写。
  • Ob :对象管理,Ob是Object的开头两个字母。
  • Mm:内存管理,Mm是Memory Manager的缩写。
  • Se:安全管理,Se是Security的开头两个字母。
  • I/O: I/O管理。
  • Fs 文件系统,Fs是File System的缩写。
  • Cc:文件缓存管理,Cc表示Cache
  • Cm:系统配置管理,Cm是Configuration Manager的缩写。
  • Pp:"即插即用"管理,Pp表示PnP
  • Rtl:运行时程序库,Rtl是Runtime Library的缩写。
    一般的函数调用时通过堆栈传递参数的,而快速调用时通过ECX等寄存器传递参数,因为避免了几个堆栈操作而使效率有所提高。说明:KfLowerIrql()是个快速调用函数,这个函数名出现在汇编程序中时则变成@KfLowerIrql@4这里的前缀@表示这是快速调用函数,后缀的@4则表示这个函数带有4字节的参数,即一个参数。当然,这是通过寄存器(因为只有一个参数,所以是ECX)传递的参数,而不是通过堆栈传递的参数。
posted @ 2022-03-15 21:47  不会笑的孩子  阅读(404)  评论(0编辑  收藏  举报