windows 内核原理与实现读书笔记之驱动程序初始化

  • Post author:
  • Post category:其他


I/O系统的初始化是在内核的阶段1初始化过程中完成的。主要函数是Phase1InitializationDiscard,它调用IoInitSystem 来初始化I/O系统。

IoInitSystem 初始化工作:

  1. 调用IopCreateObjectTypes ,创建7种类型对象:Adapter、DeviceHandler、Controller、Device、Driver、IoCompletion、File,并存放在相应的全局变量中。

WRK中的全局类型对象变量,如下表:

CmpKeyObjectType

ExWindowStationObjectType

ObpDeviceMapObjectType

DbgkDebugObjectType

IoAdapterObjectType

ObpDirectoryObjectType

ExCallbackObjectType

IoCompletionObjectType

ObpSymbolicLinkObjectType

ExDesktopObjectType

IoControllerObjectType

ObpTypeObjectType

ExEventObjectType

IoDeviceHandlerObjectType

PsJobType

ExEventPairObjectType

IoDriviceObjectType

PsProcessType

ExMutantObjectType

IoDriverObjectType

PsThreadType

ExpKeyedEventObjectType

IoFileObjectType

SeTokenObjectType

ExProfileObjectType

LpcPortObjectType

WmipGuidObjectType

ExSemaphoreObjectType

LpcWaitablePortObjectType

ExTimerObjectType

MmSectionObjectType

  1. 调用IopCreateRootDirectories ,在对象管理器的根目录下创建3个目录对象:\Driver、\FileSystem 、\FileSystem\Filters
  2. 调用IopInitializePlugPlayServices,执行即插即用管理器的阶段0初始化。
  3. 调用PoInitDriverServices,执行电源管理器的阶段0初始化
  4. 调用HalInitPnpDirver,执行HAL的即插即用总线驱动程序初始化
  5. 调用WMIInitialize,执行WMI的阶段0 初始化
  6. 再次调用IopInitializePlugPlayServices,执行即插即用管理器的阶段1初始化
  7. 调用IopInitialBootDrivers,初始化“引导-启动”类型的驱动类型
  8. 调用PpLastGoodDoBootProcessing,执行“最近一次的正确配置(LKG)”的处理
  9. 调用PsLocateSystemDll,初始化系统DLL(ntdll.dll),并映射到System进程中
  10. 调用IopInitializeSystemDrivers,加载“系统-启动”类型的驱动程序,并对它们进行初始化
  11. 调用IopCallDriverReinitializationRoutines,处理需要重新初始化的驱动程序
  12. 调用IopReassignSystemRoot,将系统根目录(\SystemRoot)替换成NT路径名,这是一个符号连接(symbolic link)名称
  13. 调用IopProtectSystemPartition,保护系统分区
  14. 调用IoAssignDriveLetters,为磁盘分区和CD-ROM驱动器分配DOS驱动器字母
  15. 再次调用WMII逆天李泽,执行WMI的阶段1初始化
  16. 再次调用PoInitDriverServices,执行电源管理器的阶段1初始化

Windows 的每一个驱动程序(和服务)在安装是都被指定了一个启动类型,存放在注册表中。

启动类型如下:

#define SERVICE_BOOT_START             0x00000000
#define SERVICE_SYSTEM_START           0x00000001
#define SERVICE_AUTO_START             0x00000002
#define SERVICE_DEMAND_START           0x00000003
#define SERVICE_DISABLED               0x00000004


在HKLM\System\CurrentControlSet\Serbices\<DriverName> 键的Start 值,表示启动类型。


4


种类型的驱动程序的加载和初始化过程。





引导-启动





类型的驱动程序是由系统加载器即ntldr程序,加载到系统空间种的,内核无需加载,直接初始化。这些驱动程序初始化过程是在IopInitializeBootDrivers中完成的,内部调用IopInitializeBuiltinDriver完成实际的初始化工作。原型如下:

NTSTATUS IopInitializeBuiltinDriver(
    IN PUNICODE_STRING DriverName,//驱动名称
    IN PUNICODE_STRING RegistryPath,//注册表键的路径
    IN PDRIVER_INITIALIZE DriverInitializeRoutine,//初始化程序例程
    IN PKLDR_DATA_TABLE_ENTRY DriverEntry,//加载参数块中的相应表项
    IN BOOLEAN IsFilter,是否为过滤驱动程序,“引导-启动”的驱动程序IsFilter为FALSE
    IN PDRIVER_OBJECT *Result //若初始化成功,则执行一个驱动程序对象
)


IopInitializeBuiltinDriver


基本流程如下:


  1. 根据参数中指定的驱动程序名称,创建一个驱动程序对象,其类型是IoInitSystem 已经注册的IoDriverObjectType

  2. 初始化该驱动程序对象,设置它的DriverInit为参数中指定的初始化例程

  3. 将驱动程序对象插入到当前进程(即System 进程)的句柄表中

  4. 搜索系统的已加载模块列表(全局变量PsLoadedModuleList),找到该驱动程序所在的模块项,并初始化驱动程序对象中与映像模块有关的域

  5. 将驱动程序的名称复制到驱动程序对象的名称缓冲区中

  6. 记录下驱动程序注册表键的名称

  7. 调用驱动程序的初始化函数(DriverEntry)

  8. 调用IopReadyDeviceObjects,将该驱动程序创建的设备对象设置成已初始化,从而可被其他驱动程序或客户访问

“系统-启动“类型的驱动程序初始化是在IopInitializeSystemDrivers 中完成的,内部调用CmGetSystemDriverList ,获得为SERVICE_SYSTEM_START的”Start“值,对尚未加载的驱动程序逐个调用IopLoadDriver,将其加载到系统地址空间,并执行初始化。

NTSTATUS IopLoadDriver(
    IN  HANDLE      KeyHandle, //驱动程序的注册表键值
    IN  BOOLEAN     CheckForSafeBoot, //是否要检查安全模式
    IN  BOOLEAN     IsFilter,//是否为过滤驱动程序
    OUT NTSTATUS   *DriverEntryStatus  //返回参数
    )


IopLoadDriver


基本流程如下:


  1. 根据参数中指定的注册表键,构造出驱动程序的全路径名

  2. 调用MmLoadSystemImage,将驱动程序加载到系统地址空间

  3. 创建一个驱动程序对象,初始化该对象的域

  4. 将该对象插入到当前进程的句柄表中

  5. 完成对象成员初始化后,调用驱动程序的初始化函数,即DriverInit,并将驱动程序对象和注册表路径传递进去


IopLoadDriver


和IopInitializeBuiltinDriver 都必须在System 进程中运行。





自动-启动





类型的启动程序,即注册表中





Start





值为SERVICE_AUTO_START的驱动程序,由SCM(服务控制管理器,Service Control manager,services.exe 进程)加载,通过NtLoadDriver 来完成。

NTSYSCALLAPI NTSTATUS NTAPI NtLoadDriver (
    __in PUNICODE_STRING DriverServiceName  //待加载的驱动程序在注册表中的名称
    );


如果用户模式调用NtLoadDriver,则检查当前进程是否由加载驱动的特权。


若是System 进程,则直接调用IopLoadUnloadDriver 完成驱动程序初始化。





按需-启动





类型的驱动程序是通过SCM来加载和初始化的。



版权声明:本文为maomao171314原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。