以下内容全部来自《Windows驱动开发技术详解》,作者张帆、史彩成等,属摘抄型笔记。
///
1.在驱动程序编写中,分配和管理内存不能使用WIN32 API函数,取而代之的是DDK提供的高效的内核函数。
2.32位的CPU有32条地址总线,能够寻址4GB(2^32)个字节,也即4GB内存。
3.CPU中有一个非常重要的寄存器CR0,它是32位的寄存器,其中PG位标识系统是否分页。PG为1,标识Windows允许分页;PG为0,标识Windwos不允许分页。DDK中有PAGE_SIZE记录分页大小,一般为4KB,4GB虚拟内存会被分割为1M个分页单元。
4.虚拟内存中,有一部分单元会被映射成磁盘上的文件,标记为Dirty,读取该段虚拟内存时,系统会发出一个异常,此时会触发异常处理函数,异常处理函数会将这个页的磁盘文件读入内存,并将标记设置为NonDirty。对于不经常读写的内存,交换为Swap文件,设置为Dirty,保存在磁盘上。
5.无论用户是否有4GB物理内存,操作系统总有4GB内存可以分配,对于不常用的内存页,可以交换出去,等需要用的时候再交换回进行读取。
不同进程间的虚拟内存互不干扰,让操作系统可以同事运行不同的进程。
6.虚拟地址在0x00000000-0x7FFFFFFF,也即低2GB的虚拟地址,称为用户模式地址,而0x80000000-0xFFFFFFFF范围,也即高2GB的虚拟内存,称为内核模式地址。用户态的程序可以访问用户模式地址,而内核模式的程序可以访问整个4GB的虚拟内存。
7.驱动程序可以看作一个特殊的DLL被应用程序加载到虚拟内存中,只不过加载地址是内核模式地址。
8.驱动程序的不同例程运行在不同的进程中,DriverEntry和AddDevice都是运行在系统(System)进程中的。
VOID DisplayItsProcessName()
{
PEPROCESS pEProcess = PsGetCurrentProcess();
PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
KdPrint(("%s\n", ProcessName));
}
kd> dt _EPROCESS
ntdll!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
+0x080 RundownProtect : _EX_RUNDOWN_REF
+0x084 UniqueProcessId : Ptr32 Void
+0x088 ActiveProcessLinks : _LIST_ENTRY
+0x090 QuotaUsage : [3] Uint4B
+0x09c QuotaPeak : [3] Uint4B
+0x0a8 CommitCharge : Uint4B
+0x0ac PeakVirtualSize : Uint4B
+0x0b0 VirtualSize : Uint4B
+0x0b4 SessionProcessLinks : _LIST_ENTRY
+0x0bc DebugPort : Ptr32 Void
+0x0c0 ExceptionPort : Ptr32 Void
+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE
+0x0c8 Token : _EX_FAST_REF
+0x0cc WorkingSetLock : _FAST_MUTEX
+0x0ec WorkingSetPage : Uint4B
+0x0f0 AddressCreationLock : _FAST_MUTEX
+0x110 HyperSpaceLock : Uint4B
+0x114 ForkInProgress : Ptr32 _ETHREAD
+0x118 HardwareTrigger : Uint4B
+0x11c VadRoot : Ptr32 Void
+0x120 VadHint : Ptr32 Void
+0x124 CloneRoot : Ptr32 Void
+0x128 NumberOfPrivatePages : Uint4B
+0x12c NumberOfLockedPages : Uint4B
+0x130 Win32Process : Ptr32 Void
+0x134 Job : Ptr32 _EJOB
+0x138 SectionObject : Ptr32 Void
+0x13c SectionBaseAddress : Ptr32 Void
+0x140 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK
+0x144 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY
+0x148 Win32WindowStation : Ptr32 Void
+0x14c InheritedFromUniqueProcessId : Ptr32 Void
+0x150 LdtInformation : Ptr32 Void
+0x154 VadFreeHint : Ptr32 Void
+0x158 VdmObjects : Ptr32 Void
+0x15c DeviceMap : Ptr32 Void
+0x160 PhysicalVadList : _LIST_ENTRY
+0x168 PageDirectoryPte : _HARDWARE_PTE_X86
+0x168 Filler : Uint8B
+0x170 Session : Ptr32 Void
+0x174 ImageFileName : [16] UChar
+0x184 JobLinks : _LIST_ENTRY
+0x18c LockedPagesList : Ptr32 Void
+0x190 ThreadListHead : _LIST_ENTRY
+0x198 SecurityPort : Ptr32 Void
+0x19c PaeTop : Ptr32 Void
+0x1a0 ActiveThreads : Uint4B
+0x1a4 GrantedAccess : Uint4B
+0x1a8 DefaultHardErrorProcessing : Uint4B
+0x1ac LastThreadExitStatus : Int4B
+0x1b0 Peb : Ptr32 _PEB
+0x1b4 PrefetchTrace : _EX_FAST_REF
+0x1b8 ReadOperationCount : _LARGE_INTEGER
+0x1c0 WriteOperationCount : _LARGE_INTEGER
+0x1c8 OtherOperationCount : _LARGE_INTEGER
+0x1d0 ReadTransferCount : _LARGE_INTEGER
+0x1d8 WriteTransferCount : _LARGE_INTEGER
+0x1e0 OtherTransferCount : _LARGE_INTEGER
+0x1e8 CommitChargeLimit : Uint4B
+0x1ec CommitChargePeak : Uint4B
+0x1f0 AweInfo : Ptr32 Void
+0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
+0x1f8 Vm : _MMSUPPORT
+0x238 LastFaultCount : Uint4B
+0x23c ModifiedPageCount : Uint4B
+0x240 NumberOfVads : Uint4B
+0x244 JobStatus : Uint4B
+0x248 Flags : Uint4B
+0x248 CreateReported : Pos 0, 1 Bit
+0x248 NoDebugInherit : Pos 1, 1 Bit
+0x248 ProcessExiting : Pos 2, 1 Bit
+0x248 ProcessDelete : Pos 3, 1 Bit
+0x248 Wow64SplitPages : Pos 4, 1 Bit
+0x248 VmDeleted : Pos 5, 1 Bit
+0x248 OutswapEnabled : Pos 6, 1 Bit
+0x248 Outswapped : Pos 7, 1 Bit
+0x248 ForkFailed : Pos 8, 1 Bit
+0x248 HasPhysicalVad : Pos 9, 1 Bit
+0x248 AddressSpaceInitialized : Pos 10, 2 Bits
+0x248 SetTimerResolution : Pos 12, 1 Bit
+0x248 BreakOnTermination : Pos 13, 1 Bit
+0x248 SessionCreationUnderway : Pos 14, 1 Bit
+0x248 WriteWatch : Pos 15, 1 Bit
+0x248 ProcessInSession : Pos 16, 1 Bit
+0x248 OverrideAddressSpace : Pos 17, 1 Bit
+0x248 HasAddressSpace : Pos 18, 1 Bit
+0x248 LaunchPrefetched : Pos 19, 1 Bit
+0x248 InjectInpageErrors : Pos 20, 1 Bit
+0x248 VmTopDown : Pos 21, 1 Bit
+0x248 Unused3 : Pos 22, 1 Bit
+0x248 Unused4 : Pos 23, 1 Bit
+0x248 VdmAllowed : Pos 24, 1 Bit
+0x248 Unused : Pos 25, 5 Bits
+0x248 Unused1 : Pos 30, 1 Bit
+0x248 Unused2 : Pos 31, 1 Bit
+0x24c ExitStatus : Int4B
+0x250 NextPageColor : Uint2B
+0x252 SubSystemMinorVersion : UChar
+0x253 SubSystemMajorVersion : UChar
+0x252 SubSystemVersion : Uint2B
+0x254 PriorityClass : UChar
+0x255 WorkingSetAcquiredUnsafe : UChar
+0x258 Cookie : Uint4B
9.其他IRP例程会运行于应用程序的“上下文”中,至于运行在什么进程中,可以使用以下代码显示。
10.可以被交换到文件中的,这类内存被称为分页内存;有一些虚拟内存页面永远不能交换到文件中,这类内存被称为非分页内存。
11.程序中断请求级别在DISPATCH_LEVEL层及之上时,程序只能使用非分页内存,否则将导致蓝屏死机。
12.PAGED_CODE()是DDK提供的宏,在Check版本,检测函数是否低于DISPATCH_LEVEL的中断请求。
#if DBG
#define PAGED_CODE() \
{ if (KeGetCurrentIrql() > APC_LEVEL) { \
KdPrint(( "EX: Pageable code called at IRQL %d\n", KeGetCurrentIrql() )); \
ASSERT(FALSE); \
} \
}
#else
#define PAGED_CODE() NOP_FUNCTION;
#endif