Memory Management


Like UNIX, Windows has the standard heap management functions. Windows also provides functions for managing memory on a thread basis. As with other functional comparisons between UNIX and Windows, to learn about differences in memory management you should consult your UNIX and Win32 programming reference guides. The basic functional mapping is covered in the next few sections.

Heap

Windows provides services similar to UNIX with respect to heap management functionality. The standard C runtime includes comparable functions for calloc , malloc , free , and so on. It also has additional functions that may or may not be available in UNIX. The more significant added functionality is covered brieflyin the following section.

Thread Local Storage

This section is a brief introduction to Thread Local Storage (TLS). For complete details, see the Win32 API reference at MSDN ( http://msdn.microsoft.com ).

The purpose of TLS is to define memory on a per-thread basis. The typical scenario where TLS would be used is within a dynamic-linked library (DLL), but this is not the only possible use. In the case of the DLL scenario, here are some of the detailsof its use:

  • When a DLL attaches to a process, the DLL uses TlsAlloc to allocate a TLS index. The DLL then allocates some dynamic storage and uses the TLS index in a callto TlsSetValue to store the address in the TLS slot. This concludes the per-thread initialization for the initial thread of the process. The TLS index is stored in a global or static variable of the DLL.

  • Each time the DLL attaches to a new thread of the process, the DLL allocates some dynamic storage for the new thread and uses the TLS index in a call to TlsSetValue to store the address in the TLS slot. This concludes the per-thread initialization for the new thread.

  • Each time an initialized thread makes a DLL call requiring the data in its dynamic storage, the DLL uses the TLS index in a call to TlsGetValue to retrieve the address of the dynamic storage for that thread.

The following functions are used to manage Thread Local Storage:

  • TlsAlloc

    Allocates a thread local storage (TLS) index. A TLS index is used by a thread to store and retrieve values that are local to the thread. The minimum number of indices available to each process is defined by TLS_MINIMUM_AVAILABLE. TLS indices are not valid across process boundaries.

  • TlsFree

    Releases a thread local storage index. This, however, does not release the data allocated and set in the TLS index slot.

  • TlsSetValue

    Stores memory in a thread local storage index.

  • TlsGetValue

    Returns a memory element stored in a specified thread local storage index.

Thread Local Storage Example

The following section shows a portion of an example application. It illustrates allocation and access to a memory space on a per-thread basis. First, there is the main thread of the process that allocates a memory slot. The memory slot is then accessed and modified by a child thread. If several instances of the thread are active, each thread procedure would have a unique TLSIndex value to ensure the separation and isolation of data and state.

 DWORD TLSIndex = 0; DWORD WINAPI ThreadProc(LPVOID lpData) { HWND hWnd = (HWND) lpData; LPVOID lpVoid = HeapAlloc(GetProcessHeap(), 0, 128); TlsSetValue(TLSIndex, lpVoid); // Do your processing on the memory within the thread here HeapFree(GetProcessHeap(), 0, lpVoid); Return(0); } LRESULT CALLBACK WndProc(HWND  { switch(uMsg) { case WM_CREATE: TLSIndex = TlsAlloc(); // Start your threads using CreateThread Break; Case WM_DESTROY: TlsFree(TLSIndex); Break; Case WM_COMMAND: Switch(LWORD(wParam)) { case IDM_TEST: // Do something with the TLS value by a call to TlsGetValue(DWORD) break; } } } 

Memory-Mapped Files

Windows supports memory-mapped files and memory-mapped page files. Memory-mapped page files are covered in the next section, Shared Memory, as part of an exercise to port System V IPC shared memory to Windows using memory-mapped files.

Creating and using shared memory in UNIX and in Windows are conceptuallythe same, but syntactically different. A simple example of creating a shared memory area and mapping it in UNIX follows :

 if ((fd = open("/dev/zero", O_RDWR)) < 0) err_sys("open error"); if ((area = mmap(0, SIZE, PROT_READ  PROT_WRITE,  MAP_SHARED, fd, 0)) == (caddr_t) -1) err_sys("mmap error"); close(fd);    // can close /dev/zero now that its mapped 

In Win32, it is coded as follows:

 hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file            NULL,                 // no security attributes            PAGE_READWRITE,       // read/write access            0,                    // size: high 32-bits            SHMEMSIZE,            // size: low 32-bits            "dllmemfilemap");     // name of map object if (hMapObject != NULL) { // Get a pointer to the file-mapped shared memory. lpvMem = MapViewOfFile(hMapObject,     // object to map view of FILE_MAP_WRITE, // read/write access 0,              // high offset:  map from 0,              // low offset:   beginning 0);             // default: map entire file if (lpvMem == NULL) { CloseHandle(hMapObject); } } 

For details on the CreateFileMapping and MapViewOfFile functions, see the Win32 API documentation.

Shared Memory

Shared memory permits two or more threads or processes to share a region of memory. It is generally considered the most performant method of IPC because data is not copied as part of the communication process. Instead, the same physical area of memory is accessed by both the client and the server.

Windows does not support the standard System V interprocess communications mechanisms for shared memory (the shm*() APIs). It does, however, support memory-mapped files and memory-mapped page files, which you can use asan alternative to the shm*() APIs.

Appendix 9.1: Shared Memory presents an example of how to port a simple UNIX application based on System V IPC to Windows based on memory-mapped page files.

Synchronizing Access to Shared Resources

The technical challenge of using shared memory is to ensure that the server and client are not attempting to access the shared resource simultaneously . This is particularly troublesome if one or both are writing to the same shared memory area. For example, if the server is writing to the shared memory, the client should not try to access the data until the server has completed the write operation.

To address this, several forms of synchronization are available for use in Windows. In Appendix 9.3: Creating a Thread in Windows, the different forms of synchronization available in Windows are shown. These are:

  • Semaphore

  • Mutex

  • Event and critical section

UNIX has two of these mechanisms, the semaphore and the semaphore, as wellas an additional mechanism: file locking.

The first three mechanisms have two states: signaled and non-signaled. The synchronization object is considered busy when it is in a non-signaled state. When the object is busy, a waiting thread will block until the object switches to a signaled state. At this time, the pending thread continues executing.

The last form of synchronization is the critical section object. The critical section object is only for synchronizing threads within a single process. This synchronization mechanism only works for a single instance of the example application. Nonetheless, you can still consider its use as an IPC synchronization mechanism. This form of synchronization is appropriate for cases where you want to migrate your existing application from a multiprocess architecture to a single process with multithreaded architecture.

A complete Windows example of using threads, shared memory, semaphore, mutexes , and critical sections and events can be found in Appendix 9.3: Creating a Thread in Windows.

Note  

For applications that consume large amounts of memory and that are constrained by a lack of virtual address space, large memory support is available on Windows 2000 Advanced Server, Windows 2000 Datacenter Server, and Windows XP. A process running when using Windows normally has 2 GB of memory available in both user and system space. If the /3GB switch is inserted into Boot.ini file, Windows changes the split to give user space 3 GB and system space 1 GB. This change is a system-wide option and applies to all applications runon the computer, so using the /3GB switch should be analyzed for undesired side effects.For a sample of how to modify Boot.ini, See Knowledge Base article Q295443.

Note  

Applications that need to control the amount of stack or heap space can use linker switches for this purpose. The default size for both the stack and heap is 1 MB. Use the/STACK option to set the size of the stack and the /HEAP option to set the heap size. Both options take the size in bytes.

Further Reading on Memory Management

A few references on memory management that you may want to consult are:

  • Solomon, David A., and Russinovich, Mark E. Inside Microsoft Windows 2000, Third Edition . Redmond, WA: Microsoft Press, 2000. (See Chapters 7 and 10.)

  • Richter, Jeffrey. Programming Applications for Microsoft Windows, Fourth Edition . Redmond, WA: Microsoft Press, 1999. (See Part III, Chapters 13 “ 18.)

  • Stevens, W. Richard. Advanced Programming in the UNIX Environment. Reading, MA: Addison-Wesley Publishing Co., 1992.




UNIX Application Migration Guide
Unix Application Migration Guide (Patterns & Practices)
ISBN: 0735618380
EAN: 2147483647
Year: 2003
Pages: 134

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