今天看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处理完的通知。
内核进程通信也太容易了哈,反正大家都是相同地址空间,一个全局变量,一个同步变量搞定哈。