25.1 IMPORT
LIBRARIES
( .LIB)
2
25.2 CALLING
CONVENTIONS
2
25.3 VARIABLE
SCOPE
IN DLL 2
25.4 RESOURCE
ONLY
DLL 5
25.5 DLL VERSIONS
5
25.6 GET
FILE
VERSION
INFO
5
25.7 THREADS
6
25.7.1 THREADS
AND MESSAGE
QUEUING
6
25.7.2 CREATING
SECONDARY
THREAD
7
25.7.3 THREAD
ADVANTAGES
7
25.7.4 THREAD
DISADVANTAGES
7
SUMMARY
8
EXERCISES
8
Threads and DLLs 2
25.1 Import Libraries ( .lib)
Import is statically linked to Executable module.
Example of Import libraries in windows are:
• Kernel32.lib
• User32.lib
• Gdi32.lib
Important System DLLs are
• Kernel32.dll
• User32.dll
• Gdi32.dll
25.2 Calling Conventions
Functions used in DLL’s are normally use
__stdcall calling convention.
__stdcall calling
convention is a standard calling convention used by the APIs in
Windows. This calling
convention cleans the stack after returning the called procedure
automatically. No extra
code is needed to clean out stack.
__stdcall calling convention
pushes the arguments in
stack from right to left order.
25.3 Variable Scope in DLL
Variables defined in DLL have scope in memory until the DLL is
loaded. After
unloading, the variable scope is vanished. Locally defined
variables are accessed within
the DLL only. The variables that are set to export variables can
be accessed outside the
DLL if the DLL is statically linked.
Variables can be shared across multiple processes by making the
separate data section as
following.
#pragma data_seg(
[ [ {
push
|
pop
},
] [
identifier,
] ] [
"segmentname"
[, "segment-class"
] )Specifies the data segment where initialized variables are
stored in the .obj file. OBJ files
can be viewed with the dumpbin application. The default segment
in the .obj file for
initialized variables is .data. Variables initialized to zero
are considered uninitialized and
are stored in .bss.
Threads and DLLs 3
data_seg with no
parameters resets the segment to .data.
push (optional)
Puts a record on the internal compiler stack. A
push
can have an identifier
and
segment-name.
pop (optional)
Removes a record from the top of the internal compiler stack.
identifier (optional)
When used with push,
assigns a name to the record on the internal compiler stack.
When used with pop,
pops records off the internal stack until
identifier
is
removed; if
identifier is not found on the internal
stack, nothing is popped.
identifier enables
multiple records to be popped with a single
pop
command.
"segment-name" (optional)
The name of a segment.
When used with
pop,
the stack is popped and segmentname
becomes the active segment name.
Example
// pragma_directive_data_seg.cpp
int h = 1; // stored in .data
int i = 0; // stored in .bss
#pragma data_seg(".my_data1")
int j = 1; // stored in "my_data1"
#pragma data_seg(push, stack1, ".my_data2")
int l = 2; // stored in "my_data2"
#pragma data_seg(pop, stack1) // pop stack1 off the stack
int m = 3; // stored in "stack_data1"
int main() {
}
Data allocated using data_seg
does not retain any information about its location.
#pragma comment(linker, “/SECTION: seg_data1, RWS”)
/SECTION:name,[E][R][W][S][D][K][L][P][X][,ALIGN=#]
The /SECTION option changes the attributes of a section,
overriding the attributes set
when the .obj file for the section was compiled.
A section in a portable executable (PE) file is roughly
equivalent to a segment or the
resources in a new executable (NE) file. Sections contain either
code or data. Unlike
segments, sections are blocks of contiguous memory with no size
constraints. Some
sections contain code or data that your program declared and
uses directly, while other
data sections are created for you by the linker and
manager (lib.exe) and contain
information vital to the operating system.
Threads and DLLs 4
Do not use the following names, as they will conflict with
standard names. For example,
.sdata is used on RISC platforms:
• .arch
• .bss
• .data
• .edata
• .idata
• .pdata
• .rdata
• .reloc
• .rsrc
• .sbss
• .sdata
• .srdata
• .text
• .xdata
Specify one or more attributes for the section. The attribute
characters, listed below, are
not case sensitive. You must specify all attributes that you
want the section to have; an
omitted attribute character causes that attribute bit to be
turned off. If you do not specify
R, W, or E, the existing read, write, or executable status
remains unchanged.
The meanings of the attribute characters are shown below.
Character Attribute Meaning
E Execute The section is executable
R Read Allows read operations on data
W Write Allows write operations on data
S Shared Shares the section among all processes that load the
image
D Discardable Marks the section as discardable
K Cacheable Marks the section as not cacheable
L Preload VxD only; marks the section as preload
P Pageable Marks the section as not pageable
X Memory-resident VxD only; marks the section as memory-resident
K and P are peculiar in that the section flags that correspond
to them are in the negative
sense. If you specify one of them on the .text section
(/SECTION:.text,K), there will be
no difference in the section flags when you run DUMPBIN with the
/HEADERS option;
it was already implicitly cached. To remove the default, specify
/SECTION:.text,!K and
DUMPBIN will reveal section characteristics, including "Not
Cached."
A section in the PE file that does not have E, R, or W set is
probably invalid.
Threads and DLLs 5
To set this linker option in the Visual Studio development
environment
1. Open the project's
Property Pages dialog box.
2. Click the Linker
folder.
3. Click the Command Line
property page.
4. Type the option into the
Additional Options box.
25.4 Resource Only DLL
Resource Only DLL contains only resource of different language
and local types.
Resource only DLLs do not contain Entry Point or any DllMain
Function.
Use of resource-only DLL is for internationalization.
25.5 DLL Versions
Version information makes it easier for applications to install
files properly and enables
setup programs to analyze files currently installed. The
version-information resource
contains the file's version number, intended operating system,
and original file name.
You can use the version information functions to determine where
a file should be
installed and identify conflicts with currently installed files.
These functions enable you
to avoid the following problems:
• installing older versions of
components over newer versions
• changing the language in a
mixed-language system without notification
• installing multiple copies
of a in different directories
• copying files to network
directories shared by multiple users
The version information functions enable applications to query a
version resource for file
information and present the information in a clear format. This
information includes the
file's purpose, author, version number, and so on.
You can add version information to any files that can have
Microsoft® Windows®
resources, such as dynamic-link libraries (DLLs), executable
files, or font files. To add
the information, create a VERSIONINFO Resource and use the
resource compiler to
compile the resource.
25.6 Get File Version Info
The GetFileVersionInfo
function retrieves version information for the specified file.
BOOL GetFileVersionInfo(
Threads and DLLs 6
LPTSTR
lptstrFilename, //file name whose version
is
to get*/
DWORD dwHandle,
/*unused*/
DWORD dwLen,
/*length of the given buffer*/
LPVOID lpData /*
buffer*/
);
lptstrFilename: Pointer to
a null-terminated string that specifies the name of the file of
interest. If a full path is not specified, the function uses the
search sequence specified by
the Load function.
dwHandle: This parameter
is ignored.
dwLen: Specifies the size,
in bytes, of the buffer pointed to by the
lpData
parameter.
Call the GetFileVersionInfoSize function first to determine the
size, in bytes, of a
file's version information. The
dwLen
member should be equal to or greater than
that value.
If the buffer pointed to by
lpData
is not large enough, the function truncates the
file's version information to the size of the buffer.
lpData: Pointer to a
buffer that receives the file-version information.
You can use this value in a subsequent call to the VerQueryValue
function to
retrieve data from the buffer.
Return Value:
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended
error information,
call GetLastError.
Call the
GetFileVersionInfoSize function before calling the
GetFileVersionInfo
function. To retrieve information from the file-version
information buffer, use the
VerQueryValue function.
25.7 Threads
25.7.1 Threads and Message Queuing
Message Queue is created when every any GDI function call is
made or sendmessage or
post message function calls are made. Message Queue can be
attached to every thread
either it is User interface thread or worker threads.
User Interface threads always a message queue.
Threads and DLLs 7
Worker threads are initially without message queue.
User Interface threads are those threads which are attached any
GUI component such as
window.
When a process start at least one thread is running that first
thread is called primary
thread other threads can made, these threads will, then, be
called secondary threads.
25.7.2 Creating Secondary Thread
For creating thread we can use following functions:
_beginthread() and _endthread()
This function is a ‘C’ runtime concept from UNIX system
These functions no longer have place in Win32 systems.
The CreateThread API
In windows systems CreateThread API is used to create a thread
in a process. Every
thread has its own thread procedure.
• Threads can be stopped and
exited using ExitThread API call.
• Thread enters into running
state after creating it. For thread not to be run
automatically gives the CREATE_SUSPENDED flag in CreateThread
API.
• Threads can be suspended or
resumes after their creations by:
• SuspendThread and
ResumeThread.
25.7.3 Thread Advantages
Using threads has the following advantages:
1. Threads can be used to start another activity parallel. E.g.
saving file on disk,
automatically while you are typing.
2. Perform different calculations parallel.
25.7.4 Thread Disadvantages
Threads major disadvantage is that they make the system slow
because thread uses the
time sharing concept that is another name 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
Threads and DLLs 8
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.
Note: You must use caution when using multiple threads in an
application, because
system performance can decrease if there are too many threads.
Summary
Multitasking Operating systems are useful to run applications
simultaneously.
Threads and processes are the key features of Operating systems.
In this lecture we
studied about variable sharing in DLLs, variable scope in DLLs,
DLL Versioning,
Resource only DLLs, Threads and their advantages and
disadvantages. Many Threads
can work better than using single thread sometime.
Exercises
1. Create a dynamic link and make a function which
displays only message
box. Export the functions using __dllexport.
2. Call the function from above in your executable
module. The linking must
be static linking and use __dllimport. |