YJX_Driver_033_驱动中的内存管理

1、

驱动中的内存管理
  A、 物理内存
  B、 虚拟内存
  C、 Ring0地址和Ring3地址
  D、 驱动程序和进程的关系
  E、 分页和非分页内存
  F、 分配内核内存

【120】了解两个概念:物理内存  虚拟内存

【140】以下概念针对 32位Windows操作系统(32位及以上的CPU)(32位 / 64位 CPU)

【210】64位下的这些概念 略有区别

【240】

A、物理内存:(Physical Memory Address)

  目前主流的操作系统还是32位的XP,而32位的系统提供的寻址能力是2^32个字节,用户最多可以使用4GB的真实物理内存。0-0xFFFFFFFF 2G+0.5G+0.1 (2.75-3.25) 2G

  【310】64位 理论寻址能力 2^64个字节

  【420】"物理内存"是一个总称。我们配备了 2G的内存,0.5G的显存,还有硬盘上的缓存0.1G,这些都是 物理内存,都会被映射到相应的地址。【565】也就是说 物理内存 是我们配备的 内存,显存,其他设备配置的一些内存  统统加起来,才是我们真是的物理内存。一般是这样的。

【645】

B、虚拟内存:(Virtual Memory Address)

  虽然可以寻址4GB的内存,但在PC里往往没有如此多的真实物理内存,现在的主流电脑一般是2G左右内存,操作系统和硬件提供了虚拟内存的概念。

  虚拟内存的作用:
    1、不管PC是否有足够的物理内存,操作系统总会有4GB的虚拟内存。这就允许使用者申请更多的内存,当物理内存不够的时候,可以通过将不常用的虚拟内存页交换成页面文件,等需要的时候再去读取。
    2、不同进程的虚拟内存互不干扰,为了让系统可以同时运行不同的进程,Windows操作系统让每个进程看到的虚拟内存都不同,这个方法就使不同的进程会有不同的物理内存到虚拟内存的映射。例如 进程A和进程B的内存地址 0x400123会完全不同。修改进程A的这个地址,不会影响到进程B,因为A进程的这个地址可能映射的是一段物理内存地址,而B进程是映射的另一段物理内存地址.

  【900】虚拟内存 设置的地方

  【1080】ZC: 这里的 虚拟内存的第2个作用,貌似是 分段/分页 的作用吧,并非 虚拟内存的作用 吧?

【1220】

C、Ring0地址和Ring3地址
  用户模式地址:
    在32位Windows操作系统中,把虚拟内存4GB的低2GB也就是虚拟地址0-0x7FFFFFFF这个范围的地址 划给 用户模式。

  内核模式地址:
    而0x80000000-0xFFFFFFFF之间虚拟内存划给 内核模式,也就是高2GB.Windows系统还规定在用户态(Ring3层)的程序,只能访问用户模式地址,而在内核态(Ring0层)的程序,可以访问整个4GB虚拟内存,即用户模式和内核模式的地址。

【1500】

D 、Windows驱动程序和进程的关系
  驱动可以看成是一个特殊的DLL函数库,只不过加载的地址是内核模式地址,只是这个DLL可以访问整个4GB的虚拟内存。

  再来看看驱动和进程的关系:
    Window驱动程序里的不同例程运行在不同的进程中。DriverEntry例程是运行在系统(System)进程中,而其它的例程如IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_IRP_MJ_CREATE 及IRP_MJ_DEVICE_CONTROL之类的例程则运行于某个进程的环境中,所能访问的虚拟是这个进程的虚拟地址.

  【1520】驱动,∵它是不能独立运行的,一般它要通过用户层 exe的程序来载入它

    ZC: 这个说的片面了啊

  【1700】DriverEntry例程 可能很多人认为是运行在 我们的载入驱动的exe进程中,其实不是这样的,它是运行在系统(System)进程中

  【1865】ZC: "某个进程" 指 哪个进程?

  【1890】举个例子。比如 我们启动了 test_exe.exe,用它来载入了驱动,那么的话,并且用它来发送相应的IRP信息 进入我们的驱动,那么相应的驱动代码就是运行在 这个进程里面

    ZC: IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_CREATE等 应该是运行于 发送它们的进程中。并不一定是载入驱动的进程。

  【1980】那么 怎么来区分它运行于某一个进程环境里呢(ZC: 应该是说“怎么来区分它运行于哪一个进程环境里呢”吧?)

