Overall System Architecture
arguably the most
attempt at operating system control in the history of computers. This section
2000 architecture, highlighting the features of significant interest to a device driver author.
Design Goals for Windows 2000
The original goals for Microsoft's NT ("New Technology") operating system took form in early 1989. Interestingly, the original concept for NT did not even include a Windows operating environment. While the NT OS has indeed come a long way since 1989, the five fundamental goals
The OS should support as much existing software and hardware as possible.
Robustness and reliability.
The OS should be resilient to inadvertent or intentional misuse. A
's application should not be able to crash the system.
The OS should run on as many present and future platforms as possible.
Since the market requirements will change (grow) over time, the OS must make it easy to add new features and support new hardware with minimal impact on existing code.
The OS should provide good performance for a given capability of the hardware platform which
Of course, goals are not reality, and over time, serious compromise of one goal may be necessary to achieve another. NT is an operating system and, as such, is subject to the same sorts of compromises that affect all systems. The remainder of this section describes the delicate balance of solutions that Microsoft OS designers chose to implement their goals.
Hardware Privilege Levels in Windows 2000
To achieve the robustness and reliability goal, the designers of NT chose a
implementation. A user application runs as a client of OS services.
The user application runs in a special mode of the hardware known generically as
. Within this mode, code is restricted to nonharmful operations. For example, through the magic of virtual memory mapping, code cannot touch the memory of other applications (except by mutual agreement with another application). Hardware I/O instructions cannot be executed. Indeed, an entire class of CPU instructions (designated
), such as a CPU Halt, cannot be executed. Should the application require the use of any of these
operations, it must make a request of the operating system kernel. A hardware-provided
mechanism is used to make these
Operating system code runs in a mode of the hardware known as
. Kernel-mode code can perform any valid CPU instruction, notably including I/O operations. Memory from any application is exposed to kernel-mode code, providing, of course, that the application memory has not been
All modern processors implement some form of
modes. Kernel-mode code executes in this privileged context, while user-mode code executes in the nonprivileged environment. Since different processors and platforms implement privileged modes differently, and to help achieve the goal of portability, the OS designers provided an abstraction for user and kernel modes. OS code always uses the abstraction to perform privileged context switches, and thus only the abstraction code itself need be ported to a new platform. On an Intel platform, user mode is implemented using Ring 3 of the instruction set, while kernel mode is implemented using Ring 0.
This discussion is relevant to device driver writers in that kernel-mode drivers execute in a privileged context. As such, poorly written device driver code can and does compromise the integrity of the Windows 2000 operating system. Driver writers must take extra care in handling all boundary conditions to ensure that the code does not bring down the entire OS.
To achieve the portability goal, NT designers chose a layered architecture for the software, as shown in Figure 1.1.
of the Windows 2000 operating system
The Hardware Abstraction Layer (HAL) isolates processor and platform dependencies from the OS and device driver code. In general, when device driver code is ported to a new platform, only a recompile is necessary. How can this work since device driver code is
device-, processor-, and platform-specific? Clearly, the device driver code must rely on code (macros) within the HAL to reference hardware registers and buses. In some cases, the device driver code must rely on abstraction code provided in the I/O Manager (and elsewhere) to manipulate shared hardware resources (e.g., DMA channels).
chapters in this book will explain the proper use of the HAL and other OS services so that device driver code can be platform-independent.
Figure 1.1 also shows an important design concept of Windows 2000 -the kernel is separate from a layer known as the
The Windows 2000 kernel is primarily responsible for the scheduling of all thread activity. A thread is simply an independent
of execution through code. To remain independent of other thread activity, a unique thread
must be preserved for each thread. The thread context consists of the CPU register state (including a separate stack and Program Counter), an ID (sometimes called a Thread ID or TID, internally known as a Client ID), a priority value, storage locations local to the thread (Thread Local Storage), and other thread-relevant information.
The scheduler's responsibility is to manage which thread should execute at any given time. In a single processor environment, of course, only one thread may actually gain control of the processor at a time. In a multiprocessor environment, different threads may be executing on the different available processors, offering true parallel execution of code. The scheduler
a processor to a thread for, at most, a fixed period of time known as the
thread time quantum
. Processors are assigned to threads primarily based on the thread's priority value. Higher priority threads that become ready to run will
a running thread.
Since the kernel's prime role is to schedule thread activity, other OS components perform the necessary work of memory, process, security, and I/O management. These
are collectively known as the
. The Executive components have been designed (though the I/O Manager itself is a significant exception) as modular software. Over the
, Microsoft has added, deleted, merged, and separated these components as improvements and compromises deemed necessary. A good example would be the addition of the Active Directory Services, which is relatively new to Windows 2000.
The notion of keeping the kernel itself small and clean,
of Executive components, provides the basis for NT's claim to extendibility. The OS has now survived about ten years of revisions, maintenance, and significant feature improvement (a.k.a.,
While the layered approach to software design is often characterized by lackluster performance, attention to fast layer interaction has been a continual effort with the NT design
. First, it should be noted that all the layers described so far execute within the same hardware mode, kernel mode. Therefore, interlayer calls often involve nothing more than a processor CALL instruction. Indeed, HAL usage is often implemented with macros, thus achieving inline performance.
Second, there has been a concentrated effort to parallelize as many
as possible by allocating threads to different units of work. The Executive components are all multithreaded. Helper routines seldom
while performing their work. This minimizes true idle time on the processor.
The performance goals of Windows 2000 impact device driver writers. As user and system threads request service from a device, it is
that the driver code not block execution. If the request cannot be handled immediately, perhaps because the device is busy or slow, the request must be queued for subsequent handling. Fortunately, I/O Manager routines facilitate this process.
Since the Executive components provide the base services for the Windows 2000 operating system (other than thread scheduling), their needs and responsibilities are
clear. These components are explained in the following sections.
SYSTEM SERVICE INTERFACE
This component provides the entry point from user mode to kernel mode. This allows user-mode code to cleanly and safely invoke services of the OS. Depending on the platform, the transition from user mode to kernel mode may be a simple CPU instruction or an elaborate Save and Restore context switch.
Almost all services
by the OS are
with an object. For example, a user-mode program that needs thread-to-thread synchronization might request a
service from the OS. The OS presents the mutex in the form of an OS-based object, referenced from user mode only through a
. Files, processes, Threads, Events, Memory Sections, and even Registry Keys are modeled with OS-based objects. All objects are created and
by a centralized Object Manager. This allows for uniform access, life
, and security with all objects.
The Configuration Manager of Windows 2000 models the hardware and installed software of the machine. A database called the Registry is used to store this model. Device drivers utilize information in the Registry to discover many aspects of the environment in which they are executed. With the introduction of Plug and Play into Windows 2000, the role of the Registry for device drivers has been significantly reduced.
A process is the environment in which threads execute in Windows 2000. Each process maintains a private address space and security identity. In Windows 2000, it is important to note that processes do not
; instead, threads are the unit of execution and the process is a unit of ownership. A process owns one or more threads.
The Windows 2000 Process Manager is the Executive component that
the process model and exposes the environment in which process threads run. The Process Manager relies heavily on other Executive components (e.g., the Object Manager and Virtual Memory Manager) to perform its work. As such, it could be said that the Process Manager simply exposes a higher level of abstraction for other lower-level system services.
Device drivers seldom interact with the Process Manager directly. Instead, drivers rely on other services of the OS to touch the process environment. For example, a driver must ensure that a buffer residing with the private address space of a process remains "locked down" during an I/O transfer. Routines within the OS allow a driver to perform this locking activity.
VIRTUAL MEMORY MANAGER
Under Windows 2000, the address space of a process is a flat 4 gigabytes (4 GB) (2
). Only the lower 2 GB is accessible in user mode. A program's code and data must reside in this lower half of the address space. If the program relies on shared library code (
libraries or DLLs), the library code also must reside in the first 2 GB of address space.
The upper 2 GB of address space of every process contains code and data accessible only in kernel-mode. The upper 2 GB of address space is shared from process to process by kernel-mode code. Indeed, device driver code is mapped into address space above 2 GB.
The Virtual Memory Manager (VMM)
memory management on
of the entire system. For normal user-mode programs, this means allocating and managing address space and physical memory below the 2 GB boundary. If the needed memory for a given process is not physically available, the VMM provides an illusion of memory by
the request. Needed memory is
onto a disk file and retrieved into RAM when accessed by a process. In effect, RAM becomes a shared resource of all processes, with memory moving between files on the disk and the limited RAM available on a given system.
The VMM also acts a memory allocator in that it maintains heap areas for kernel-mode code. Device drivers can request the VMM to assign dedicated areas of pagable or nonpagable memory for its use. Further, devices that
using DMA (direct memory access) can assign nonpagable memory as needed to perform data transfers between RAM and a device. Of course, these topics are covered in more detail in subsequent chapters.
LOCAL PROCEDURE CALL FACILITY
A Local Procedure Call (LPC) is a call mechanism between processes of a single machine. Since this
call must pass between different address spaces, a kernel-mode Executive component is provided to make the action efficient (and possible). Device driver code has no need for the LPC facility.
The I/O Manager is an Executive component that is implemented with a series of kernel-mode routines that present a uniform abstraction to user-mode processes for I/O operations. One goal of the I/O Manager is to make all I/O access from user mode device-independent. It should not matter (much) to a user process whether it is accessing a keyboard, a communication port, or a disk file.
The I/O Manager presents requests from user-mode processes to device drivers in the form of an I/O Request Packet (IRP). The IRP represents a work order, usually
by the I/O Manager, that is presented to a device driver. It is the job of device drivers to carry out the
work of an IRP. Much of the remainder of this book is devoted to the proper care and processing of IRPs by device driver code.
In effect, the I/O Manager serves as an interface layer between usermode code and device drivers. It is therefore the most important block of code that a device driver must interact with during operation.
ACTIVE DIRECTORY SERVICE
The Active Directory Service is somewhat new to Windows 2000. It provides a network-wide namespace for system resources. Previously, the internal names used to identify system resources (disk drive names, printer names, user names, file
) were managed within a restricted space of the OS. It was the responsibility of other OS components (e.g., the networking services) to
names across different protocols.
The Active Directory is now a uniform, secure, and standard way to identify system resources. It is based on a hierarchical scheme (
defined by a schema) whereby entities are categorized into organization units (OUs), trees, and forests.
EXTENSIONS TO THE BASE OPERATING SYSTEM
Although the Executive components of Windows 2000 define and implement core services of the OS, it might be interesting to note that these services are not directly exposed to user-mode applications. Instead, Microsoft defines several Application Programming Interfaces (APIs) that user-mode code treats as abstractions of OS services. These APIs form different
that application code live within. Currently, the following environmental subsystems are included with Windows 2000.
The Win32 subsystem is the native-mode API of Windows 2000. All other environmental subsystems rely upon this subsystem to perform their work. All new Windows 2000 applications (and indeed, most ported ones as well) rely on the Win32 subsystem for their environment. Because of its importance (and interesting implementation), this subsystem is described in more detail in the next section.
The Virtual DOS Machine (VDM) subsystem provides a 16-bit MSDOS environment for old-style DOS applications. Despite its promise of compatibility, many existing 16-bit DOS programs do not operate properly. This is due to Microsoft's conservative and safe approach that
device (and other system resources) access. Attempts to directly access these resources results in intervention from the OS that provides safe, but not always faithful, results.
The Windows on Windows (WOW) subsystem supports an environment for old-style 16-bit Windows applications (i.e., Windows 3.X programs). Interestingly, each 16-bit program runs as a separate thread within the address space of a single WOW process. Multiple WOWs can be spawned, but 16-bit Windows applications are then prohibited from sharing resources.
The POSIX subsystem provides API support for Unix-style applications that conform to the POSIX 1003.1 source code standard. Unfortunately, this subsystem has not proved
for hosting the ports of many (most) Unix-style applications. As such, most Unix applications are ported by rewriting for the Win32 environment.
The OS/2 subsystem creates the execution environment for 16-bit OS/2 applications -at least those that do not rely on the Presentation Manager (PM) services of OS/2. This subsystem is available only for the Intel (x86) version of Windows 2000.
A given application is tightly coupled to exactly one environmental subsystem. Applications cannot make API calls to other environments. Also, only the Win32 subsystem is native -other subsystems emulate their environments and therefore experience various degrees of performance degradation compared to native Win32. Their purpose is compatibility, not speed.
Environmental subsystems are
implemented as separate user-mode processes. They launch as needed to support and host user-mode processes. The environmental subsystem becomes the
for the usermode
. Each request from a client is passed, using the Local Procedure Call Executive component, to the appropriate server process. The server process (i.e., the environmental subsystem) either performs the work to fulfill the request directly or it, in
, makes a request of the appropriate Executive component.
THE WIN32 SUBSYSTEM
As the native API for Windows 2000, the Win32 environmental subsystem is responsible for
The Graphical User Interface (GUI) seen by users of the system. It implements and exposes viewable windows, dialogs, controls, and an overall style for the system.
Console I/O including keyboard, mouse, and display for the entire system, including other subsystems.
Implementation of the Win32 API, which is what applications and other subsystems use to interact with the Executive.
Because the Win32 Subsystem holds special status within the system and because of its inherent requirement for high performance, this subsystem is implemented differently from any of the other subsystems. In particular, the Win32 subsystem is split into some components that execute in user mode and some that execute in kernel mode. In general, the Win32 function can be divided into three categories.
USER functions that manage windows,
, dialogs, and controls.
GDI functions that perform drawing operations on physical devices (e.g., screens and printers).
KERNEL functions, which manage non-GUI resources such as processes, threads, files, and synchronization services. KERNEL functions map closely to system services of the Executive.
Since NT 4.0, USER and GDI functions have been moved to kernel mode. User processes that request GUI services are therefore sent directly to kernel-mode using the System Service Interface, an efficient process. Kernel-mode code that implements USER and GDI functions resides in a module called WIN32K.SYS. The USER and GDI kernel components are
in Figure 1.2.
USER and GDI kernel components
Conversely, KERNEL functions rely on a standard server process, CSRSS.exe (Client-Server Runtime Subsystem), to respond to user process requests. In turn, CSRSS traps into Executive code to complete the request for such functions.
In addition to the Environmental Subsystems, there are also key system components that are implemented as user mode processes. These include
The Security Subsystem, which manages local and remote security using a variety of processes and dynamic libraries. Part of the Active Directory work also resides within this logical subsystem.
The Service Control Manager (affectionately called the
, or SCM) manages services (daemon processes) and device drivers.
The RPC Locator and Service processes give support to applications distributed across the network. Through the use of remote procedure calls, an application can distribute its workload across several networked machines.