驱动开发学习笔记(3-7)–Four-F的驱动开发教程-系统内存堆

在这里下载本文的源代码

6. 系统内存堆

本篇翻译:songsong <http://www.songsong.org>
源码位置:KmdKit\examples\basic\MemoryWorks\SystemModules

首先是罗云彬的废话:感谢刘松一起参与这个翻译项目,这样本教程的中文翻译才能这么快和大家见面,刘松是温哥华的帅哥作家,著有《GRE Yellow Bible》(《GRE词汇黄宝书》),文风幽默,看他的翻译,使大家看枯燥的驱动教程如同看泡妞教程,于轻松间掌握繁琐的东西。原本这也是本人梦想中的写作风格,可惜本人多年努力,除了外貌长得还是一如既往的幽默外,文字中还是幽默不起来,没办法哟~~~,好了,废话少说,下面请刘松出场。
(稀稀落落的掌声)……
……
我是温哥华的松松,被罗大哥抓来翻译文章,几个MM还等着我去酒吧,只好不去了……
如果各位帅哥美女已经看完了前面的基础知识,那就跟小弟来看看”一些”必要的底层技术。
为什么”一些”要加引号(一女同学提问)?那是因为驱动程序可以做许许多多的事情啊!
如果你不懂MM,你就别混了!(一男同学问:驱动程序和泡妞还有关系?)哦,我这里的MM不是指”美眉”,是指”内存管理(Memory Management)”。
好的,我们现在就开始学习MM……
内存管理器给用户进程提供了大量的用于MM的API。这些API可以分为三类:虚拟内存函数、内存映射文件函数和堆函数。内核的成员(包括驱动程序)有很多高级的工具。例如:驱动程序能够在物理地址空间里分配一个连续的内存。这类函数呢,前缀是”Mm”。另外呢,还有一种以”Ex”为前缀的函数,用于从系统内存池里(分页和不分页的)分配和释放内存,还可以操作后备列表(lookaside lists)。
后备列表是啥东东?我们下一节会讲,它可以提供更快的内存分配,却要使用预定义的固定的块大小。

Continue Reading

驱动开发学习笔记(3-5)–Four-F的驱动开发教程-I/O子系统

在这里下载本文的源代码

4. I/O子系统

※ 和本节内容相关的源代码见KmdKit\examples\simple\VirtToPhys

4.1 I/O管理器

在用户模式下,我们可以通过访问某个地址来直接调用dll中的函数,与此不同的是,从系统的稳定性考虑,在内核模式下这样做的话是很危险的。所以,系统提供了和内核模式通讯的媒介–I/O管理器,它是I/O子系统的部件之一。I/O管理器将应用程序、系统部件和设备连接起来,并定义了一个架构来支持设备驱动程序。
图4.1是I/O管理器如何在用户模式程序和驱动程序之间进行沟通的简单图解。

图4.1 I/O子系统的简单架构

从上图可以看到,所有用户模式程序到设备(包括设备驱动程序)的调用都必须通过I/O管理器来完成。
一般来说,用户模式的操作都被转换成了对具体硬件设备的I/O操作,仅对于某些设备,设备由驱动程序来创建和控制,这些设备就是虚拟设备。当然,创建这些设备并不意味着你创造了什么硬件(不然我每天创建n个显卡再卖掉,然后换BMW,呵呵~~~~),而仅仅是在内存中创建了一个新的对象而已。每个对象和一个物理设备或者逻辑设备对应,用于描述它们的特征。
创建设备后,驱动程序告诉I/O管理器:”这里有个我控制的设备,如果你收到了操作这个设备的I/O请求的话,直接发给我好了,剩下的由我来搞定!”。驱动程序知道如何对自己管理的设备进行I/O操作,I/O管理器唯一的职责在于创建I/O请求并把它发送给适当的设备驱动程序。用户模式的代码不知道(也不必知道)其中的细节,也不用知道究竟是哪个驱动程序在管理哪个设备。

Continue Reading

