When the original IBM PC was launched in 1981, it came equipped with a 16-bit real-mode, single-user, command-line oriented operating system called MS-DOS 1.0. This operating system consisted of 8 KB of memory resident code. Two years later, a much more powerful 24-KB system, MS-DOS 2.0, appeared. It contained a command line processor (shell), with a number of features borrowed from UNIX. When IBM released the 286-based PC/AT in 1984, it came equipped with MS-DOS 3.0, by now 36 KB. Over the years, MS-DOS continued to acquire new features, but it was still a command-line oriented system.
Inspired by the success of the Apple Macintosh, Microsoft decided to give MS-DOS a graphical user interface that it called Windows. The first three versions of Windows, culminating in Windows 3.x, were not true operating systems, but graphical user interfaces on top of MS-DOS, which was still in control of the machine. All programs ran in the same address space and a bug in anyone of them could bring the whole system to a grinding halt.
The release of Windows 95 in 1995 still did not eliminate MS-DOS, although it introduced a new version, 7.0. Together, Windows 95 and MS-DOS 7.0 contained most of the features of a full-blown operating system, including virtual memory, process management, and multiprogramming. However, Windows 95 was not a full 32-bit program. It contained large chunks of old 16-bit code (as well as some 32-bit code) and still used the MS-DOS file system, with nearly all its limitations. The only major change to the file system was the addition of long file names in place of the 8 + 3 character file names allowed in MS-DOS.
Even with the release of Windows 98 in 1998, MS-DOS was still there (now called version 7.1) and running 16-bit code. Although a bit more functionality migrated from the MS-DOS part to the Windows part, and a disk layout suitable for larger disks was now standard, under the hood, Windows 98 was not very different from Windows 95. The main difference was the user interface, which integrated the desktop, the Internet, and television more closely. It was precisely this integration that attracted the attention of the U.S. Dept. of Justice, which then sued Microsoft claiming that it was an illegal monopoly.
While all these developments were going on, Microsoft was also busy with a completely new 32-bit operating system being written from the ground up. This new system was called Windows New Technology, or Windows NT. It was initially hyped as the replacement for all other operating systems for Intel-based PCs, but it was somewhat slow to catch on and was later redirected to the upper end of the market, where it found a niche. It is gradually becoming more popular at the low end as well.
NT is sold in two versions: server and workstation. These two versions are nearly identical and are generated from the same source code. The server version is intended for machines that run as LAN-based file and print servers and has more elaborate management features than the workstation version, which is intended for desktop computing for a single user. The server version has a variant (enterprise) intended for large sites. The various versions are tuned differently, each one optimized for its expected environment. Other than these minor differences, all the versions are essentially the same. In fact, nearly all the executable files are identical for all versions. NT itself discovers which version it is by looking at a variable in an internal data structure (the registry). Users are forbidden by the license from changing this variable and thus converting the (inexpensive) workstation version into the (much more expensive) server or enterprise versions. We will not make any further distinction between these versions.
MS-DOS and all previous versions of Windows were single-user systems. NT, however, supports multiprogramming, so several users can work on the same machine at the same time. For example, a network server may have multiple users logged in simultaneously over a network, each accessing its own files in a protected way.
NT is a true 32-bit multiprogramming operating system. It supports multiple user processes, each of which has a full 32-bit demand-paged virtual address space. In addition, the system itself is written as 32-bit code everywhere.
One of NT's original improvements over Windows 95 was its modular structure. It consisted of a moderately small kernel that ran in kernel mode, plus a number of server processes that ran in user mode. User processes interacted with the server processes using the client-server model: a client sent a request message to a server, and the server did the work and returned the result to the client via a second message. This modular structure made it easier to port it to several computers besides the Intel line, including the DEC Alpha, IBM PowerPC, and SGI MIPS. However, for performance reasons, starting with NT 4.0, pretty much all of the system was put back into the kernel.
One could go on for a long time both about how NT is structured internally and what its system call interface is like. Since our primary interest here is the virtual machine presented by various operating systems (i.e., the system calls), we will give a brief summary of the system structure and then move on to the system call interface.
The structure of NT is illustrated in Fig. 6-31. It consists of a number of modules that are structured in layers and work together to implement the operating system. Each module has some particular function and a well-defined interface to the other modules. Nearly all the modules are written in C, although part of the graphics device interface is written in C++ and a tiny bit of the lowest layers are written in assembly language.
At the bottom is a thin layer called the hardware abstraction layer. Its job is to present the rest of the operating system with abstract hardware devices, devoid of the warts and idiosyncracies with which real hardware is so richly endowed. Among the devices modeled are off-chip caches, timers, I/O buses, interrupt controllers, and DMA controllers. By exposing these to the rest of the operating system in idealized form, it becomes easier to port NT to other hardware platforms, since most of the modifications required are concentrated in one place. User mode
Figure 6-31. The structure of Windows NT.
Above the hardware abstraction layer is a layer containing the microkernel. and the device drivers. The microkernel and all the device drivers have direct access to the hardware when needed, as they contain hardware-dependent code.
The microkernel supports the primitive kernel objects, interrupt, trap, and exception handling, process scheduling and synchronization, multiprocessor synchronization, and time management. The purpose of this layer is to make the rest of the operating system completely independent of the hardware, and thus highly portable. The micro kernel is permanently resident in main memory and is not preemptable, although it can temporarily give up control to service I/O interrupts.
Each device driver can control one or more I/O devices, but a device driver can also do things not related to a specific device, such as encrypting a data stream or even just providing access to kernel data structures. Since users can install new device drivers, they have the power to affect the kernel and corrupt the system. For this reason, drivers must be written with great care.
Above the microkernel and device drivers is the upper portion of the operating system, called the executive. The executive is architecture independent and can be ported to new machines with relatively little effort. It consists of three layers.
The lowest layer contains the file systems and the object manager. The file systems support the use of files and directories. The object manager handles objects known to the kernel. These include processes, threads (lightweight processes within an address space), files, directories, semaphores, I/O devices, timers, and many others. It also manages a namespace in which newly created objects can be placed so they can be referred to later.
The next layer consists of six major parts, as shown in Fig. 6-31. The I/O manager provides a framework for managing I/O devices and provides generic I/O services. It uses the services of the file system, which in turn uses the device drivers, as well as the services of the object manager.
The cache manager keeps the most recently used disk blocks in memory to speed up access to them in the (likely) event that they are needed again. Its job is to figure out which blocks are probably going to be needed again and which ones are not. It is possible to configure NT with multiple file systems, in which case the cache manager works for all of them, so each one does not have to do its own cache management. When a block is needed, the cache manager is asked to supply it. If it does not have the block, the cache manager calls upon the appropriate file system to get it. Since files can be mapped into processes' address spaces, the cache manager must interact with the virtual memory manager to provide the necessary consistency.
The virtual memory manager implements NT's demand-paged virtual memory architecture. It manages the mapping of virtual pages onto physical page frames. It thereby enforces the protection rules that restrict each process to only access those pages belonging to its address space and not to other processes' address spaces (except under special circumstances). It also handles certain system calls that relate to virtual memory.
The process and thread manager handles processes and threads, including their creation and destruction. It is concerned about the mechanisms used to manage them, rather than policies about how they are used.
The security manager enforces NT's elaborate security mechanism, which meets the U.S. Dept. of Defense's Orange Book C2 requirements. The Orange Book specifies a large number of rules that a conforming system must meet, starting with authenticated login through how access control is handled to the fact that virtual pages must be zeroed out before being reused.
The graphics device interface handles image management for the monitor and printers. It provides system calls to allow user programs to write on the monitor or printers in a device-independent way. It also contains the window manager and hardware device drivers. In versions of NT prior to NT 4.0, it was in user space but the performance was disappointing, so Microsoft moved it into the kernel to speed it up. The Win32 module also handles most of the system calls. It, too, was originally in user space but was also moved to the kernel to improve performance.
On the top of the executive is a thin layer called system services. Its function is to provide an interface to the executive. It accepts the true NT system calls and calls other parts of the executive to have them executed.
Outside the kernel are the user programs and the environmental subsystems. The environmental subsystems are provided because user programs are not encouraged to make system calls directly (although they are technically capable of it). Instead, each environmental subsystem exports a (different) set of function calls that user programs can use. Three environmental subsystems are shown in Fig. 6-31: Win32 (for NT or Windows 95/98 programs), POSIX (for UNIX programs that have been ported), and OS/2 (for OS/2 programs that have been ported).
Windows applications use the Win32 functions and communicate with the Win32 subsystem to make system calls. The Win32 subsystem accepts the Win32 function calls and uses the system interface library module (actually, a DLL file-see Chap. 7) to make the necessary true NT system calls to carry them out.
There is also a POSIX subsystem, which provides minimal support for UNIX applications. It supports only the P1003.l functionality and little else. It is a closed subsystem, meaning that its applications cannot use the facilities of the Win32 subsystem, which greatly restricts what they can do. In practice, porting any real UNIX program to NT using this subsystem is nearly impossible. It was included only because parts of the U.S. government require operating systems for government computers to be PlOO3.1 compliant. This subsystem is not selfcontained so it uses the Win32 subsystem for some of its work, but without exporting the full Win32 interface to its user programs.
The OS/2 subsystem is similarly limited in functionality and may be dropped in some future release. It also uses the Win32 subsystem. There is also an MS-DOS environmental subsystem (not shown in the figure).
Having looked briefly at the structure of NT, let us now turn to our main subject, the services offered by NT. This interface is the programmer's main connection to the system. Unfortunately, Microsoft has never made the complete list of NT system calls public, and it also changes them from release to release. Under such conditions, writing programs that make system calls directly is nearly impossible.
What Microsoft has done is define a set of calls called the Win32 API (Application Programming Interface) that are publicly known. These are library procedures that either make system calls to get the work done, or, in some case, do the work right in the user-space library procedure or in the Win32 sub system. The Win32 API calls do not change with new releases, to promote stability. However, there are also NT API calls that may change between releases of NT. Although the Win32 API calls are not all NT system calls, it is better to focus on these here rather than the true NT system calls because the Win32 API calls are well documented and more stable over time.
The Win32 API philosophy is completely different from the UNIX philosophy. In the latter, the system calls are all publicly known and form a minimal interface: removing even one of them would reduce the functionality of the operating system. The Win32 philosophy is to provide a very comprehensive interface, often with three or four ways of doing the same thing, and including many functions that clearly should not be (and are not) system calls, such as an API call to copy an entire file.
Many Win32 API calls create kernel objects of one kind or another, including files, processes, threads, pipes, etc. Every call creating a kernel object returns a result called a handle to the caller. This handle can be subsequently used to perform operations on the object. Handles are specific to the process that created the object referred to by the handle. They cannot be passed directly to another process and used there (just as UNIX file descriptors cannot be passed to other processes and used there). However, under certain circumstances, it is possible to duplicate a handle and pass it to other processes in a protected way, allowing them controlled access to objects belonging to other processes. Every object also has a security descriptor associated with it, telling in detail who may and may not perform what kinds of operations on the object.
NT is sometimes said to be object-oriented because the only way to manipulate kernel objects is by invoking methods (API functions) on their handles. On the other hand, it lacks some of the most basic properties of object-oriented systems such as inheritance and polymorphism.
The Win32 API is also available on Windows 95/98 (as well as on the consumer electronics operating system, Windows CE), with a small number of exceptions. For example, Windows 95/98 do not have any security, so those API calls that relate to security just return error codes on Windows 95/98. Also, NT file names use the Unicode character set, which is not available on Windows 95/98.
There are also differences in parameters to some API function calls. On NT, for example, all the screen coordinates given in the graphics functions are true 32-bit numbers; on Windows 95/98, only the low-order 16 bits are used (for backward compatibility with Windows 3.1). The existence of the Win32 API on several different operating systems makes it easier to port programs between them but also points out more clearly that it is somewhat decoupled from the actual system calls. Some of the differences between Windows 95/98 and NT are summarized in Fig. 6-32.
|Item||Windows 95/98||NT 5.0|
|Full 32-bit system?||No||Yes|
|Protected file mappings?||No||Yes|
|Private address space for each MS-DOS program?||No||Yes|
|Plug and play?||Yes||Yes|
|Runs on||Intel 80x86||80x86, Alpha|
|Re-entrant code inside aS?||No||Yes|
|Some critical as data writable by user?||Yes||No|
Figure 6-32. Some differences between versions of Windows.
from Andrew S. Tanenbaum, Structured Computer Organization, Fourth Ed., Prentice-Hall, 1999. (ISBN 0-13-095990-1)