24.1 WHAT
IS
A PROCESS
2
24.2 MEMORY
MANAGEMENT
BASICS
2
24.2.1 VIRTUAL
ADDRESS
SPACE
2
24.2.2 VIRTUAL
ADDRESS
SPACE
AND PHYSICAL
STORAGE 2
24.2.3 PAGE
STATE
3
24.3 MEMORY
PROTECTION
3
Copy-on-Write Protection
5
Loading Applications and DLLs
6
24.4 WHAT IS A
THREAD
6
24.4.1 MULTITASKING
7
24.5 LINKING THE
COMPILED
CODE
7
24.6 DYNAMIC
LINK
LIBRARIES
7
Types of Dynamic Linking
8
DLLs and Memory Management
8
24.7 DLL ENTRY
POINT
9
24.8 DLL EXPORTS
AND DLL IMPORTS
11
24.9 DLL FUNCTION
AND CALLING FUNCTION FROM IN IT
12
SUMMARY
12
EXERCISES
12
Dynamic Link Libraries 2
24.1 What Is a Process
A running application that consists of a private virtual address
space, code, data, and
other operating-system resources, such as files, pipes, and
synchronization objects that
are visible to the process. A process also contains one or more
threads that run in the
context of the process.
An application consists of one or more processes. A
process,
in the simplest terms, is an
executing program. One or more threads run in the context of the
process. A thread
is the
basic unit to which the operating system allocates processor
time. A thread can execute
any part of the process code, including parts currently being
executed by another thread.
A fiber
is a unit of execution that must be manually
scheduled by the application. Fibers
run in the context of the threads that schedule them.
24.2 Memory Management Basics
Each process on 32-bit Microsoft® Windows® has its own virtual
address space that
enables addressing up to 4 gigabytes of memory. All threads of a
process can access its
virtual address space. However, threads cannot access memory
that belongs to another
process which protects a process from being corrupted by another
process.
24.2.1 Virtual Address Space
The virtual addresses used by a process do not represent the
actual physical location of an
object in memory. Instead, the system maintains a
page map
for each process, which is
an internal data structure used to translate virtual addresses
into corresponding physical
addresses. Each time a thread references an address, the system
translates the virtual
address to a physical address.
The virtual address space is divided into partitions as follows:
The 2 GB partition in low
memory (0x00000000 through 0x7FFFFFFF) is available to the
process, and the 2 GB
partition in high memory (0x80000000 through 0xFFFFFFFF) is
reserved for the system.
24.2.2 Virtual Address Space and Physical storage
The virtual address space of each process is much larger than
the total physical memory
available to all processes. To increase the size of physical
storage, the system uses the
disk for additional storage. The total amount of storage
available to all executing
processes is the sum of the physical memory and the free space
on disk available to the
paging file, a disk file
used to increase the amount of physical storage. Physical storage
and the virtual address space of each process are organized into
pages,
units of memory,
whose size depends on the host computer. For example, on x86
computers the host page
size is 4 kilobytes.
Dynamic Link Libraries 3
To maximize its flexibility in managing memory, the system can
move pages of physical
memory to and from a paging file on disk. When a page is moved
in physical memory,
the system updates the page maps of the affected processes. When
the system needs
space in physical memory, it moves the least recently used pages
of physical memory to
the paging file. Manipulation of physical memory by the system
is completely transparent
to applications which operate only in their virtual address
spaces.
24.2.3 Page State
The pages of a process's virtual address space can be in one of
the following states.
State Description
Free
The page is neither committed nor reserved. The page is not
accessible to the
process. It is available to be committed, reserved, or
simultaneously reserved
and committed. Attempting to read from or write to a free page
results in an
access violation exception.
A process can use the
VirtualFree or
VirtualFreeEx
function to release
reserved or committed pages of its address space, returning them
to the free
state.
Reserved
The page has been reserved for future use. The range of
addresses cannot be
used by other allocation functions. The page is not accessible
and has no
physical storage associated with it. It is available to be
committed.
A process can use the
VirtualAlloc or
VirtualAllocEx
function to reserve
pages of its address space and later to commit the reserved
pages. It can use
VirtualFree or
VirtualFreeEx
to decommit committed pages and return
them to the reserved state.
Committed
Physical storage is allocated for the page, and access is
controlled by a
memory protection option. The system initializes and loads each
committed
page into physical memory only during the first attempt to read
or write to
that page. When the process terminates, the system releases the
storage for
committed pages.
A process can use
VirtualAlloc or
VirtualAllocEx
to allocate committed
pages. These functions can commit pages that are already
committed. The
GlobalAlloc and
LocalAlloc
functions allocate committed pages with
read/write access.
24.3 Memory Protection
Memory that belongs to a process is implicitly protected by its
private virtual address
space. In addition, Windows provides memory protection using the
virtual memory
hardware. The implementation of this protection varies with the
processor. For example,
Dynamic Link Libraries 4
code pages in the address space of a process can be marked
read-only and protected from
modification by user-mode threads.
The following table lists the memory-protection options provided
by Windows. You must
specify one of the following values when allocating or
protecting a page in memory.
Value Meaning
PAGE_EXECUTE
Enables execute access to the committed region of
pages. An attempt to read or write to the committed
region results in an access violation.
PAGE_EXECUTE_READ
Enables execute and read access to the committed
region of pages. An attempt to write to the committed
region results in an access violation.
PAGE_EXECUTE_READWRITE Enables execute, read, and write access
to the
committed region of pages.
PAGE_EXECUTE_WRITECOPY
Enables execute, read, and write access to the
committed region of pages. The pages are shared
read-on-write and copy-on-write.
PAGE_NOACCESS
Disables all access to the committed region of pages.
An attempt to read from, write to, or execute the
committed region results in an access violation
exception, called a general protection (GP) fault.
PAGE_READONLY
Enables read access to the committed region of pages.
An attempt to write to the committed region results in
an access violation. If the system differentiates
between read-only access and execute access, an
attempt to execute code in the committed region
results in an access violation.
PAGE_READWRITE Enables both read and write access to the
committed
region of pages.
PAGE_WRITECOPY
Gives copy-on-write protection to the committed
region of pages.
Windows Me/98/95: This
flag is not supported.
The following are modifiers that can be used in addition to the
options provided in the
previous table, except as noted.
Value Meaning
PAGE_GUARD
Pages in the region become guard pages. Any attempt to access a
guard page causes the system to raise a STATUS_GUARD_PAGE
exception and turn off the guard page status. Guard pages thus
act as
a one-time access alarm.
Dynamic Link Libraries 5
When an access attempt leads the system to turn off guard page
status, the underlying page protection takes over.
If a guard page exception occurs during a system service, the
service
typically returns a failure status indicator.
This value cannot be used with PAGE_NOACCESS.
PAGE_NOCACHE
Does not allow caching of the committed regions of pages in the
CPU cache. The hardware attributes for the physical memory
should
be specified as "no cache." This is not recommended for general
usage. It is useful for device drivers; for example, mapping a
video
frame buffer with no caching.
This value cannot be used with PAGE_NOACCESS.
Copy-on-Write Protection
Copy-on-write protection is an optimization that allows multiple
processes to map their
virtual address spaces such that they share a physical page
until one of the processes
modifies the page. This is part of a technique called
lazy evaluation,
which allows the
system to conserve physical memory and time by not performing an
operation until
absolutely necessary.
For example, suppose two processes load pages from the same DLL
into their virtual
memory spaces. These virtual memory pages are mapped to the same
physical memory
pages for both processes. As long as neither of the processes
writes to these pages, they
can map to and share the same physical pages as shown in the
following diagram.
If Process 1 writes to one of these pages, the contents of the
physical page are copied to
another physical page and the virtual memory map is updated for
Process 1. Both
processes now have their own instance of the page in physical
memory. Therefore, it is
Dynamic Link Libraries 6
not possible for one process to write to a shared physical page
and for the other process to
see the changes.
Figure 1
Loading Applications and DLLs
When multiple instances of the same Windows-based application
are loaded, each
instance is run in its own protected virtual address space.
However, their instance handles
(hInstance)
typically have the same value. This value represents the base address of the
application in its virtual address space. If each instance can
be loaded into its default base
address, it can map to and share the same physical pages with
the other instances, using
copy-on-write protection. The system allows these instances to
share the same physical
pages until one of them modifies a page. If for some reason one
of these instances cannot
be loaded in the desired base address, it receives its own
physical pages.
DLLs are created with a default base address. Every process that
uses a DLL will try to
load the DLL within its own address space at the default virtual
address for the DLL. If
multiple applications can load a DLL at its default virtual
address, they can share the
same physical pages for the DLL. If for some reason a process
cannot load the DLL at the
default address, it loads the DLL elsewhere. Copy-on-write
protection forces some of the
DLL's pages to be copied into different physical pages for this
process, because the
fixups for jump instructions are written within the DLL's pages,
and they will be different
for this process. If the code section contains many references
to the data section, this can
cause the entire code section to be copied to new physical
pages.
24.4 What is a Thread
A thread
is the basic unit to which the operating system
allocates processor time. A
thread can execute any part of the process code, including parts
currently being executed
by another thread.
Dynamic Link Libraries 7
24.4.1 Multitasking
A multitasking operating system divides the available processor
time among the
processes or threads that need it. The system is designed for
preemptive multitasking; it
allocates a processor
time slice to each thread it executes.
The currently executing thread
is suspended when its time slice elapses, allowing another
thread to run. When the system
switches from one thread to another, it saves the context of the
preempted thread and
restores the saved context of the next thread in the queue.
The length of the time slice depends on the operating system and
the processor. Because
each time slice is small (approximately 20 milliseconds),
multiple threads appear to be
executing at the same time. This is actually the case on
multiprocessor systems, where the
executable threads are distributed among the available
processors. However, you must
use caution when using multiple threads in an application,
because system performance
can decrease if there are too many threads.
24.5 Linking the Compiled Code
What is compiled .OBJ code?
Compiled Object file contains the reference of the unresolved
symbols.
Linker links the and paste the actual code from the
libraries to the executable code
that is called
static Linking;
Linking at run time is called Dynamic Linking.
Dynamic Link Libraries (DLLs) are linked dynamically.
Libraries are statically linked to the code and unresolved
symbols. When a programs
loads in memory and run then it would need dynamic link
libraries that have the symbols
and resolved addresses.
24.6 Dynamic Link Libraries
A dynamic-link
(DLL) is a module that contains
functions and data that can be
used by another module (application or DLL).
A DLL can define two kinds of functions: exported and internal.
The exported functions
are intended to be called by other modules, as well as from
within the DLL where they
are defined. Internal functions are typically intended to be
called only from within the
DLL where they are defined. Although a DLL can export data, its
data is generally used
only by its functions. However, there is nothing to prevent
another module from reading
or writing that address.
DLLs provide a way to modularize applications so that
functionality can be updated and
reused more easily. They also help reduce memory overhead when
several applications
use the same functionality at the same time, because although
each application gets its
own copy of the data, they can share the code.
Dynamic Link Libraries 8
The Windows application programming interface (API) is
implemented as a set of
dynamic-link libraries, so any process that uses the Windows API
uses dynamic linking.
Dynamic linking allows a module to include only the information
needed to locate an
exported DLL function at load time or run time. Dynamic linking
differs from the more
familiar static linking, in which the linker copies a
function's code into each
module that calls it.
Types of Dynamic Linking
There are two methods for calling a function in a DLL:
• In
load-time dynamic linking,
a module makes explicit calls to exported DLL
functions as if they were local functions. This requires you to
link the module
with the import for the DLL that contains the functions.
An import
supplies the system with the information needed to load the DLL
and locate the
exported DLL functions when the application is loaded.
• In
run-time dynamic linking,
a module uses the Load
or
LoadEx
function to load the DLL at run time. After the DLL is loaded,
the module calls
the GetProcAddress
function to get the addresses of the exported
DLL functions.
The module calls the exported DLL functions using the function
pointers returned
by GetProcAddress.
DLLs and Memory Management
Every process that loads the DLL maps it into its virtual
address space. After the process
loads the DLL into its virtual address, it can call the exported
DLL functions.
The system maintains a per-thread reference count for each DLL.
When a thread loads
the DLL, the reference count is incremented by one. When the
process terminates, or
when the reference count becomes zero (run-time dynamic linking
only), the DLL is
unloaded from the virtual address space of the process.
Like any other function, an exported DLL function runs in the
context of the thread that
calls it. Therefore, the following conditions apply:
• The threads of the process
that called the DLL can use handles opened by a DLL
function. Similarly, handles opened by any thread of the calling
process can be
used in the DLL function.
• The DLL uses the stack of
the calling thread and the virtual address space of the
calling process.
• The DLL allocates memory
from the virtual address space of the calling process.
Dynamic Link Libraries 9
24.7 DLL Entry Point
The DllMain
function is an optional entry point into a
dynamic-link (DLL). If the
function is used, it is called by the system when processes and
threads are initialized and
terminated, or upon calls to the
Load
and
Free functions.
DllMain is a placeholder
for the -defined function name. You must specify the
actual name you use when you build your DLL. For more
information, see the
documentation included with your development tools.
BOOL WINAPI DllMain(
HINSTANCE
hinstDLL,
/*Handle to the instance of the */
DWORD
fdwReason, /*reason of
loading and unloading
LPVOID
lpvReserved /*future use or no use des. By Microsoft*/
);hinstDLL: Handle to the
DLL module. The value is the base address of the DLL. The
HINSTANCE of a DLL is the
same as the HMODULE
of the DLL, so
hinstDLL
can be
used in calls to functions that require a module handle.
fdwReason: Indicates why
the DLL entry-point function is being called. This parameter
can be one of the following values.
Value Meaning
DLL_PROCESS_ATTACH
The DLL is being loaded into the virtual address
space of the current process as a result of the
process starting up or as a result of a call to
Load. DLLs can use
this opportunity to
initialize any instance data or to use the
TlsAllocfunction to allocate a thread local storage (TLS)
index.
DLL_THREAD_ATTACH
The current process is creating a new thread.
When this occurs, the system calls the entrypoint
function of all DLLs currently attached to
the process. The call is made in the context of
the new thread. DLLs can use this opportunity to
initialize a TLS slot for the thread. A thread
calling the DLL entry-point function with
DLL_PROCESS_ATTACH does not call the
DLL entry-point function with
DLL_THREAD_ATTACH.
Note that a DLL's entry-point function is called
with this value only by threads created after the
DLL is loaded by the process. When a DLL is
loaded using Load, existing threads do
not call the entry-point function of the newly
loaded DLL.
Dynamic Link Libraries 10
DLL_THREAD_DETACH
A thread is exiting cleanly. If the DLL has stored
a pointer to allocated memory in a TLS slot, it
should use this opportunity to free the memory.
The system calls the entry-point function of all
currently loaded DLLs with this value. The call
is made in the context of the exiting thread.
DLL_PROCESS_DETACH
The DLL is being unloaded from the virtual
address space of the calling process as a result of
unsuccessfully loading the DLL, termination of
the process, or a call to
Free.
The DLL
can use this opportunity to call the
TlsFree
function to free any TLS indices allocated by
using TlsAlloc
and to free any thread local data.
Note that the thread that receives the
DLL_PROCESS_DETACH notification is not
necessarily the same thread that received the
DLL_PROCESS_ATTACH notification.
lpvReserved: If
fdwReason
is DLL_PROCESS_ATTACH,
lpvReserved
is NULL for
dynamic loads and non-NULL for static loads.
If fdwReason
is DLL_PROCESS_DETACH,
lpvReserved
is NULL if
DllMain
has been called by using
Free and non-NULL if
DllMain
has been called
during process termination.
Return Values:
When the system calls the
DllMain
function with the DLL_PROCESS_ATTACH
value, the function returns TRUE if it succeeds or FALSE if
initialization fails. If
the return value is FALSE when
DllMain
is called because the process uses the
Load function,
Load
returns NULL. (The system immediately
calls your entry-point function with DLL_PROCESS_DETACH and
unloads the
DLL.) If the return value is FALSE when
DllMain
is called during process
initialization, the process terminates with an error. To get
extended error
information, call GetLastError.
When the system calls the
DllMain
function with any value other than
DLL_PROCESS_ATTACH, the return value is ignored.
During initial process startup or after a call to
Load,
the system scans the list of
loaded DLLs for the process. For each DLL that has not already
been called with the
DLL_PROCESS_ATTACH value, the system calls the DLL's entry-point
function. This
call is made in the context of the thread that caused the
process address space to change,
such as the primary thread of the process or the thread that
called Load.
Access
to the entry point is serialized by the system on a process-wide
basis.
Dynamic Link Libraries 11
There are cases in which the entry-point function is called for
a terminating thread even if
the entry-point function was never called with DLL_THREAD_ATTACH
for the thread:
• The thread was the initial
thread in the process, so the system called the entrypoint
function with the DLL_PROCESS_ATTACH value.
• The thread was already
running when a call to the Load
function was
made, so the system never called the entry-point function for
it.
When a DLL is unloaded from a process as a result of an
unsuccessful load of the DLL,
termination of the process, or a call to
Free,
the system does not call the DLL's
entry-point function with the DLL_THREAD_DETACH value for the
individual threads
of the process. The DLL is only sent a DLL_PROCESS_DETACH
notification. DLLs
can take this opportunity to clean up all resources for all
threads known to the DLL.
However, if the DLL does not successfully complete a
DLL_PROCESS_ATTACH
notification, the DLL does not receive either a
DLL_THREAD_DETACH or
DLL_PROCESS_DETACH notification.
Warning The entry-point
function should perform only simple initialization or
termination tasks. It must not call the
Load
or LoadEx function (or a
function that calls these functions), because this may create
dependency loops in the DLL
load order. This can result in a DLL being used before the
system has executed its
initialization code. Similarly, the entry-point function must
not call the Freefunction (or a function that calls
Free),
because this can result in a DLL being
used after the system has executed its termination code.
It is safe to call other functions in Kernel32.dll, because this
DLL is guaranteed to be
loaded in the process address space when the entry-point
function is called. It is common
for the entry-point function to create synchronization objects
such as critical sections and
mutexes, and use TLS. Do not call the registry functions,
because they are located in
Advapi32.dll. If you are dynamically linking with the C run-time
, do not call
malloc; instead, call
HeapAlloc.
Calling imported functions other than those located in
Kernel32.dll may result in
problems that are difficult to diagnose. For example, calling
User, Shell, and COM
functions can cause access violation errors, because some
functions in their DLLs call
Load to load other
system components. Conversely, calling those functions
during termination can cause access violation errors because the
corresponding
component may already have been unloaded or uninitialized.
Because DLL notifications are serialized, entry-point functions
should not attempt to
communicate with other threads or processes. Deadlocks may occur
as a result.
24.8 DLL Exports and DLL Imports
The export table How to export and import code (functions) in a
DLLs
__declspec( dllimport ) int i;
Dynamic Link Libraries 12
__declspec( dllexport ) void function(void);
24.9 DLL Function and calling function from in it
Load loads a in process address space.
HMODULE Load(
LPCTSTR lpFileName //file name of module
);
Free free the that was loaded previously by
Load function.
Free(hModule)
Now we call function from using GetProcAddress.
GetProcAddress returns the
address of the function.
FARPROC GetProcAddress(
HMODULE hModule, // handle to DLL module
LPCSTR lpProcName // function name
);
Summary
Dynamic link libraries are the windows executables but these
cannot be executed
by writing its name on command line or double clicking on it.
These libraries contain
separate modules that load and run in any process address space.
Thread is the execution
unit in a Process. A process can have more than one thread.
There are two types of
dynamic linking load time dynamic linking and run time dynamic
linking. In load time
dynamic linking, a module makes explicit calls to exported DLL
functions as if they were
local functions and in run time dynamic linking Load
function is used to load the
and Get procedure address functions are called to get
the address of the function
from loaded . DLL can export functions in the form
definition files. In definition
file we can provide ordinal as well. Ordinal is a number that is
used to locate the function
instead of function name.
Exercises
1. Create a dynamic link and make a function which
displays only message
box.
Dynamic Link Libraries 13
2. Call the function from above in your executable
module the linking must
be dynamic linking. |