Understanding
How Windows Works
By Denthor
When I was first asked to program in Windows, I put aside the paranoid dislike
of Microsoft that most people have and decided to give it a go. Windows had
intrigued me early on anyway; as an assembler coder, I was wondering how they
got all those separate windows going at once at that speed? Were they saving
and restoring the registers each time a window got a time slice? After I while
I figured out what Microsoft was doing and found out that they were using some
pretty clever tricks in order to have the whole system function.
What I am going to discuss is how Windows works at a base level. This could
help you if you decide to program for it, or may just give you an insight as
to why things happen as they do, especially when they go wrong. I will start
off by focusing on Windows 3.1, of which 95 and NT are super-enhanced versions.
The main trick behind Windows is that it is a message-based system. This requires
a comparison with a simple DOS program. In DOS, you have a single program thread;
you have an entry point, do initialization routines, go into a main loop (in
a game at least), do some shutdown routines and then quit. This linear method
is quite easy to follow. However, if you try to create some sort of time slicing
for this, when you run two programs each will be less then half as fast as the
original.
Windows takes another approach. You have an entry point, where you do your initializations.
Your program then waits to be told what to do next. For the rest of the time
you receive messages, which you must respond to. Let me give you an example.
You start a program with an entry point. You create a window with a frame, a
menu and a "body" - the white space under the menu. If you ignored all messages,
you would never see this window. Instead you watch for when this window is sent
a WM_PAINT message. When you get this, you are required to draw whatever it
is you want in the body of the window. You will get another message when a user
clicks a menu item, when the mouse moves, or when the palette changes etc. You
handle only the messages you wish to and call the default Windows response for
any others.
An interesting point is that while you are handling a message and drawing something
during a WM_PAINT, nothing else is happening in windows. All the other applications
have stopped while you are processing this message. (Not quite true in 95 and
NT, but we'll get to that). This means that if you create an infinite loop whilst
processing the WM_PAINT message (or any message you've chosen to implement),
the entire windows system will stop there and you will need to hit ctrl-alt-del
to terminate the application and restart windows. In 95, which does do close
on "real" multitasking, the other windows will continue to operate, but the
"hung" window will not be updated, and become white (I'm sure we have all seen
this happen). This means that the window cannot receive any new messages because
it hasn't finished with the last one.
That is where the speed of the windows system comes from : the main "kernel"
monitors which windows have moved, notifies the windows that are now visible
to repaint themselves, handles mouse movements and sends messages when the user
does something to the application. Even animation (under 3.1) is handled via
messages. A standard game loop, e.g. making a pixel move from A to B, would
temporarily halt all other applications while it was happening. Instead (in
windows) the application asks to be sent a WM_TIMER message every 10 or so milliseconds,
and every time it gets this it moves the pixel a little bit more.
95 and NT are much nicer than 3.1. Applications still use messages in exactly
the same way that 3.1 does (which is why 3.1 applications still work in 95),
but they are also thread based. A "thread" is like a separate process in a multithreaded
environment, each thread working independently of the others. That is why, in
95, when one application goes into an infinite loop or takes a long time to
finish processing a message, another application will still update itself, receive
timer messages and so on. Another nice point about 95 and NT is that a single
application can create multiple threads; this was evidenced in a recent star
conquest game where the computer thought up its next move in a separate thread
while the player made his. With the added facilities of 32bit code, a flat memory
model and various other perks, 95 and NT make much better platforms than any
of their predecessors.
As you can see, Windows is not using time slicing in the standard sense of the
word. A multi-tasking system based on the standard time-slicing mechanism made
up of standard DOS-application threads would not have been able to have as many
applications open on my old 386 as Win31 did. Nowadays, 95 flies along on my
Pentium processor. The challenges of programming for a message-based system
are vastly different to those of DOS, but the benefits make it more than worth
it.
Denthor
[email protected]