最近在学文件过滤驱动,盯着DDK文档一点一点看的,有些小体会,记录下来,方便自己,方便他人。
1. 使用 ExAllocatePoolWithTag(...) 分配非分页内存
DDK关于使用ExAllocatePoolWithTag(...)分配内存是这么说的:“当用户申请的内存大小不足或等于一个页面的大小(X86机器上,是4KB)时,ExAllocatePoolWithTag精确地分配用户申请的配额;如果申请的内存超过了一个页面大小,则分配的内存会round to页面大小的整数倍。并且超出用户申请配额的那几K内存对用户来说是不可访问的。例如,申请5KB,系统会分配2个页面内存给申请者,不过多的3KB申请者无法使用。”DDK由此建议,以申请5KB内存为例,申请者最好先申请4KB,再申请1KB,这样就可以省3KB的系统非分页内存。
看完了我觉得挺有意思,这种不复杂的细活,MS干嘛不在实现的时候就这么做,一定要用户自己动手。以我恶毒的心灵揣测,应该很少有人按照DDK上建议的这种方法来做。那MS在DDK里辛辛苦苦举例说明了这么半天岂不是白费了...
看的时候也没觉得按照DDK上的说法能多大的节省空间,不过还是看了下,得到如下这张图:
我正在用的这台机器是1G的内存,除去被显卡什么的剥削的之外,实际差不多900M,可未分页的内存只有22.5M,看来还是有必要省着点用~
附:DDK中关于这一点的介绍的原话:
NonPagedPool for any objects or resources not stored in a device extension or controller extension that the driver might access while running at IRQL > APC_LEVEL For this PoolType(指 “NonPagedPool”) value, ExAllocatePoolWithTag allocates exactly the amount of memory requested if the specified NumberOfBytes is less than or equal to PAGE_SIZE. Otherwise, any remainder bytes on the last-allocated page are wasted: inaccessible to the caller and unusable by other kernel-mode code.
2. 关于内存的种类
刚学驱动不久,所以还是习惯性的把驱动里的一些术语,名词,原理,用应用层的思维方式来理解。比如:
应用层编程时,有两种申请内存的方法:
1.在进程栈中申请(从《windows核心编程》中看到被称为TLS的线程栈,不过我从来没用过~);
2.在进程堆中申请;
驱动编程时,也有两种申请内存的方式:
(1).在核心栈中申请,类似于上面的1.不过栈容量有很大的区别,R3中进程的栈貌似可以自己设置,VC6默认为自己编译、连接的进程设置2M的栈(查资料的时候,看到的,具体没有考证)。而在X86 R0级中,核心栈只有约两个页面的大小,所以DDK中提到,不能使用递归调用。
(2).在核心堆中申请,比如上面提到的ExAllocatePoolWithTag函数就可以。不过核心堆分成两种:分页的、非分页的。
在学习操作系统时,关于分页是这么说的:“将物理内存和硬盘上的一部分空间按页划分是为了实现虚拟内存机制。”所谓分页的内存,就是可以、方便换出到虚拟内存中内存。相反非分页内存则是不需要换出的内存,比如操作系统的内存管理模块本身占用的内存,它要是被换出去了,那谁来为分页的内存服务~
3. 关于 非分页内存 和 IRQL
《Programming Microsoft Windows Driver Moddel》书中提到:“系统在APC级别处理页故障”。这样一来,所有APC或以上级别的都只能使用非分页内存。因为内存管理模块在这些IRQL上没法把需要访问的分页内存换入、换出。

#1
