2
votes

I am learning from here about Windows 32-bit virtual memory page mapping,

(I am targeting modern Windows versions, like Vista, Win 7, Server 2003/2008 32-bit versions.)

http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx

Two confusions,

  1. user space virtual memory space is limited to 2G normally, but physical disk page storage could be much larger than 2G. Since there are more disk pages than virtual memory pages, so in theory more than one disk pages could be mapped to one virtual address page. If user request to access some virtual address, how did memory manager know which disk page should be accessed if more than one disk pages are mapped to one virtual address page?

  2. I do not know why there is restrictions like byte[] array must use continuous virtual memory space. I think in theory even if we only allocate 500M virtual space address, we can re-use such virtual space address to continue to map/unmap disk page file to consume as much as we want, even larger than 2G.

Any ideas?

4
Check out my article and code at codeproject.com/KB/recipes/MemoryMappedGenericArray.aspx. I'm also working on a more general memory mapped library, and I might put back the paging support to support 32bit systems better. - Mikael Svenson
Thanks Mikael. I have read your published document and it looks so great! But I am still confused about issue #1. Here is a scenario which describes my confusion of item #1. Suppose in virtual memory we have a disk page D1 mapped to virtual page V1. Then at some time, memory manager needs to load more disk page and reuse the same virtual page V1 to load disk page D2. When program access virtual page V1, how did memory manager know whether D1 or D2 data should be accessed? Suppose D1 is requested by Thread 1 and D2 is requested by thread 2. - George2
en.wikipedia.org/wiki/Virtual_memory explains this a bit more. If you access something which is swapped out, it must swap it back in. Two apps should never share a virtual space unless you choose too share the pointer, so the underlying mapping table will know what to read in when you access it. You will get a queue of requests, each being servered by the memory manager. A virtual address space can be reused when you release it. Hope this was a bit clearer. Virtual Address Space (max 4gb) -> Cached Pages(reused) -> Physical Disk - Mikael Svenson
On a 32bit system this is true. One single page cannot exceed 4G, but the file can. And you can move a smaller page around the bigger file, which is the whole point of doing paging in the first place. You map smaller chunks on a bigger space, since you don't need all the data at once. But paging is "expensive", so if you can map the whole file in one page, access will be quicker, but the OS will still swap data in/out as it sees fit. Hence 64bit systems are nice since you can address in all practical means unlimited memory. - Mikael Svenson
32bit has 4G of address space which is shared among programs running, the graphics card and virtual memory. So you can never allocate more address space than 4G in total. A 32bit machine with 4gb of RAM can only access 3-3.5G since the gfx card uses the rest. - Mikael Svenson

4 Answers

2
votes

byte (or any other) arrays must use contiguous address space, in this case contiguous virtual address space. This is an area that can make fragmentation becomes an issue, and is actually exacerbated by virtualization of memory. Since the various 'redirections' inherent in a such a system system and the performance considerations in making it efficient lead to actual allocation of physical address space mapped to virtual address space in chunks (commonly pages).

So requesting a 10 byte chunk of virtual address space might actually lead to a whole 4K page being reserved and mapped. Since the physical memory within the page must be contiguous this can lead to a whole 4K of virtual address space being 'blocked off'.
Multiple small allocations can be placed within one page (and good memory managers will try to achieve this) but none the less address space has in effect been reserved over and above what was strictly required. Consider the allocation of a single byte at the start f a page, then 4K - 2 bytes followed by another single byte. This occupies (efficiently) the whole page.
Consider if the middle allocation is no longer necessary, and is thus freed. Until the 'top' and 'tail' values are either freed or moved elsewhere a gap has been created in the virtual address space which can only be filled by something < 4K-1 bytes in size. If sufficient of these sorts of things occur the contiguous regions in virtual address space shrink much faster than the actual total really used memory does.

You are correct in that there is nothing stopping you, the user, mapping your (limited in 32bit land) address space to the much larger disk or memory space that the CPU/OS supports . Some chips make this possible with more than 4GB of physical address space via mechanisms like PAE.

Windows itself provides an API to deal with most aspects of 'changing the mapping of your address space to get a different 'window' onto a wider pool (be it via things like PAE, running WoW64, disk or a mixture). This is called AWE. But mechanisms like this have existed for years (as those who remember the days of EMS with conventional memory or indeed the days of segmented memory.

Even without CPU and OS support you can still do it yourself by hand by a variety of techniques (see below).

A great deal of the more complex aspects of this in windows were dealt with by ever interesting Raymond Chen.

1
votes

(There is a switch for some versions of Windows to enable 3G for user programs, but we'll ignore that for purposes of this discussion, since the principle is the same.)

32bit programs can only access 4G of memory, since that's the largest pointer you can fit in 32 bits. When a program runs, some of the memory space is mapped to itself, and some is mapped into the operating system. Otherwise, when you call into the operating system, the operating system code couldn't see both its own memory and the program memory at the same time.

So your program doesn't get all of the memory, and hence the restrictions on contiguous allocation.

Now, different programs can have different subsets of all of the addressable memory. Some 32bit chips allow physically more than 4G of memory, but still, any given process, since it's 32bits, can only "see" directly up to 32bits-worth, or 4G, at a time, some of which belongs to the process (2G), and some to the operating system (2G) for managing the program and other programs.

That's as simple an explanation as I can give; see Virtual Memory for a longer and more technical explanation.

1
votes

Mark Russinovich wrote good article Pushing the Limits of Windows: Virtual Memory. I think you should read it to clearly understand how it is works.

0
votes

The total virtual address space available to a process is 4GB. The upper 2GB of this is common to all processes and is accessible only to system level components. The lower 2GB is private to each process, it is not shared. This has absolutely nothing to do with the size of RAM. There can be far more than 2GB of disk pages mapped to user processes. Since the 2GB process space is private the total address space for all processes will be far more than 2GB. It is impossible, even in theory, for more than one disk page to be mapped to one virtual address in the same process.