阅读:1780回复:3
物理地址如何释放内存?
我现在面临的问题是这样的。
在两个IOCTL中,一个是分配内存,我调用ExAllocatePoolWithTag分配了不分页的一段内存,虚拟地址为V1,然后MmGetPhysicalAddress得到对应的物理地址P1,将P1传给用户。另一个是释放内存,用户将P1传回来,但是这个时候我底层已经不保存V1值啦,如何能够获得虚拟地址V1,同时调用ExFreePool将其释放掉呢? |
|
沙发#
发布于:2013-01-10 10:40
保存到全局变量
|
|
板凳#
发布于:2013-01-11 10:29
了解一下虚拟地址和物理地址的关系,你就知道怎么做了,这里按x86处理器来说明。CPU有个页表,这个页表是操作系统构造的,格式是CPU定义的,页表的基地址在CR3寄存器里。当系统访问V1的时候,处理器把V1(就是地址值)拆成几个部分,用作页表的索引从页表里找出物理地址。也就是说,页表是从虚拟地址到物理地址的映射表,系统提供的MmGetPhysicalAddress就实现了这个查找流程。知道P1,不知道V1,那就有点麻烦,页表不是双向的,是单向的,如果反过来,那你就需要搜索页表了。
另外,ExFreePool不仅仅是释放了物理内存,而且还释放了虚拟内存空间,一个虚拟地址,同一时间,肯定只能对应一个物理地址(可以没有物理地址,但不会有多个物理地址),但一个物理地址,可能有多个虚拟地址对应,所以就算你从页表把P1的虚拟地址搜出来,如果不止一个,那你也无法判断你之前用ExAllocatePoolWithTag申请到的虚拟地址是哪个,所以为了安全起见,虚拟地址必须保存,物理地址可以需要的时候,用MmGetPhysicalAddress获得。 |
|
地板#
发布于:2013-01-15 11:05
我现在面临的情况是,因为是两个IOCTL,所以应用可以多次调用分配内存,然后再最后在同一释放。
我现在的解决办法是在驱动里面维护了一个链表,将分配的内存虚拟地址V1和物理地址P1以及内存大小S1,都记录下来,然后在释放的时候,逐一查找,取得相应虚拟地址进行释放的。可以实现功能,但不知道是不是最佳。 |
|