文章目录
- Windows操作系统的版本
- Windows NT和Windows 95
- 基础概念和术语
- 内核调试
- 用户模式调试
Windows操作系统的版本
Windows NT和Windows 95
Windows NT和Windows 95之间的一些结构性差异,以及Windows NT优于Windows 95及其后续版本的一些方面:
Windows NT | Windows 95 |
---|---|
支持多处理器系统 | 不支持多处理器系统 |
文件系统支持安全性,如自主访问控制 | 文件系统不支持 |
完全32位(现在是64位)的操作系统 | 继承了大量的16位代码 |
完全可重入的 | 部分不可重入 |
可让16位Windows应用程序运行在他们自己的地址空间中 | 总是在一个共享的地址空间中运行16位Windows应用程序,共享地址空间中程序相互影响,可能会破坏其他程序的运行 |
进程共享的内存只对那些映射了这一共享内存区的进程才是可见的 | 所有共享的内存都是可见的,而且在任何一个进程内都可以写这些内存 |
存在关键的操作系统页面在用户模式下是可写的,从而允许一个用户程序破坏系统,或者使系统崩溃 | |
Windows 95可以做到但Windwos NT系统无法做到的一点是:运行所有老的MS-DOS和Windows 3.1应用程序(特别是那些要求直接访问硬件的应用程序)以及16位MS-DOS设备驱动程序。Windows NT的最初目标是:能够运行大多数原有的16位应用程序,同时又不破坏系统的完整性和可靠性。 |
基础概念和术语
Windows API:Windows 应用程序接口(API)是针对Miscrosoft Windows操作系统家族的系统编程接口。每个操作系统实现了Windows API的不同子集。可能会发现许多函数名和接口看起来并不一致,原因之一是:要确保Windows API与老的16位Windows API保持兼容。
SDK:platform software development kit,平台软件开发工具。文档描述了Windows API。
.NET框架:是由一个被称为框架类库(FCL,Framework class library)的类库和一个提供了托管代码执行环境的公共语言运行库(CLR,Common Language Runtime)组成。后者提供的环境包含以下一些特性:即时编译、类型检查、垃圾回收和代码访问安全性等。.NET框架中的所有组件的实现形式都是用户模式的标准Windows DLL,它们建立在飞托管的Windows API之上。
Windows API函数:指Windows API中已被文档化的可调用子例程。
原生的系统服务(或者 执行体系统服务):操作系统中未文档化的、可在用户模式下调用的底层服务。
内核支持函数(或 例程):指位于Windows操作系统内部且只能在内核模式下调用的子例程。
Windows服务:由Windows服务控制管理器启动的进程
DLL(动态链接库):指一组可调用的子例程,合起来被链接成一个二进制文件,使用这些子例程的应用程序可以动态地加载此二进制文件。Windows的用户模式组件和应用程序大量使用了DLL。DLL比静态库的优势在于:应用程序可以共享DLL,Windows保证在内存中只有一份DLL代码,供所有引用该DLL的应用程序共享。
程序是指一个静态的指令序列,而进程则是一个容器,其中包含了当执行一个程序的特定实例时所用到的各种资源。一个Windows进程是由以下元素构成:
1)一个私有的虚拟地址空间,指该进程可以使用的一组虚拟内存地址
2)一个可执行程序,定义了初始的代码和数据,并且被映射到该进程的虚拟地址空间中
3)一个已打开句柄的列表,这些句柄指向各种系统资源,该进程内所有线程都可以访问这些系统资源
4)一个被称为访问令牌的安全环境,标识了与该进程关联的用户、安全组和特权
5)一个被称为进程ID的唯一标识符(在内部被称为客户ID)
6)至少一个执行线程
每个进程也指向它的父进程或者创建者进程。但是如果父进程退出的话,子进程中的父进程信息并不会被更新。因此一个进程有可能指向一个已不再存在的父进程。可使用Windows调试工具箱中的tlist.exe的/t查看进程树,如下:
对于父进程不在的进程,显示的时候被调整到最左边。此外还有一个工具:process explorer进程管理器可提供关于进程、线程的详细信息。优势有:
1)显示被执行的映像文件的完整路径名
2)显示进程的安全令牌(安全组和特权的列表)
3)加亮显示进程中的服务,包含显示名和说明
4)显示作业(job)中的进程,以及作业的细节
5)显示运行.NET/WinFX应用的进程,以及与.NET相关的细节
6)显示进程和线程的启动时间
7)显示内存映射文件的完整列表
8)能够挂起/杀死一个进程
9)容易识别出一段时间以来哪些进程消耗了绝大多数CPU时间
10)进程树
11)无需特别设置就可以访问一个进程内的已打开句柄
12)列出一个进程内的DLL
13)一个进程内的线程活动
14)用户模式的线程栈
15)针对系统线程的内核模式线程栈
16)内核内存限制
线程:一个进程内部的实体,也是Windows执行此进程时的调度实体。没有线程,进程的程序不可能运行。线程包含以下一些部件:
1)一组代表处理器状态的CPU寄存器中的内容
2)2个栈:一个用于当前线程在内核模式下执行时,另一个用于线程在用户模式下执行时
3)一个被称为线程局部存储区(TLS)的私有存储区域,各个子系统、运行库和DLL都会用到该存储区域
4)一个被称为线程ID的唯一标识符(在内部也被称为客户ID——进程ID和线程ID是在同一个名字空间中生成的,所以永远不会重叠)
5)线程也有自己的安全环境
线程的环境:易失的寄存器、栈和私有存储区域。这些信息会随着Windows所在的体系结构的不同而有所不同,因此这些数据结构必须是与底层体系结构相关的。
纤程与线程:纤程使得一个应用程序可以调度它自己的“线程”的执行过程,而不必依赖于Windows内置的基于优先级的调度机制。也被称为“轻量级”的线程。因为是在用户模式下实现的,因此从调度的角度看,对于内核是不可见的。和线程不同的是:纤程不会自动被执行,必须手工调用指定的函数选中一个纤程,才能使它运行。新的纤程一直运行,直到它退出,或者直到调用指定方法关闭纤程或者选择领一个纤程运行。
共享内存区(Windwos API中称为文件映射对象)
每个进程都有一个安全环境,被存储在一个被称为访问令牌的对象中。进程的访问令牌包含了进程的安全标识和凭证。默认情况下,线程没有自己的访问令牌,但它们也可以包含一个访问令牌,因此单独的线程可以模仿另一个进程得到安全环境——包括在远程Windows系统上运行的进程——而不会影响到当前进程中的其他线程。
虚拟地址描述符(VAD):一些数据结构,内存管理器利用这些数据结构来记录一个进程所使用的虚拟地址。
作业(job):Windows在进程模型上作的一个扩展。主要功能是:使得一组进程被当做一个整体来管理和维护。允许对特定的属性进行控制,也允许对一个进程,或者所有与作业相关联的进程进行限制。也为所有与该作业相关联的进程记录下基本的审计信息。
虚拟内存:Windows实现了一个基于平面(线性)地址空间的虚拟内存系统,每个进程自己独立拥有一个很大的私有地址空间。虚拟内存提供了一个内存逻辑视图,它可能并不对应于内存的物理布局。在运行时内存管理器借助于硬件的支持,将虚拟地址翻译或者映射成真正存放数据的物理地址。操作系统通过控制这一层保护或者映射机制,可以保证一个进程不会闯入到另一个进程中,也不会改写操作系统的数据。
虚拟地址空间的大小随着硬件平台的不同而有所差异。低一半地址空间的映射关系反映了当前执行进程额虚拟地址空间,但是高一半地址空间的映射关系总是由操作系统的虚拟内存构成的。
处理器访问模式:用户模式和内核模式。为了避免用户应用程序访问/修改关键的操作系统数据,因此使用了这2种模式。内核模式:允许访问所有的系统内存和所有的CPU指令。处理器让操作系统软件比应用软件有更高的特权级,从而为操作系统设计者提供了一层保护的基础,确保一个行为不正常的应用程序不会破坏系统整体的稳定性。
对于在内核模式下运行的组件,Windows对它们的读写系统内存并不加以保护。因此在加载第三方设备驱动程序时需要加倍小心,因为一旦进入内核模式,这些软件就可以完全访问所有的操作系统数据。这也是Windows之所以要引入驱动程序签名的原因之一。
从用户模式转换为内核模式(或 从内核模式转为用户模式)本身并不会影响线程的调度,模式切换非环境切换。
终端服务:Windows为了在单个系统中支持多个可交互的用户会话而提供的能力。
对象:在Windows操作系统中,指某一个静态定义的对象类型的单个运行时的实例。对象类型包含了一个系统定义的数据类型、在该数据类型的实例上进行操作的一些函数,以及一组对象属性。对象属性是对象中的数据域,每个对象属性定义了对象的一部分状态。对象方法就是操纵对象的手段,通常是读取或改变对象的属性。
对象和和普通数据结构之间最根本的区别是:对象的内部结构是被隐藏的。这一区别将对象的底层实现与那些仅仅使用该对象的代码隔离开来。必须调用一个对象服务才可以获得对象内部的数据,或者把数据置到对象内部。不可以直接读取或改变一个对象内部的数据。
对象技术提供了一种便捷的方式实现下列4个重要的操作系统任务:
1)为系统资源提供了可供人读的名字
2)在进程之间共享资源和数据
3)保护资源,避免未授权的访问
4)引用跟踪
Windows操作系统中并不是所有数据结构都是对象。只有确实需要被共享、保护、命名或者让用户模式的程序看得到(通过系统服务)的数据才被放到对象中。
Windows的核心安全功能:针对所有可共享对象的自主保护、安全审计、登录时的口令认证、以及在一个用户释放了某一资源后,另一个用户无法通过访问未初始化资源的办法看到前一个用户留下的资源。
针对系统内部的对象,Windows有2种访问控制形式:自主访问控制、特权访问控制。自主访问控制得到做法是:由对象的所有者授权或拒绝其他人访问这些对象。特权访问控制可以确保:在无法联系到对象的所有者时,某些人也可以访问被保护的对象。
注册表:系统数据库,包含了引导和配置系统所必要的信息、系统范围的控制Windows操作的软件设置、安全数据库、以及针对每个用户的配置信息。同时注册表是个反映内存中易失数据的窗口。
Windows操作系统区别于大多数其他操作系统的特点之一是:它的大多数内部文本串是以16位宽度的Unicode字符来存储和处理的。Unicode(统一的字符编码标准)是一个国际字符集标准,为世界上绝大多数已知的字符集定义了唯一的16位值。Windows是不会转换文件内部的数据的,是由应用程序决定是否要存储为Unicode或者ANSI。
内核调试
内核调试意味着检查内核的内部数据结构,以及跟踪内核中的函数。
符号文件:包含函数和变量名称。是由连接器生成的,在调试过程中被调试器用来引用和显示这些名称。这些名称信息并不存储在二进制映像文件中,因为在执行代码时并不需要这些信息。基于此,必须确保在一个调试会话中,调试器能够访问到与正在调试的映像文件相关联的符号文件。
想获得当前调试所需符号的正确版本,最容易的办法是:利用Miscrosoft的按需符号服务器,只要在调试器中用一种特殊的语法来指定符号路径即可。如:
调试器葱internet的符号服务器上加载所需要的符号,并且在本地的c:\symbols文件下维护一份拷贝
src*c:\symbols*http://msdl.miscrosoft.com/download/symbols
用户模式调试
附载到一个进程上时用两种方式:侵入式的、非侵入式的。
侵入式:程序员可以检查或者修改该进程的内存,设置断点,执行其他的调试功能。
非侵入式:只是打开被调试的进程,并不作为一个调试器被附载到目标进程中。可以检查和修改目标进程中的内存,但不能设置断点。
可用于内核调试的Miscrosoft调试器有两种主要的形式:命令行版本(Kd.exe)和图形用户界面版本(Windbg.exe),这两个版本提供了同样的命令集。可执行以下3种类型的内核调试:
1)打开一个崩溃转储文件
2)连接到一个正在运行的系统上,并检查该系统的状态