关于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.我在看驱动的时候看到下面代码
留着 下面的函数用!
VirtualCopy(pVMem, (LPVOID)pContext->dwIOBase,
pContext->dwIOLen, PAGE_READWRITE | PAGE_NOCACHE);
主要用在首先预留内存,后面再进行使用的情况,如下:
一个比较好的分配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的可用内存,分配将会成功。
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.
引用: 引用 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函数。
我这样理解对不对?
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
很多驱动里面 尤其是在5.0之前 ! 直接用的是
0xB1200000
定义一个该设备控制器相关的结构体,然后将0xB1200000指向这个结构体就可以访问设备寄存器,而不用
VirtualAlloc :
和
VirtualCopy:
引用: 引用 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函数。
我这样理解对不对?
必须得,呵呵,就是这么回事