驱动开发学习笔记(3-4)–Four-F的驱动开发教程-最简单的设备驱动程序

在这里下载本文的源代码

3. 最简单的设备驱动程序

※ 和本章内容相关的源代码见:
KmdKit\examples\simple\Beeper
KmdKit\examples\simple\DateTime

3.1 如何编译和链接内核模式驱动程序

我总是把驱动程序的汇编源代码放到批处理文件中,这样的文件从内容上看是.asm和.bat文件的混合体,但是扩展名是.bat(注:读者在实际使用的时候是不是这样做完全可以根据个人喜好而定)

;@echo off
;goto make

.386                      ; driver's code start
  ;::::::::::::::::::::::::::::::::
  ; the rest of the driver's code ;
  ;::::::::::::::::::::::::::::::::
end DriverEntry            ; driver's code end

:make
set drv=drvname
\masm32\bin\ml /nologo /c /coff %drv%.bat
\masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
del %drv%.obj
echo.
pause

如果你运行这个”自编译”的批处理文件的话,系统会做以下的事情:
对于汇编编译器来说,前面两行的命令是被注释掉的,所以会被忽略;但是对于命令解释器来说,这两行会被执行,因为命令解释器会忽略前面的分号。这样一来,执行会跳到最后面的:make标号处,接下来下面的编译和链接命令就会被执行,跳转语句和:make标号中间的汇编源代码会被忽略。另外,对于汇编编译器来说,所有end标号后面的内容都会被忽略,所以后面的:make及其后的内容会被编译器忽略。
这种方式用起来很方便,因为源代码和如何编译、链接程序的信息都被放在一起了,如果需要的话,读者也可以自己另外加些命令上去,在我编写的所有的驱动代码中,我都使用了这种方法。
下面我来解释一下:make后面的一些命令的含义。

Continue Reading

驱动开发学习笔记(3-3)–Four-F的驱动开发教程-服务

在这里下载本文的源代码

2. 服务

※ 和本节对应的例子代码见KmdKit\examples\simple\Beeper

读者也许有点疑惑:用户模式的服务关内核模式的驱动程序什么事呀?事实上,两者的确风马牛不相及,但是如果我们要和设备驱动程序通讯的话,我们必须首先安装它,启动它,而和设备驱动程序通讯的界面刚好和服务通讯的界面是类似的。

2.1 Windows服务

Windows NT使用某种机制来启动进程,并让它们不和某个具体的交互式的用户界面相关联,这些进程就被称为服务(service),服务的一个很好的例子就是Web服务器,这些Web服务都没有用户界面,服务是唯一以这种方式运行的应用程序(注:指没有用户界面,当然,严格地说病毒、木马以及所有不想见光的程序也是这样的~~),服务可以在系统启动的时候自动启动,也可以被手工启动,从这一点来看,设备驱动程序和服务是类似的。
Windows NT还支持驱动程序服务,只要使用的时候遵循设备驱动程序协议就可以了,这和用户模式的服务类似,所以,”服务”一词既可以指用户模式的服务进程或者内核模式的设备驱动程序,微软不知何故没有明确地区分两者的概念,所以下面的叙述可能看起来有点让人疑惑。可能有的地方我会说到”driver”一词,但在其他的文章中可能说到”service”一词,但既然这篇教程讲的是如何编写内核设备驱动程序,那么我们就约定无论说到”service”还是”driver”,我们的意思都是指”驱动程序”,当的确需要提及”服务”的时候,我会明确地指出来的。
另外,请读者时刻记得,文档中关于服务管理的函数其实是叙述得相当含糊的,因为这些函数既能用于驱动程序也能用于服务,在下面的文章中,我们只强调它们在驱动方面的用途和忽略服务方面的用途。
Windows NT中有三个组件和服务管理相关:
◎ 服务控制管理器(Service Control Manager/SCM)–用于启动服务以及和它通讯
◎ 服务控制程序(Service Control Program/SCP)–用于和SCM进行通讯,告诉它何时启动或者停止服务

Continue Reading

