今天看NT内核源码,有点小小心得,分享一下
===========================
我们都知道,驱动程序的入口DriverEntry是在SYSTEM进程环境中执行的,不知大家注意过没有:
第一,DriverEntry问什么要在SYSTEM中运行
第二,DriverEntry是如何实现在SYSTEM中运行的呢?
要回答者两个问题,先请大家看NtLoadDriver中的一段代码:
代码:
//
// Because drivers may wish to create a system thread and execute in
// its context, the remainder of this service must be executed in the
// context of the primary system process. This is accomplished by
// queueing a request to one of the EX worker threads and having it
// invoke the I/O system routine to complete this work.
//
// Fill in a request packet and queue it to the worker thread then, so
// that it can actually do the load.
//
KeInitializeEvent( &loadPacket.Event, NotificationEvent, FALSE );
loadPacket.DriverObject = (PDRIVER_OBJECT) NULL;
loadPacket.DriverServiceName = &driverServiceName;
if (PsGetCurrentProcessByThread(CurrentThread) == PsInitialSystemProcess) {
//
// If we are already in the system process, just use this thread.
//
IopLoadUnloadDriver(&loadPacket);
} else {
ExInitializeWorkItem( &loadPacket.WorkQueueItem,
IopLoadUnloadDriver,
&loadPacket );
ExQueueWorkItem( &loadPacket.WorkQueueItem, DelayedWorkQueue );
KeWaitForSingleObject( &loadPacket.Event,
UserRequest,
KernelMode,
FALSE,
(PLARGE_INTEGER) NULL );
}
对这两个问题,程序解释的很清楚,由于驱动程序在初始化时有可能要创建在SYSTEM进程环境中运行的系统线程,所以DriverEntry必须运行在SYSTEM进程环境中,
由于NtLoadDriver既可能在SYSTEM进程中调用,也可能在其他进程中调用,所以NtLoadDriver会判断当前进程是否是SYSTEM进程,如果不是,就将 IopLoadUnloadDriver例程的调用任务封装成一个任务包,通过ExQueueWorkItem加入了一个队列 ExWorkerQueue[DelayedWorkQueue] 中,SYSTEM进程中有一个工作线程,会周期查看该队列,如果不空,就一个一个任务包取出来处理,每处理完一个任务包会将其中的event对象设置为有效,NtLoadDriver就通过任务包中的event得到IopLoadUnloadDriver处理完的通知。
内核进程通信也太容易了哈,反正大家都是相同地址空间,一个全局变量,一个同步变量搞定哈。