Understand and use the NT driver's execution context (1)
One of the most important concepts of understanding the Windows NT driver is the "execution context" at which the driver is running. Understand and carefully apply this concept to help you build faster, more efficient drivers.
An important concept in the NT standard kernel mode driver program is "context" at a particular driver function execution. Traditionally, file system developers are most concerned about this problem, but all types of NT core mode drivers will benefit from the deep understanding of the execution context. Carefully use the concept of executing context to help build a driver design of higher performance, lower overhead.
In this article, we will explore the concept of performing context. As a demonstration for the concept, this article describes a driver that allows the user program to run and owns all permissions in kernel mode. In this process, we will also discuss the actual usage of the context in the device driver.
What is context?
When referring to a context of a routine, we refer to its threads and processes execution environments. In NT, this environment is established by the current thread environment block (TEB) and process environment block (PEB). The context includes the setting of the virtual memory (tell us the physical memory page to the virtual memory address), the handle conversion (because the handle is a process based), the dispatcher information, the stack, and the setup of the general and floating point registers. When we asked a specific kernel routine to run in that context, we are actually asking, "That is the current thread established by the (NT core) dispatcher?" Because each thread only belongs to a process, the current thread is determined. Current process. The current thread and the current process determine all things that uniquely identify threads and processes (handle, virtual memory, scheduler status, and register).
Virtual memory may be the most useful aspects of the kernel mode driver writer in the context. I still remember that the NT maps the user process to the low 2GB of the virtual address space, map the code of the operating system itself to the high 2GB of the virtual address space? When the thread in a user process is executed, its virtual address range is 0 to 2GB, and all addresses above 2GB are set to "No Access" to prevent the user from directly accessing the operating system code and structure. When the operating system code is executed, its virtual address range is 2 to 4GB, and the address of the current user process (if any) is mapped to 0 to 2GB. In NT3.51 and V4.0, the code mapped to a high 2GB address is never changed. However, the code that maps to the low 2GB address will change, depending on the current process.
Further, in the special virtual internal memory policy, a legal virtual address X (X is less than or equal to 2GB) and the kernel virtual address X correspond to the same physical memory location. Of course, this can only be set up when the process P is the current process and (and therefore) the physical page of the process P mapped to the low 2GB virtual address space of the operating system. Another saying of the above sentence is that "this only can be established when P is the current process." So in the same process context, the user virtual address and 2GB of kernel virtual addresses point to the same physical location.
Another aspect of the other in the context allows the kernel mode driver writer, is the thread dispatch context. When a thread is waiting (for example, by emitting Win32 functions WaitForsingleObject (...), the scheduling context object is used to store information about the object waiting for the thread definition. When a unmetable waiting is issued, this thread is removed from the ready queue, and only when waiting for satisfaction (specified dispatcher object being excited), it is moved back.
The context also affects the use of the handle. Because the handle is for a specific process, the handle created in a process is not used in other processes.
Different types of context
The routine of the kernel mode runs in one of the three different contexts:
- System process context
- Specific user threads (and processes) context
- Any user thread (and processes) context
During the execution, each part of each core mode driver may run one of three contexts above. For example, a driverentry (...) function of a driver is always running in the context of the system process. The system process context has no user context (so there is no TEB), and no user process is mapped to the low 2GB of the kernel virtual address space. On the other hand, DPCS (eg, a driver is a DPC or timer expiration function of the ISR service) runs in the context of any user thread. This inventor can be "current" thread in a DPC execution process, so any user process can be mapped to the low 2GB of the kernel virtual address space.