System and device programming-Memory management in Windows

 Overview

 

The OS manages all the details of mapping virtual to physical memory and the mechanics of page swapping, demand paging, 

Heap

Windows maintains pools of memory in heaps. A process can contain several heaps, and you allocate memory from these heaps

Heaps are Windows objects; therefore, they have handles. However, heaps are not kernel objects. The heap handle is necessary when you’re allocating memory. Each process has its own default heap, and the next function obtain

s its handle.

HANDLE GetProcessHeap (VOID)

Return:The handle for the process's heap;NUll on failure.

A program can also create distinct heaps. It is convenient at times to have separate heaps for allocation of separate data structures. The benefits of separate heaps include the following

( as the problem of contention between multiple threads is one of the most critical problems in allocating memory blocks within an heap. Indeed, this single heap must be shared among several threads by means of a single global lock. In order to solve, or at least to relieve, this problem, it is possible to use multiple heaps in place of only one. The benets of using separate heaps are: )


Fairness. If threads allocate memory solely from a unique heap assigned to the thread, then no single thread can obtain more memory than is allocated to its heap. In particular, a memory leak defect, caused by a program neglecting to free data elements that are no longer needed, will affect only one thread of a process.3

Allocation efficiency. Allocation of fixed-size data elements within a small heap can be more efficient than allocating elements of many different sizes in a single large heap. Fragmentation is also reduced. Furthermore, giving each thread a unique heap for storage used only within the thread simplifies synchronization, resulting in additional efficiencies. 

Deallocation efficiency. An entire heap and all the data structures it contains can be freed with a single function call. This call will also free any leaked memory allocations in the heap

Locality of reference efficiency. Maintaining a data structure in a small heap ensures that the elements will be confined to a relatively small number of pages, potentially reducing page faults as the data structure elements are processed


The memory management system of Windows systems is based on the utilization of heaps as primary internal data structure. The heap’s primary function is to eciently manage the memory and address space of a process for an application. An heap is used for allocating and freeing objects dynamically for use by the program. Heap operations are called for when: the number and size of objects needed by the program are not known ahead of time; an object is too large to t into a stack allocator

A heap uses parts of memory outside of what is allocated for the code and stack during run time. The Windows heap is a thin layer surrounding the Windows run-time allocator. All APIs forward their requests to the DLL. The Windows run-time allocator provides the core heap allocator within Windows. It consists of a front-end allocator with 128 free lists for sizes ranging from 8 to 1,024 bytes. The back-end allocator uses virtual memory to reserve and commit pages. The Virtual Memory Allocator reserves and commits pages used by the OS. All allocators use the virtual memory facility for accessing the data


At the beginning of a process, the OS creates a default heap called Process heap. The Process heap is used for allocating blocks if no other heap is used. Language run times also can create separate heaps within a process. Besides these dedicated heaps, the application program or one of the many loaded dynamic-link libraries (DLLs) may create and use separate heaps. Each process has then a default heap provided by the system. Applications that make frequent allocations from the heap can improve performance by using private heaps. When applications or DLLs create private heaps, these live in the process space and are accessible process-wide. A private heap is a block of one or more pages in the address space of the calling process. After creating the private heap, the process uses functions such as HeapAlloc() and HeapFree() to manage the memory in that heap. The heap functions can also be used to manage memory in the process’s default heap, using the handle returned by the GetProcessHeap() function. There is no dierence between memory allocated from a private heap and that allocated by using the other memory allocation functions. Note that a thread should call heap functions only for the process’s default heap and private heaps that the thread creates and manages, using handles returned by GetProcessHeap() or HeapCreate() function. 



Summary: Heap Management The normal process for using heaps is straightforward.

1. Get a heap handle with either  or . 2. Allocate blocks within the heap using . 3. Optionally, free some or all of the individual blocks with .

     

EXAMPLE: SORTING FILES WITH A BINARY SEARCH TREE

143

4. Destroy the heap and close the handle with . 5. The C run-time library ( , , etc.) are frequently adequate. However, memory allocated with the C library must be freed with the C library. You cannot assume that the C library uses the process heap.

wKiom1dLKfbxkVKXAABP0Int3C4702.png-wh_50

The node elements are fixed size and go in a heap of their own, whereas the varying-length data element records are in a separate heap.

 

Memory-Mapped Files


Dynamic memory in heaps must be physically allocated in a paging file. The OS’s memory management controls page movement between physical memory and the paging file and also maps the process’s virtual address space to the paging file. When the process terminates, the physical space in the file is deallocated. Windows memory-mapped file functionality can also map virtual memory space directly to normal files. This has several advantages.

There is no need to perform direct file I/O (reads and writes).

