关于VirtualAlloc 函数的PAGE_NOACCESS问题:

森林898   2009-12-28 16:42 楼主
1. PAGE_NOACCESS参数问题
PAGE_NOACCESS 为任何访问该区域的操作将被拒绝
pVMem = (PUCHAR)VirtualAlloc(0, PAGE_SIZE*3, MEM_RESERVE, PAGE_NOACCESS);
这里如果分配一快虚拟内存不能访问,分配它有什么用。2.我在看驱动的时候看到下面代码

回复评论 (10)

留着 下面的函数用!
VirtualCopy(pVMem, (LPVOID)pContext->dwIOBase,
            pContext->dwIOLen, PAGE_READWRITE | PAGE_NOCACHE);
点赞  2009-12-28 17:17
主要用在首先预留内存,后面再进行使用的情况,如下:
     一个比较好的分配512块特殊内存的方法是这样做:
#define PAGESIZE 1024   // Assume we're on a 1-KB page machine.
// Reserve a region first.
pMemBase = VirtualAlloc (NULL, PAGESIZE * 512, MEM_RESERVE,
                         PAGE_NOACCESS);

for (i = 0; i < 512; i++)
    pMem = VirtualAlloc (pMemBase + (i*PAGESIZE), PAGESIZE,
                            MEM_COMMIT, PAGE_READWRITE);
     代码首先保留了一块区域,页面将在以后被提交。因为区域已经被先保留了,提交页就不受64-KB限制(译者注:只有保留页最小值受64KB限制),等等,如果你系统中有512KB的可用内存,分配将会成功。
点赞  2009-12-28 19:27
MSDN上是这样说的:
If you call VirtualAlloc with dwSize >= 2 MB, flAllocationType set to MEM_RESERVE, and flProtect set to PAGE_NOACCESS, it automatically reserves memory at the shared memory region. This preserves per-process virtual memory.
点赞  2009-12-28 20:43
引用: 引用 2 楼 guopeixin 的回复:
主要用在首先预留内存,后面再进行使用的情况,如下:
? ? 一个比较好的分配512块特殊内存的方法是这样做:
#define PAGESIZE 1024? // Assume we're on a 1-KB page machine.
// Reserve a region first.
pMemBase = VirtualAlloc (NULL, PAGESIZE * 512, MEM_RESERVE,
? ? ? ? ? ? ? ? ? ? ? ? PAGE_NOACCESS);

for (i = 0; i < 512; i++)
? ? pMem = VirtualAlloc (pMemBase + (i*PAGESIZE), PAGESIZE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? MEM_COMMIT, PAGE_READWRITE);
? ? 代码首先保留了一块区域,页面将在以后被提交。因为区域已经被先保留了,提交页就不受64-KB限制(译者注:只有保留页最小值受64KB限制),等等,如果你系统中有512KB的可用内存,分配将会成功。

上边是预留MEM_RESERVE----只是在虚拟内存分配,下边是提交MEM_COMMIT参数指定----与物理内存关联,这样就可以使用了。
如果要和具体的内存地址关联,就需要调用VirtualCopy函数。
我这样理解对不对?
点赞  2009-12-29 08:41
VirtualAlloc :
MSDN:
This function reserves or commits a region of pages in the virtual address space of the calling process.


所以 保留一段在calling process.  中的虚拟空间! 这段空间在MEM_RESERVE, PAGE_NOACCESS和参数下不可以被访问,只有通过VirtualCopy才可以直接使用!

-------------------
VirtualCopy:
MSDN:
This function dynamically maps a virtual address to a physical address by creating a new page-table entry.
其实我发现在很多驱动里面!VirtualCopy:是将VirtualAlloc过后的虚拟地址和与设备寄存器关联的地址进行绑定。
我这里用“设备寄存器关联” 是因为这样的例子:
pVMem = (PBYTE)VirtualAlloc(0, PAGE_SIZE*2, MEM_RESERVE, PAGE_NOACCESS);
if (pVMem) {       
        BOOL fSuccess = VirtualCopy(pVMem, (LPVOID)pContext->dwIOBase,
              pContext->dwIOLen, PAGE_READWRITE | PAGE_NOCACHE);
}
dwIOBase, 是从注册表中读到的!  我这里取的是USB的例子 那么dwIOBase,就是0xB1200000
而0xB1200000就是virtual addresses。 0x91200000映射到Uncache field就是了!
         DCD 0x91200000, 0x52000000,  1  ; USB device register

点赞  2009-12-29 10:59
很多驱动里面 尤其是在5.0之前 ! 直接用的是
0xB1200000
定义一个该设备控制器相关的结构体,然后将0xB1200000指向这个结构体就可以访问设备寄存器,而不用
VirtualAlloc :

VirtualCopy:
点赞  2009-12-29 11:02
学习了..
点赞  2009-12-29 11:04
引用: 引用 4 楼 jiereliyi 的回复:
引用 2 楼 guopeixin 的回复:
主要用在首先预留内存,后面再进行使用的情况,如下:
? ? 一个比较好的分配512块特殊内存的方法是这样做:
#define PAGESIZE 1024? // Assume we're on a 1-KB page machine.
// Reserve a region first.
pMemBase = VirtualAlloc (NULL, PAGESIZE * 512, MEM_RESERVE,
? ? ? ? ? ? ? ? ? ? ? ? PAGE_NOACCESS);

for (i = 0; i < 512; i++)
? ? pMem = VirtualAlloc (pMemBase + (i*PAGESIZE), PAGESIZE,
? ? ? ? ? ? ? ? ? ? ? ? ? ? MEM_COMMIT, PAGE_READWRITE);
? ? 代码首先保留了一块区域,页面将在以后被提交。因为区域已经被先保留了,提交页就不受64-KB限制(译者注:只有保留页最小值受64KB限制),等等,如果你系统中有512KB的可用内存,分配将会成功。


上边是预留MEM_RESERVE----只是在虚拟内存分配,下边是提交MEM_COMMIT参数指定----与物理内存关联,这样就可以使用了。
如果要和具体的内存地址关联,就需要调用VirtualCopy函数。
我这样理解对不对?

必须得,呵呵,就是这么回事
点赞  2009-12-29 18:07
学习了~~~~
点赞  2009-12-29 20:18
谢谢
点赞  2009-12-30 08:21
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复