wdk tips (4): 当你CreateFile时,你都干了些什么

今天我们聊一聊CreateFile,这个名字取的不合适但IO的世界里完全绕不过去的东西,以及与之相关的“namespace”这一概念。

我们知道Create的意思是创造,创建,上帝创造了这个世界,指的可不是上帝打开了某样存在的东西(唯物主义者,我知道你们有意见,给我闭嘴…),但这个倒霉的函数要做的却是打开。我们也知道File是文件,windows里面也没有“一切都是文件”的概念,但这个倒霉的函数要做的却是打开所有能返回handle的内核对象。Anyway,CreateFile函数是唯一一个能打开内核对象的handle,并让user mode app来访问的方法。将范围缩小到驱动,这个函数也是唯一一个能打开驱动的handle以便user mode app访问驱动的方法。CreateFile带的参数中有一个lpFileName指定了内核对象的名字,如果该名字指代的是一个驱动,那么拥有该名字的PDEVICE_OBJECT的IRP_MJ_CREATE例程就会被调用到,返回的handle则是该object的代理(详情请参看本博中跟handle有关的那几篇),在这个handle上调用read,write,DeviceIoControl等操作最后都会落到PDEVICE_OBJECT相应的IRP_MJ_XX上。IoManager在打开handle的过程中扮演了至关重要的角色,没有它的帮忙,user mode和kernel mode的通信将会非常困难,除非你觉得每写一个驱动就增加一个系统调用很简单很有趣。那么IoManager都做了些什么了,一般是以下几步:

  1. 解析lpFileName参数。文件名里的内容对user mode有意义,但对内核不一定有意义。一般情况下这个名字都是一个symbol link,简单点可以把它想成是一个别名,link的target是真正的名字,就好比地海中的魔法师都有真名,只有知道了真名,你才能打败他。举个例子,"C:”这个盘符就是一个symbol link,它的真名是"\Device\HarddiskVolume1”
  2. 如果名字存在,那么找到相应的内核对象。讨论范围缩小到驱动就是一个PDEVICE_OBJECT。
  3. 如果解析完名字后还有字符串剩下,则把这剩下的字符串贴在FileName域里
  4. 生成一个IRP,交给驱动处理。

注意,这里有个安全漏洞:如果FileName域为NULL,那么打开handle的时候会做权限检查。如果不为NULL,则默认不检查,即使你的驱动里放了空空的动作片,你父母想访问就能访问。你肯定不想让这种事发生。所以在创建PDEVICE_OBJECT时记得把FILE_DEVICE_SECURE_OPEN标志位加到Characteristics域中去,这会强制IoManager检查权限,即使FileName不为NULL。

让我们举几个例子,假设你要对"C:\av\rio.avi”做CreateFile,IoManager首先会解析这个字符串,它发现"C:”指的是"\Device\HarddiskVolume1”,并且"\Device\HarddiskVolume1”在namespace中存在,那么它将寻找"\Device\HarddiskVolume1”对应的object,找到后创建IRP,将"\av\rio.avi”贴在FileName域里,并将irp转给相应的object处理。因为FileName里的内容不为空,所以IoManager不会检查权限,你就祈求上帝FILE_DEVICE_SECURE_OPEN标志位已经被设置了吧。但是如果你对"c:”做访问,那么FileName域为NULL,不管标志位有没有设置,权限检查的动作都会做。

关于symbol link和真实姓名的信息全部在一个叫name space的东西里,这东西和文件系统一样,也用树形结构管理,根部是名字"\”。用牛逼工具WinObj可以清楚的看到整个name space的信息,如截图所示

wdk tips (4): 当你CreateFile时,你都干了些什么_第1张图片

个人认为这才是真正的文件系统,与*NIX中的文件系统相对应,而C盘D盘等所谓的盘符其实是文件系统中的某个目录,被Explorer这个Window Manager放在首页了而已。盘符是*NIX程序员最喜欢的吐槽点,没有之一,但其实nt内核里的目录(某种程度上说)也是单根的,所谓盘符就是个别名,mount等操作其实也很容易实现。linux中内核可以注册虚拟目录,比如/proc,/dev这种,nt里也可以在name space里添加自己想要的东西,将这个名字与自己的驱动绑定,能做的事情跟虚拟目录实在很像。说到这里我又想感慨一下,操作系统这么手艺,发展到今天大家在某些关键点上的选择那是出奇的一致。反而是那些user mode的东西则是各有个的特色,大家会争的面红耳赤。那些个满嘴"UNIX”哲学的哲学家,我可以肯定他没接触过内核。

你可能感兴趣的:(create)