ID Number: Q30590
2.03 2.10 3.00
WINDOWS
Summary:
This article describes how using Windows expanded memory affects
application development.
Please note that when expanded memory is mentioned in this article, it
also means extended memory. Extended memory is used as expanded memory
by Windows.
More Information:
In Windows versions 2.x and 3.0, expanded memory can be used by the
Windows memory manager. In enhanced mode Windows 3.0, the memory
manager can emulate expanded memory by using extended memory. All
Windows applications are run in one virtual machine, but each DOS
application receives its own virtual machine in which to run.
In real mode Windows, expanded memory presents the following problems:
1. Applications cannot share memory through global handles
2. The efficient use of available EMS (expanded memory specification)
in a small frame
The only way applications can share global data is through the dynamic
data exchange (DDE) protocol or through the clipboard. When large
frame EMS is used, global objects are allocated above the EMS line and
are available only to one application. For example, in large frame
EMS, task A allocates some global memory and passes the handle to task
B. When task B attempts to access the memory object, it will not be in
memory. Instead, task B will access the corresponding location in its
own EMS memory.
DDE and clipboard objects can be shared because the Windows memory
manager will copy the contents of these objects to the currently
running application's EMS bank. The application must check the return
value from GlobalLock() because the memory manager may not be able to
successfully copy the object in a low memory situation. Clipboard
objects should be copied by the receiving application before the
clipboard is closed because the memory manager may delete the global
object.
Applications can share data through dynamic-link libraries (DLLs), as
well as through DDE and clipboard objects; however, only data located
in the DLL data segment can be shared. Global objects allocated by
DLLs are allocated above the EMS line, just like objects allocated by
an application.
There is one exception to the rule of not sharing global memory
handles. If the GMEM_NOT_BANKED flag is used, the object will be
allocated below the EMS bank line, making it available to all
applications. This should not be done because there is only a limited
amount of memory below the EMS line when the system is using large
frame EMS. This flag is available for device drivers that require this
kind of shared memory; applications should be designed using one of
the other methods to share memory objects.
The second issue regards the most effective use of small frame EMS by
applications. In small frame EMS, code and resources are the only EMS
items available to applications. Once code and resources are loaded
into EMS, they will not be discarded. However, they are banked out
when another task is running.
The Windows loader fills EMS before it loads code or resources into
conventional memory. For this reason, the DEF file for each
application should list the segments that are important throughout the
life of an application at the top of the list of segments in the
SEGMENTS statement, and these segments should be marked as PRELOAD.
List the segment that contains the application's main window procedure
first. The segments for code that is used and discarded, such as
initialization code, should be listed toward the bottom of the list.
By the same reasoning, mark resources that are important throughout
the life of the application as PRELOAD.
For small applications, the LimitEmsPages() function allows an
application to limit the amount of EMS that is allocated on its
behalf. The argument passed to this function is the maximum number of
kilobytes of EMS that Windows will allocate for the application. A
small application can call this function to keep 400-500K of EMS from
being allocated when the application can run reliably with 100K of
EMS.
When LimitEmsPages() is used, it is important to note that in large
frame EMS (where DLL code is located above the EMS line), a small
application will require more space than the sum of its segments
because library code shares the EMS allocated for the application.
Note: Hook callback functions must be placed in FIXED DLL code so the
code will always be present regardless of EMS state. The same is true
for GlobalNotify() callback functions.
Additional reference words: 2.03 2.10 3.00