The data structures created in memory will be saved in the file for later use by the same or other programs. Be careful about pointer usage, as Program 5–5 illustrates.  Convenient and efficient in-memory algorithms (sorts, search trees, string processing, and so on) can process file data even though the file may be much larger than available physical memory. The performance will still be influenced by paging behavior if the file is large. 

File processing performance is frequently much faster than using the  and  file access functions. 

There is no need to manage buffers and the file data they contain. The OS does this hard work and does it efficiently with a high degree of reliability. 

Multiple processes can share memory by mapping their virtual address spaces to the same file or to the paging file (interprocess memory sharing is the principal reason for mapping to the paging file).

There is no need to consume paging file space.

Summary:

 File Mapping Here is the standard sequence required by file mapping.

1. Open the file. Be certain that it has at least  access. 2. If the file is new, set its length either with  (step 3) or by using  followed by . 3. Map the file with  or . 4. Create one or more views with . 5. Access the file through memory references. If necessary, change the mapped regions with  and . Use SEH to protect against  exceptions. 6. On completion, perform, in order, , for the mapping handle, and  for the file handle.

   

https://msdn.microsoft.com/zh-CN/Library/ms810613.aspx


General Heap Behavior

While the heap does provide support for managing smaller chunks of memory, it is itself nothing more than a chunk of memory implemented in the Windows NT virtual memory system. Consequently, the techniques that the heap uses to manage memory are based on the virtual memory management functions available to the heap. 


The two Types of Heaps

Every process in Windows has one heap called the default heap. Processes can also have as many other dynamic heaps as they wish, simply by creating and destroying them on the fly. The system uses the default heap for all global and local memory management functions, and the C run-time library uses the default heap for supporting malloc functions. The heap memory functions, which indicate a specific heap by its handle, use dynamic heaps. The behavior of dynamic heaps is discussed in the "Heap Memory API" section later in this article.


https://msdn.microsoft.com/en-us/library/ms810603.aspx

What Are Memory-Mapped File

There comes a time when you want to read and write to and from files so that the information is shared between processes. Think of it this way: two processes both open the same file and both read and write from it, thus sharing the information. The problem is, sometimes it's a pain to do all those fseek()s and stuff to get around. Wouldn't it be easier if you could just map a section of the file to memory, and get a pointer to it? Then you could simply use pointer arithmetic to get (and set) data in the file.

Well, this is exactly what a memory mapped file is. And it's really easy to use, too. A few simple calls, mixed with a few simple rules, and you're mapping like a mad-person.


Memory-mapped files (MMFs) offer a unique memory management feature that allows applications to access files on disk in the same way they access dynamic memory—through pointers. With this capability you can map a view of all or part of a file on disk to a specific range of addresses within your process's address space. And once that is done, accessing the content of a memory-mapped file is as simple as dereferencing a pointer in the designated range of addresses. So, writing data to a file can be as simple as assigning a value to a dereferenced pointer as in:


*pMem = 23;

Similarly, reading from a specific location within the file is simply:


nTokenLen = *pMem;

In the above examples, the pointer pMem represents an arbitrary address in the range of addresses that have been mapped to a view of a file. Each time the address is referenced (that is, each time the pointer is dereferenced), the memory-mapped file is the actual memory being addressed.

Note

   

While memory-mapped files offer a way to read and write directly to a file at specific locations, the actual action of reading/writing to the disk is handled at a lower level. Consequently, data is not actually transferred at the time the above instructions are executed. Instead, much of the file input/output (I/O) is cached to improve general system performance. You can override this behavior and force the system to perform disk transactions immediately by using the memory-mapped file function FlushViewOfFile explained later.


What Do Memory-Mapped Files Have to Offer?

One advantage to using MMF I/O is that the system performs all data transfers for it in 4K pages of data. Internally all pages of memory are managed by the virtual-memory manager (VMM). It decides when a page should be paged to disk, which pages are to be freed for use by other applications, and how many pages each application can have out of the entire allotment of physical memory. Since the VMM performs all disk I/O in the same manner—reading or writing memory one page at a time—it has been optimized to make it as fast as possible. Limiting the disk read and write instructions to sequences of 4K pages means that several smaller reads or writes are effectively cached into one larger operation, reducing the number of times the hard disk read/write head moves. Reading and writing pages of memory at a time is sometimes referred to as paging and is common to virtual-memory management operating systems.

Another advantage to using MMF I/O is that all of the actual I/O interaction now occurs in RAM in the form of standard memory addressing. . The MMF approach works a little differently. When the record is first accessed, the entire 4K page(s) of memory containing the record is read into memory. All subsequent accesses to that record deal directly with the page(s) of memory in RAM. No disk I/O is required or enforced until the file is later closed or flushed.

