Reserving a Region in an Address Space

[Previous] [Next]

You reserve a region in your process's address space by calling VirtualAlloc:

 PVOID VirtualAlloc( PVOID pvAddress, SIZE_T dwSize, DWORD fdwAllocationType, DWORD fdwProtect); 

The first parameter, pvAddress, contains a memory address specifying where you would like the system to reserve the address space. Most of the time, you'll pass NULL for this parameter. This tells VirtualAlloc that the system, which keeps a record of free address ranges, should reserve the region wherever it sees fit. The system can reserve a region from anywhere in your process's address space—there are no guarantees that the system will allocate regions from the bottom of your address space up or vice versa. However, you can have some say over this allocation by using the MEM_TOP_DOWN flag, discussed later in this chapter.

For most programmers, the ability to choose a specific memory address where a region will be reserved is an unusual concept. When you allocated memory in the past, the operating system simply found a block of memory large enough to satisfy the request, allocated the block, and returned its address. But because each process has its own address space, you can specify the base memory address where you would like the operating system to reserve the region.

For example, say that you want to allocate a region starting 50 MBs into your process's address space. In this case, you will pass 52,428,800 (50 × 1024 × 1024) as the pvAddress parameter. If this memory address has a free region large enough to satisfy your request, the system will reserve the desired region and return. If a free region does not exist at the specified address, or if the free region is not large enough, the system cannot satisfy your request and VirtualAlloc returns NULL. Note that any address you pass for the pvAddress parameter must always reside in your process's user-mode partition or the call to VirtualAlloc will fail, causing it to return NULL.

As I mentioned in Chapter 13, regions are always reserved on an allocation granularity boundary (64 KB for all implementations of Windows to date). So if you attempt to reserve a region starting at address 19,668,992 (300 × 65,536 + 8192) in your process's address space, the system rounds that address down to a multiple of 64 KB and will reserve the region starting at address 19,660,800 (300 × 65,536).

If VirtualAlloc can satisfy your request, it returns a value indicating the base address of the reserved region. If you passed a specific address as VirtualAlloc's pvAddress parameter, this return value is the same value that you passed to VirtualAlloc rounded down (if necessary) to a 64-KB boundary.

VirtualAlloc's second parameter, dwSize, specifies the size of the region you want to reserve in bytes. Because the system must always reserve regions in multiples of the CPU's page size, an attempt to reserve a region that spans 62 KB will result in reserving a region that spans 64 KB on machines that use 4-KB, 8-KB, or 16-KB pages.

VirtualAlloc's third parameter, fdwAllocationType, tells the system whether you want to reserve a region or commit physical storage. (This distinction is necessary because VirtualAlloc is also used to commit physical storage.) To reserve a region of address space, you must pass the MEM_RESERVE identifier as the value for the fdwAllocationType parameter.

If you're going to reserve a region that you don't expect to release for a long time, you might want to reserve the region at the highest memory address possible. That way, the region does not get reserved from the middle of your process's address space, where it can potentially cause fragmentation. If you want the system to reserve a region at the highest possible memory address, you must pass NULL for the pvAddress parameter and for the fdwAllocationType parameter, you must also bitwise OR the MEM_TOP_DOWN flag with the MEM_RESERVE flag.

NOTE
Under Windows 98, the MEM_TOP_DOWN flag is ignored.

The last parameter, fdwProtect, indicates the protection attribute that should be assigned to the region. The protection attribute associated with the region has no effect on the committed storage mapped to the region. Regardless of the protection attribute assigned to a region, if no physical storage is committed, any attempt to access a memory address in the range will cause the thread to raise an access violation.

When reserving a region, assign the protection attribute that will be used most often with the storage committed to the region. For example, if you intend to commit physical storage with a protection attribute of PAGE_READWRITE (by far the most common protection attribute), you should reserve the region with PAGE_READWRITE. The system's internal record keeping behaves more efficiently when the region's protection attribute matches the committed storage's protection attribute.

You can use any of the following protection attributes: PAGE_NOACCESS, PAGE_READWRITE, PAGE_READONLY, PAGE_EXECUTE, PAGE_EXECUTE_READ, or PAGE_EXECUTE_READWRITE. However, you cannot specify either the PAGE_WRITECOPY attribute or the PAGE_EXECUTE_WRITECOPY attribute. If you do so, VirtualAlloc will not reserve the region and will return NULL. Also, you cannot use the protection attribute flags PAGE_GUARD, PAGE_NOCACHE, or PAGE_WRITECOMBINE when reserving regions—they can be used only with committed storage.

NOTE
Windows 98 supports only the PAGE_NOACCESS, PAGE_READONLY, and PAGE_READWRITE protection attributes. Attempting to reserve a region using PAGE_EXECUTE or PAGE_EXECUTE_READ results in a region with PAGE_READONLY protection. Likewise, reserving a region using PAGE_EXECUTE_READWRITE results in a region with PAGE_READWRITE protection.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net