2、

第32课中的代码
// 如果是被保护的PID,则拒绝访问,并将句柄设置为空

          if(PID == MyPID)
          {
            KdPrint(("被保护进程 MyPID=%d \n",(int)MyPID));
            //调试输出 类似C语言的 Printf
            ProcessHandle = NULL; //这个是关键
            rc = STATUS_ACCESS_DENIED; //这个返回值
            //PsLookupProcessByProcessId((ULONG)PID,&EP);
            EP=PsGetCurrentProcess(); //获取当前进程的相关信息
            KdPrint((" ACESS Process Name --:%s-- \n",(PTSTR)((ULONG)EP+0x174))); //pid +0x84
          }

E、分页和非分页内存
  前边介绍了虚拟内存页和物理内存页之间的关系,Windows规定有些虚拟内存页面是可以交换到文件中的,这类内存被称为分页内存。而有些虚拟内存页永远不会交换到文件中,这种内存称为非分页内存。

  在编译驱动时,可以指定某个例程和某个全局变量是载入分页内存还是非分页内存。

在mini_ddk中我们也定义了这样的分页宏

#include "ctl_code.h"
#include <windef.h>
#define INITCODE code_seg("INIT") //此标志的内存在使用一次后 会及时的释放掉 节省不少内存data_seg
#define PAGECODE code_seg("PAGE") /*表示内存不足时,可以被置换到硬盘*/
#define PAGEDATA data_seg("PAGE") //定义变量和数据用的

#pragma INITCODE extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING B) //TYPEDEF LONG NTSTATUS
#pragma PAGECODE
NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)

注:当中断请求级别在DISPATCH_LEVEL及之上时程序只能使用 非分页内存 ,否则会蓝屏死机 加上此宏PAGED_CODE()可判断。

F、分配内核内存
  Windows驱动程序使用的内存资源非常珍贵,分配内存时要尽量节约。和应用程序一样,局部变量是放在栈(Stack)空间中的,但栈空间不会像应用程序那么大,所以驱动程序不适合递归或者局部变量是大型结构体。如果需要大型结构体,一般使用Heap中申请。

  因为在内核中分配内存 所以New Delete这类操作符 或者malloc这类分配内存的方法都不可用了。

用户态

int *pi=(int*)malloc(sizeof(int));
int *pi=(int*)new int;

内核态要用

int *pi=(int*)ExAllocatePool(PagedPool,sizeof(int));

暂时讲到这里 下节课我们详细的测试 各个内存相关的 内核API

  1000 物理地址

  PEPROCESS

            int ep=(int)PsGetCurrentProcess();
              ULONG* pid=(ULONG*)(ep+0x84);//Xp系统下的进程ID偏移
              PTSTR pname=(PTSTR)(ep+0x174);//Xp系统 进程名

0: kd> dt _EPROCESS

nt!_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 //进程PID 不同系统下 这个偏移不同 2000 +0 2003 +0x094
  +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
  +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

时间: 2025-01-15 15:51:03

YJX_Driver_033_驱动中的内存管理的相关文章

Cocos2d-x开发中C++内存管理

由于开始并没有介绍C++语言,C++的内存管理当然也没进行任何的说明,为了掌握Cocos2d-x中的内存管理机制,是有必要先了解一些C++内存管理的知识.C++内存管理非常复杂,如果完全地系统地介绍可能需要一本书的篇幅才能解释清楚.这里只给大家介绍C++内存管理最为基本的用法. 内存分配区域创建对象需要两个步骤:第一步,为对象分配内存,第二步,调用构造函数初始化内存.在第一步中对象分配内存时候,我们可以选择几个不同的分配区域,这几个区域如下:栈区域分配.栈内存分配运算内置于处理器的指令集中,效率

cocos2dx中的内存管理机制及引用计数

