I. Background introduction
1.1 Composition of Windows NT operating system
1.1.1 User mode (UserMode) and kernel mode (KernelMode)
Starting from Intel80386, for security And stability considerations, the series of CPUs can run four different privilege levels from high to low ring0~ring3, and provide four levels of protection for the data. Code running at a lower level cannot arbitrarily call high-level code and access higher-level data, and only the code of the ring0 layer can directly access physical hardware. Since Windows NT is a multi-platform operating system, it only takes advantage of the two operating levels of the CPU in order to be compatible with other platforms. One is called kernel mode, corresponding to the 80x86 ring0 layer, the core part of the operating system, including device drivers running in this mode; the other is called user mode, corresponding to the 80x86 ring3 layer, the user interface part of the operating system and All user applications run at this level.
1.1.2 Structure of Windows NT Operating System
Figure 1 briefly describes the system components of Windows NT.
As can be seen from the figure, there is a hardware abstraction layer (HardwareAbstractionLayer) between the physical hardware (Hardware) and the system kernel (Kernel), which shields the differences between different platform hardware. Provides a unified interface to the upper layers of the operating system. As we can see from the figure, the device driver (DeviceDriver) is surrounded by the I/O Manager (I/OManager), that is, the communication between the driver and the upper layer of the operating system must pass through the I/O Manager. This brings great convenience to the writing of the driver, because many tasks such as receiving user requests, exchanging data with user programs, memory mapping, hooking interrupts, synchronization, etc. are all handled by the I/O Manager. .
1.1.3 Classification of Windows NT device drivers
According to whether the hardware is directly operated, the drivers can be divided into two categories: kernel mode drivers and dedicated drivers.
The kernel mode driver directly performs port access, interrupt response, and DMA transfer to the hardware according to the hardware communication protocol. It includes: serial, parallel port, keyboard, file system, SCSI, network and other drivers; dedicated drivers include video, print, multimedia, virtual DOS and other drivers, they are very different in implementation. The work I did during my internship and the discussion below in this article were limited to kernel mode drivers.
p>1.2Windows NT kernel mode device driver structure and operation
In general, the device driver task has two main: first, accept read and write requests from the user program Transfer the user's data to the device or transfer the data received from the device to the user. Second, poll the device or process the interrupt request from the device to complete the data transfer.
1.2.1 Driver and User Program Communication
The I/O Manager abstracts each device into a file, so in the Win32 user program, only the following A simple file manipulation API function can communicate with a device in the driver (note that one driver can drive multiple devices):
Function name function
CreateFile opens a device and is ready to transfer data. Returns a handle associated with the device.
CloseHandle closes a device opened by CreateFile.
ReadFile reads data from the device.
WriteFile writes data to the device.
DeviceIoControl performs some custom operations on the device, such as changing settings.
This is the entry point for each device driver, which is automatically called by the system each time the program starts. Most of the device initialization work is done in this process. This includes setting up the entry for the process that responds to various user requests, so that the I/O Manager can know which procedures should be called when the user's request for opening, closing, reading, and writing comes. Only the name of the procedure "DriverEntry" is fixed in the driver. All the processes listed below are registered with the system by this procedure.
If the driver does not respond to any requests, a DriverEntry process can constitute a working driver.
1.2.3Unload and ShutDown Processes
The Unload process is responsible for doing some necessary processing before the driver is stopped. For example, release resources, record final status, and so on. The ShutDown procedure is called when the system is about to shut down. The difference with the former is that no resources are released.
1.2.4DispatchOpen and DispatchClose Process
These two procedures are called when the user calls CreateFile and CloseHandle, to prepare for the upcoming read and write operations, or to do some necessary processing after reading and writing.
1.2.5DispatchRead, DispatchWrite and StartIo Procedures
These first two procedures are called when the user calls ReadFile and WriteFile. They do some work to verify the legitimacy of the user request, and then start a process called StartIo to start the actual data transfer between the hardware. The I/O Manager also provides them with a pointer to the user buffer through the IRP. For details on the number of exchanges with the user program, see 1.3.2
1.2.6 Accepting Customs Others Requests
These two procedures are called when the user calls DeviceIoControl. It obtains the user's request number through the IRP, and a pointer to the user buffer, which can communicate with the user program.
1.2.7 Interrupt Processing (ISR)
These procedures are called by the system when an interrupt occurs.
These procedures are used to accomplish some of the tasks of higher run level processes (such as interrupt handling) at lower run levels. For details, please refer to 1.3.3
p>1.3 implementation details
1.3.1 kernel code running level
WindowsNT is its kernel The code for the pattern is assigned a different level. On the same CPU, low-level processes can be interrupted by any higher level process. The levels are listed from low to high as follows:
The process of running the level name at this level
PASSIVE_LEVELDriverEntry, Unload, ShutDown, DispatchXxx.
APC_LEVEL In some special cases, drivers for large storage devices run at this level.
DISPATCH_LEVELStartIo, AdapterControl, ControllerControl, IoTimer, Dpc.
DIRQLs various interrupt handlers. Table 2
1.3.2 Several Objects
i) I/O Request Packet (IRP)
Each I/O Manager receives a request from the user Create a structure and pass it as a parameter to the driver's DispatchXxx, StartIo process. The structure stores information such as the type of the request, the first address of the user buffer, and the length of the data requested by the user. After the driver has processed the request, it also adds information about the processing result to the structure, calls IoCompleteRequest to return it to the I/O Manager, and the user program's request returns.
This object needs to be created when the Dpc process is to be used in the driver. See 1.3.3 for specific effects.
iii) Driver Object (DriverObject)
This object is created by the I/O Manager when the driver is started, and the procedure entry for the program to process various requests is saved. A linked list of all device objects that are driven, and the like.
iv)Device Objects (DeviceObject)