内核模式 VS 用户模式
为了防止普通的应用程序修改或访问临界区的操作系统的数据,Windows使用两种访问模式:内核模式和用户模式。用户级别的应用程序代码运行在用户模式下,操作系统的代码运行在内核模式(比如系统服务和驱动)。内核模式下有权限访问所有内存和所有的CPU指令。内核模式比用户模式权限高的目的是保证系统的稳定性。
注意:X86和X64处理器定义了4个级别的代码执行权限(也叫做ring)。第0级(Ring 0)是内核模式,Ring 3是用户模式。Windows只用这两个级别的原因是有些硬件架构只实现了这两个级别的执行权限(比如Compaq Alpha和Sillion Graphics MIPS)。
虽然每个Windows进程都有自己的私有内存空间,但内核模式的系统代码和驱动代码共享一个单独的虚拟地址空间,虚拟内存中的每一页都标记了在什么访问模式下才可以读写。系统空间中的页只能被内核模式访问,用户模式访问用户模式的地址空间。只读内存页(比如存储静态数据的页)在任何模式下都不能写。另外,处理器支持非可执行内存区域保护,来防止在数据区域执行恶意或无意的代码。
32位Windows不提供内核模式下对私有可读写内存区域的保护,换句话说,一旦在内核模式下,操作系统代码和驱动代码可以完全访问系统的所有内存并绕过Windows安全机制来访问某些资源。因为大量Windows操作系统代码运行在内核模式,所以一定要万分注意不要违反系统安全去执行某行代码而引起系统不稳定。加载第三方驱动代码的时候也要格外小心,因为一旦进入内核模式,所有系统级的代码都可以访问。所以Windows引入了驱动签名机制,如果用户安装没签名的驱动时,系统会报警告。
在64位Windows上,内核模式的代码签名条款规定任何64位的驱动代码必须要用官方给的密钥来签名(KMCS),而且用户不能强制安装未签名的驱动代码,即使是管理员权限也不行。但是有一个例外,那就是在启动时按F8进入boot选项,可以禁止强制驱动签名,如果这样设置了的话,桌面的壁纸上就会有水印,而且数字版权管理(DRM)功能会被禁止。普通应用程序调用系统服务的时候可以从用户模式切换到内核模式,比如读文件的功能最终还是需要调用操作系统的Readfile()函数,这就会切换到内核模式。这种转换用一个特殊的CPU指令进入到内核模式去执行Ntoskrnl.exe或Win32k.sys中的函数。在返回到用户模式的线程之前,会回到用户模式。操作系统就是用这种方式来保护系统数据的。
注意:从用户模式切换到内核模式不会影响线程调度。
所以,用户线程的时间一部分花在用户模式下,一部分花在内核模式下是很常见的。事实上,因为大量的图形和系统代码运行在内核模式,图形计算集中的程序会更多地执行在内核模式,可以微软的画图板程序来测试在哪个模式下执行的多。而D2D技术则大量的运行在用户模式下,只会发送少量的原始表面数据给内核来减少在两个模式下的转换。
有一个叫做csrss.exe的进程是专门负责原始输入的,比如鼠标,键盘,如果晃动一下鼠标会影起内核模式下csrss进程的活动。
有一个叫做idle的进程有时会占100%的CPU,其实它是一个假的进程,当CPU空闲的时候执行。
终端服务和多会话
终端服务指的是Windows提供了在单个系统上与多个用户交互的功能。远程用户可以使用终端服务与机器建立一个会话(Session),登陆,并且在服务器上运行程序。服务器将图形界面传输给远程用户(还可以传声音和剪贴板),远程用户传输用户的输入给服务器。
第一个建立的会话会被认为是服务会话,或者叫做Session0,包括系统服务宿主进程。Session0是服务器本机的控制台,其他Session可以通过远程桌面连接(mstsc.exe)或快速用户切换来登陆。
Windows客户端版本允许一个远程用户连接,如果有人登陆,其他人就不能操作了,当有其他人再登陆的时候,当前用户又被锁住。
Windows带MediaCenter的版本允许4个扩展会话,Windows服务器支持同时连接两个远程用户。
所有的windows客户端版本都支持在本地通过快速用户切换功能建立多个会话(开始->切换用户),切换后会话仍然活动状态。
对象和句柄
在Windows下,一个内核对象指的是静态定义的“对象类型”的运行时实例。对象类型包括:
- 系统定义的数据类型
- 操作数据类型的实例的函数,
- 一些对象属性。
- 给系统资源提供一个人类认识的名字。
- 在进程中共享资源和数据。
- 禁止对资源未授权的访问。
- 引用计数。让系统知道什么时候该回收对象。
安全
Windows最初的设计目标是为了满足各种政府部门的规定和行业安全级别,比如CCITSE。
Windows的核安全功能包括:
- 对于系统对象(如文件,目录,进程,线程等)的自主或强制的保护。
- 安全审核。
- 用户登陆时的身份验证。
- 防止用户访问其他用户已经释放的资源但还未初始化的资源(如未分配的内存或空闲的磁盘空间)。
Windows对于对象有三种形式的访问控制:
- 任意访问的控制机制 -- 对象的拥有者可以分配权限给他人或拒绝他人访问这个对象。当用户登陆系统后,会得到一个安全上下文,访问对象时,会查看对象的安全控制列表中有没有权限。
- 特权访问控制 -- 确保当找不着对象的拥有者时,仍然可以访问受保护的对象。比如有些文件的创建者已经离职,管理员需要一种方式去获得文件的访问权限。这时,管理员可以取得文件的拥有权。当重装系统时以前文件的扔有者丢失也会遇到这种情况。
- 强制控制 -- 当同一个用户访问时可以给需要保护的对象加更多的安全控制,比如在IE上对每个用户实行隔离保护模式,以及保护由提权得到管理员权限的用户建立的对象不受非提权的管理员访问。
注册表
注册表是Windows的系统数据库,包括启动信息和系统配置,软件配置,安全数据库,每个用户的配置。
另外,注册表也是查看内存中可变数据的窗口,比如当前的硬件状态(比如设备驱动加载,资源使用等),以及性能计数器。
虽然很多Windows用户和管理员从不直接看注册表,但它确实是查看系统信息的一个很有用的工具。
Unicode
Windows与其他操作系统不同之外在于Windows上大多数字符串都是以16位宽的Unicode字符来处理的。Unicode是国际标准的字符集。
因为很多程序以8位ANSI字符集来处理,很多Windows函数支持两个入口,一个是Unicode版本(16位宽字符)的一个是ANSI版本(8位窄字符)的。如果你调用窄字符的版本,会有一点效率影响,因为系统在处理前会转换成Unicode,然后输出时再转换成ANSI。但是Windows不会在文件中将ANSI转换成Unicode。怎么存到文件中由程序自己控制。
不用考虑语言,因为所有版本的Windows包含同样的函数,而不是每一个国家的语言单独用一个版本。
内核调试
内核调试的意思是查看内核数据结构,单步跟踪函数的执行情况。是研究Windows内核的重要方式。
符号文件和内核调试
srv*c:\symbols*http://msdl.microsoft.com/download/symbols
更多帮助在 http://msdn.microsoft.com/en-us/windows/hardware/gg462988.aspx
Windows调试工具
WindowsSDK里最新的调试工具,这些工具用在用户模式和内核模式。
注意:这上结调试工具经常更新,而且与Windows的版本相关,所以最好下载最新版本。用户模式调试
调试工具可以附加一个用户模式的进程来查看或修改其内存。附加的时候有两个选项:
- 侵入式(Invasive ),调试时Windows会在调试器和程序间建立一个连接,可以修改程序的内存,设置断点,停止调试而不杀死进程,直到退出附加。
- 非侵入(Noninvasive ),不附加进程,不能设置断点,也可以通过打开用户模式进程的dump文件。
内核模式调试
有两种工具用来调试内核:
- kd.exe,命令行工具。
- Windbg.exe,GUI工具。
- 打开崩溃dump文件。
- 连接到系统。需要使用两台电脑。可以用IEEE1394或USB来连接到目标电脑,目标系统必须可以boot到debug模式(可以用F8或bcdedit或msconfig),也可以用命名管道连接(比如hyper-V,Virtual PC,VMWare)。
- 也可以连接到系统,这种方式叫做本地内核调试,可以用WinDbg,文件->Kernel Debug->local。但是系统必须是boot到bebug模式下的。