1.内存管理的两大策略: 谁申请,谁释放原则(类似于,谁污染了内存,最后由谁来清理内存)--------->适用于过程性函数 引用计数原则(创建时,引用数为1,每引用一次,计数加1,调用结束时,引用计数减1,当引用计数为0时,才会真正释放内存) --------->适用于注册性函数(消息处理,中断等场合) 2.cocos2dx中的内存管理采用引用计数和内存托管的原则 spr->retainCount();//获取对象的引用计数值 spr->retain();//引用计数加1 spr

关于OC中得内存管理问题,alloc,retain,release,copy,dealloc

我们都知道,一个手机,它的内存是有限的,而每一个手机应用都是需要一定空间,当应用所占空间过大时,系统就会发出警告,怎样在有限的空间中,做到更高效实用美观的效果呢? 这时候就牵涉到OC中得内存管理了. 在OC这门语言中,是不存在垃圾回收机制的,但是它采用了另外一种形式或者说方法,实现这一个空间回收的效果,那就是引用计数器. 别看-引用计数器,这个名字很高大上,实际是它就是一个整数. 所以OC中分配4个字节才存储它. 引用计数的值只有两种:0和非0,我们知道,计算机其实是很笨的,结果只有这两种时,它

Unity游戏开发中的内存管理_资料

内存是手游的硬伤——Unity游戏Mono内存管理及泄漏http://wetest.qq.com/lab/view/135.html 深入浅出再谈Unity内存泄漏http://wetest.qq.com/lab/view/150.html 这一次,我优化了37%的内存http://wetest.qq.com/lab/view/147.html Unity项目资源加载与管理http://wetest.qq.com/lab/view/124.html Android应用内存泄露分析.改善经验总结h

C++中的内存管理

在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存泄露.所以我们要学会内存管理,不要内存泄露.在C++中的内存管理机制和OC中的还不太一样,在OC中的ARC机制会给程序员的内存管理省不少事,但在C++中没有ARC所以我们要自己管理好自己开辟的内存.Java中也有自己相应的内存管理机制,比如JDBC里的获取的各种资源在finally里进行close等

cocos2d-x中的内存管理机制

cocos2d-x中的内存管理机制    Object *obj = new Object();        obj->autorelease();//自动释放资源        //    {    //        //在这段中使用obj    //    obj->retain();//保留对象    //    obj->release();//手动释放资源    //    //    }            log("Count %d",obj-&g

Android中的内存管理机制以及正确的使用方式

概述 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面来理解操作系统的内存管理机制. 第一:分配机制.为每一个进程分配一个合理的内存大小,保证每一个进程能够正常的运行,不至于内存不够使用或者每个进程占用太多的内存. 第二:回收机制.在系统内存不足打的时候,需要有一个合理的回收再分配的机制,以保证新的进程可以正常运行.回收的时候就要杀死那些正在占有内存的进程,操

iOS学习第四天杂记--Objective-C中的内存管理

先说明下,原文为青玉伏案写的.我这只是学习而已. OC中的内存管理. OC中使用引用计数和垃圾回收来管理内存,在OC中为每个对象分配一个引用计数器,当对象刚刚被创建时其初始值为1,当有某段代码需要访问一个对象时,会将该对象的引用计数器加1(通过retain来实现):当访问一个对象结束时,会将该对象的引用计数器减1(通过release来实现):当计数器为0时,该对象占用的内存空间会被收回.在NSObject类有一个retainCount方法,调用该方法可获取当前对象的引用计数值. Tips:测试时

IOS阶段学习第20天笔记(OC中的内存管理)

IOS学习(OC语言)知识点整理 一.OC中的内存管理 1)概念:内存管理的对象为所有继承了NSObject的对象,对基本数据(如:int .float.double...)无效      OC中采用引用计数器对内存做管理,他是一个整数数据,表示对象引用的次数,每个对象分配4字节      的内存空间存放引用计数器.当一个对象的引用计数器为0时 它将被自动释放,反过来说 当使用alloc.      new .copy(mutableCopy)创建新对象时,引用计数器默认为1 2)黄金法则 当使