IC67863.gif

Figure 4. Prototype page-table entries are the mechanism that permits pages of memory to be shared among processes.

One of the best ways to use an MMF for sharing data is to use it in a DLL (dynamic-link library). The PortTool application serves as a useful illustration. PortTool uses a DLL to provide its porting functionality and relies on the main application for the user interface. The reason for this is simple: Other applications can then also use the DLL functionality. That is, other editors that are programmable can import the porting functionality. Because it is entirely feasible for PortTool to be running while another editor that imports the PortTool DLL is also running, it is best to economize system resources as much as possible between the applications. PortTool does this by using an MMF for sharing the porting information with both processes. Otherwise, both applications would be required to load their own set of porting information while running at the same time, a waste of system resources. The PortTool code demonstrates sharing memory via an MMF in a DLL.

Using Memory-Mapped File Functions

Memory-mapped file functions can be thought of as second cousins to the virtual-memory management functions in Windows. Like the virtual-memory functions, these functions directly affect a process's address space and pages of physical memory. No overhead is required to manage the file views, other than the basic virtual-memory management that exists for all processes. These functions deal in reserved pages of memory and committed addresses in a process. The entire set of memory-mapped file functions are:

  • CreateFileMapping

  • OpenFileMapping

  • MapViewOfFile

  • MapViewOfFileEx

  • UnmapViewOfFile

  • FlushViewOfFile

  • CloseHandle


Creating a File Mapping

To use a memory-mapped file, you start by creating a memory-mapped file object. The act of creating an MMF object has very little impact on system resources. It does not affect your process's address space, and no virtual memory is allocated for the object (other than for the internal resources that are necessary in representing the object). One exception, however, is that, if the MMF object represents shared memory, an adequate portion of the system pagefile is reserved for use by the MMF during the creation of the object.

Viewing Part of a Memory-Mapped File

Once obtained, the handle to the memory-mapped file object is used to map views of the file to your process's address space. Views can be mapped and unmapped at will while the MMF object exists. When a view of the file is mapped, system resources are finally allocated. A contiguous range of addresses, large enough to span the size of the file view, are now committed in your process's address space. Yet, even though the addresses have been committed for the file view, physical pages of memory are still only committed on a demand basis when using the memory. So, the only way to allocate a page of physical memory for a committed page of addresses in your memory-mapped file view is to generate a page fault for that page. This is done automatically the first time you read or write to any address in the page of memory.

To map a view of a memory-mapped file, use either the MapViewOfFile or the MapViewOfFileEx function. With both of these functions, a handle to a memory-mapped file object is a required parameter

/* Map a view of this file for writing. */
lpMMFile = (char *)MapViewOfFile (hMMFile, 
                                  FILE_MAP_WRITE, 
                                  0, 
                                  0, 
                                  0);

In this example, the entire file is mapped, so the final three parameters are less meaningful. The first parameter specifies the file-mapping object handle. The second parameter indicates the access mode for the view of the file. This can be FILE_MAP_READ, FILE_MAP_WRITE, or FILE_MAP_ALL_ACCESS, provided the protection on the file-mapping object permits it. If the object is created with PAGE_READWRITE protection, all of these access types are available. If, on the other hand, the file is created with PAGE_READONLY protection, the only access type available is FILE_MAP_READ. This allows the object creator control over how the object can be viewed.

Conclusion

Memory-mapped files provide unique methods for managing memory in the Windows application programming interface. They permit an application to map its virtual address space directly to a file on disk. Once a file has been memory-mapped, accessing its content is reduced to dereferencing a pointer.

A memory-mapped file can also be mapped by more than one application simultaneously. This represents the only mechanism for two or more processes to directly share data in Windows NT. With memory-mapped files, processes can map a common file or portion of a file to unique locations in their own address space. This technique preserves the integrity of private address spaces for all processes in Windows NT.

Memory-mapped files are also useful for manipulating large files. Since creating a memory mapping file consumes few physical resources, extremely large files can be opened by a process and have little impact on the system. Then, smaller portions of the file called "views" can be mapped into the process's address space just before performing I/O.

There are many techniques for managing memory in applications for Windows. Whether you need the benefits of memory sharing or simply wish to manage virtual memory backed by a file on disk, memory-mapped file functions offer the support you need.

heap and stack

http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