驱动开发学习笔记(3-2)–Four-F的驱动开发教程-内核模式驱动程序基础

1.Kernel Mode驱动程序基础

本教程讲述了如何在Windows NT为基础的操作系统上用Win32汇编开发KMD,包括NT4.0、2000、XP和2003等操作系统。开发Windows 95/98/ME使用的VxD驱动程序方面的知识并不在本教程讲述的范围内,另外,毫无疑问本教程并不那么完美,可能还包含了诸多未发现的错误,如果您发现了问题,请告知作者,毕竟作者的母语并不是英语,把它翻译成英文已经够难为我了(注:原作者是俄国人也),也感谢masquer和Volodya的校对工作。

1.1 KMD结构概述

1.1.1 主要组成部分

根据地址空间、代码权限和职责的不同,Windows NT内部划分为两个截然不同的部分。
地址空间的享用方式也非常容易理解,整个32位系统的4GB内容被划分为两个相等的部分,用户模式(user-mode)的进程使用的地址空间被映射到低位的2GB上(地址范围00000000 – 7FFFFFFFh),而高位的2GB(地址范围80000000h – 0FFFFFFFFh)则供操作系统的组成部分来使用,如设备驱动程序、系统内存池、系统使用的数据结构等,在这部分中,内存共享的权限和职责等方面就要复杂一点了。

下面就是用户模式进程的一些简单分类:
◎ 系统支持进程–如Logon进程(位于\%SystemRoot%\System32\Winlogon.exe)
◎ 服务进程–如Spooler进程(位于\%SystemRoot%\System32\spoolsv.exe)
◎ 用户应用程序–任何Win32、Windows 3.1、DOS、POSIX或者OS/2程序
◎ 子系统–Windows内置3个子系统:Win32(位于\%SystemRoot%\System32\Csrss.exe)、POSIX子系统(位于\%SystemRoot%\System32\Psxss.exe)和OS/2子系统(位于\%SystemRoot%\System32\Os2ss.exe),在Windows XP以及后续的操作系统中,POSIX和OS/2子系统已经被去掉了。

Continue Reading

驱动开发学习笔记(3-1)–Four-F的驱动开发教程-前言

0.前言

0.1 关于KmdTut

KmdTut是一份以Win32汇编语言来开发Kernel mode驱动程序的教程,读者可以从http://www.freewebs.com/four-f/下载最新的英文版本,为了使用本教程,你还需要下载Kernel mode驱动程序开发包KmdKit,更多信息请参考http://www.wasm.ru/(很不幸,是俄文的,倒ing~~~)

0.2 关于KmdKit

KmdKit的全称是Kernel Mode Driver development Kit for assembly language programmers,即内核模式驱动程序汇编开发包,KmdKit中包括了用宏汇编编译器开发驱动程序需要用到的所有东西。
你可以从http://www.wasm.ru/或者http://www.freewebs.com/four-f/下载到最新版本的KmdKit。

0.3 关于KmdTut中文版

本中文版由罗云彬和刘松翻译,首先发表在http://asm.yeah.net(罗云彬的编程乐园)中,如果需要转载或者引用,请注明出处。
虽然本人(这里的本人当然是指罗云彬了~~)在一些使用习惯上并不十分赞同原作者的使用方式,如将汇编代码和Makefile的内容合并放在BAT文件中、还有过多的使用宏来定义字符串等方式,因为个人认为严格地按照常规的方式来写代码更有利于读者理解,但是在翻译的时候,还是首先尊重原作,读者对于文中的一些和个性化的表达方式可以自行取舍。

◎ 将汇编代码和编译命令一同放在BAT文件中的缺点:
一般在汇编项目往往将编译命令放在Makefile中,并且使用nmake工具来进行编译,在本人著的《Windows环境下32位汇编语言程序设计》一书中,所有的例子都是这样写的。这样写的好处实际上就是nmake工具带来的好处——那就是源文件的从属关系清晰,编译链接的效率很高,符合流行的习惯等。

Continue Reading