今天看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处理完的通知。

内核进程通信也太容易了哈,反正大家都是相同地址空间,一个全局变量,一个同步变量搞定哈。