共享內存可以說是最有用的進程間通信方式,也是最快的IPC形式。兩個不同進程A、B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。進程A可以即時看到進程B對共享內存中數據的更新,反之亦然。由於多個進程共享同一塊內存區域,必然需要某種同步機制,互斥鎖和信號量都可以。 
採用共享內存通信的一個顯而易見的好處是效率高,因爲進程可以直接讀寫內存,而不需要任何數據的拷貝。對於像管道和消息隊列等通信方式,則需要在內核和用戶空間進行四次的數據拷貝,而共享內存則只拷貝兩次數據[1]:一次從輸入文件到共享內存區,另一次從共享內存區到輸出文件。實際上,進程之間在共享內存時,並不總是讀寫少量數據後就解除映射,有新的通信時,再重新建立共享內存區域。而是保持共享區域,直到通信完畢爲止,這樣,數據內容一直保存在共享內存中,並沒有寫回文件。共享內存中的內容往往是在解除映射時才寫回文件的。因此,採用共享內存的通信方式效率是非常高的。

mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以向訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。 
http://www.cnblogs.com/techdoc/archive/2010/12/22/1913521.html


DLL

http://stackoverflow.com/questions/913691/dll-and-lib-files-what-and-why

There are static libraries (LIB) and dynamic libraries (DLL).

Libraries are used because you may have code that you want to use in many programs. For example if you write a function that counts the number of characters in a string, that function will be useful in lots of programs. Once you get that function working correctly you don't want to have to recompile the code every time you use it, so you put the executable code for that function in a library, and the linker can extract and insert the compiled code into your program. Static libraries are sometimes called 'archives' for this reason.

Dynamic libraries take this one step further. It seems wasteful to have multiple copies of the library functions taking up space in each of the programs. Why can't they all share one copy of the function? This is what dynamic libraries are for. Rather then build the library code into your program when it is compiled, it can be mapped into your program as it is loaded into memory to run. Multiple programs running at the same time that use the same functions can all share one copy, saving memory. In fact, you can load dynamic libraries only as needed, depending on the path through your code. No point in having the printer routines taking up memory if you aren't doing any printing. On the other hand, this means you have to have a copy of the dynamic library installed on every machine your program runs on. This creates its own set of problems.

As an example, almost every program written in 'C' will need functions from a library called the 'C runtime library, though few programs will need all of the functions. The C runtime comes in both static and dynamic versions, so you can determine which version your program uses depending on particular needs.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682592(v=vs.85).aspx

Dynamic-Link Library Creation

An import library (.lib) file contains information the linker needs to resolve external references to exported DLL functions, so the system can locate the specified DLL and exported DLL functions at run time. You can create an import library for your DLL when you build your DLL.

Entry-Point Function Definition

A DLL can optionally specify an entry-point function. If present, the system calls the entry-point function whenever a process or thread loads or unloads the DLL. It can be used to perform simple initialization and cleanup tasks. For example, it can set up thread local storage when a new thread is created, and clean it up when the thread is terminated

The DLL entry-point function must be declared with the standard-call calling convention. If the DLL entry point is not declared correctly, the DLL is not loaded, and the system displays a message indicating that the DLL entry point must be declared with WINAPI.

Header file declares everything so that the compiler knows that you will provide it.

You have to include the header files so that the compiler understands the declarations of various types and functions that are exposed/used by the library.

The library files(lib or dll) contain the object code to which the code using the library links to.

for lib the linkage is static and happens at compile time.Using a static library(lib) causes the size of your executable to increase because the entire lib is linked in to your program.

for dll the linkage is dynamic and calls are evaluated at runtime.When using dll the size of your executable does not increase because the dll's are linked at runtime and you usually need to place them at predefined paths so that they can be linked at runtime.

Advantage of static library over dll is that your executable which uses the lib is standalone while in case of dll, the dll needs to be present at a predefined path whil running the executable which uses it.

The .lib file is necessary for the link step: at this point you'll have a set of object files that reference the FreeGLUT functions but no actual definition / implementation of them. In this case, it'll define them as DLL imports from the FreeGLUT.DLL that get resolved at load time.The .lib file is used to tell the linker where to find the implementations- normally they're just packaged in the .lib itself but in this case you have an import library, so it says "In the .DLL that I will dynamically load at run-time".

The .dll file is the implementation and is loaded at run-time. Normally you would not copy this to your System folder but instead leave them in the folder with your .exe.

Summary

Windows memory management includes the following features.

Logic can be simplified by allowing the Windows heap management and exception handlers to detect and process allocation errors.  Multiple independent heaps provide several advantages over allocation from a single heap, but there is a cost of extra complexity to assure that blocks are freed, or resized, from the correct heap.  Memory-mapped files, also available with UNIX but not with the C library, allow files to be processed in memory, as illustrated by several examples. File mapping is independent of heap management, and it can simplify many programming tasks. Appendix C shows the performance advantage of using memory-mapped files.  DLLs are an essential special case of mapped files, and DLLs can be loaded either explicitly or implicitly. DLLs used by numerous applications should provide version information.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章