简体   繁体   中英

Question about memory page protection

Here's another question I met when reading < Windows via C/C++ 5th Edition >. First, let's see some quotation.

LPVOID WINAPI VirtualAlloc(
  __in_opt  LPVOID lpAddress,
  __in      SIZE_T dwSize,
  __in      DWORD fdwAllocationType,
  __in      DWORD fdwProtect
);

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.

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, 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.

(When commiting storage)...you usually pass the same page protection attribute that was used when VirtualAlloc was called to reserve the region, although you can specify a different protection attribute.

The above quotation totally puzzled me.

  • If the protection attribute associated with the region has no effect on the committed storage, why do we need it?

  • Since it is recommended to use the same protection attribute for both reserving and committing, why does Windows still offer us the option to use different attribute? Isn't it mis-leading and kind of a paradox?

  • Where exactly is the protection attribute stored for reserved region and committed storage , repectively?

Many thanks for your insights.

It's important to read it in context.

The protection attribute associated with the region has no effect on the committed storage mapped to the region.

was referring to reserving , not committing regions.

A reserved page has no backing store, so it's protection is always conceptually PAGE_NOACCESS, regardless of what you pass to VirtualAlloc . Ie if a thread attempts to read/write to an address in a reserved region, an access violation is raised.

From linked article:

Reserved addresses are always PAGE_NOACCESS, a default enforced by the system no matter what value is passed to the function. Committed pages can be either read-only, read-write, or no-access.

Re:

  • Where exactly is the protection attribute stored for reserved region and committed storage, repectively?

The protection attributes for virtual address regions are stored in the VAD tree, per process. (VAD == Virtual Address Descriptor, see Windows Internals , or linked article)

Since it is recommended to use the same protection attribute for both reserving and committing, why does Windows still offer us the option to use different attribute? Isn't it mis-leading and kind of a paradox?

Because the function always accepts a protection parameter, but its behaviour depends on fdwAllocationType . Protection only makes sense for committed storage.

The reason Richter suggests using the same protection setting is presumably because fewer changes in the protection flags in a region mean fewer "blocks" (see your book for definition), and hence a smaller AVL tree for the VADs. Ie if all pages in a region are committed with the same flags, there'll only be 1 block. Otherwise there could be as many blocks as pages in the region. And you need a VAD for each block (not page).

Block == set of consecutive pages with identical protection/state.

If the protection attribute associated with the region has no effect on the committed storage, why do we need it?

As above.

Well... One reason could be so you could use guard pages so you can commit memory as you use it.

Think of the thread stack in Windows; the page immediately below the stack is set as a guard page, typically with read and write ability. Once the guard page is touched, an exception handler runs and commits the guard page and makes the next page a guard.

See here for a better description. Also, that link is part of a series on how windows handles low level resources and is pretty good reading.

Another reason for allowing you to respecify the protection attributes could be for copy on write techniques. Pages are set to read only until they're changed, which can raise an exception you can handle etc etc etc.

On the 386 family of Intel chips, the commit, read/write/reserve flags are stored in the page tables. Take a look at a 386 chip reference for more details. Edit: I poked around for a bit and could not find where MS stores the PAGE_GUARD bit. Now I'm curious where I saw it. :) Too bad I threw out about 500 pounds of old reference material last spring...

Hope this helps :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM