用有限的几句话就舒舒服服的建立起对驱动对象和设备对象的概念是不可能的。刚开始是一片模糊,了解的多了,慢慢就清楚。下面的内容会使你对他们了解的清楚些。

为了后面的叙述方便,首先列出驱动对象和设备对象的结构。

驱动对象结构 DRIVER_OBJECT ,定义如下

struct _DRIVER_OBJECT (sizeof=168)
+00 int16 Type
+02 int16 Size
+04 struct _DEVICE_OBJECT *DeviceObject
+08 uint32 Flags
+0c void *DriverStart
+10 uint32 DriverSize
+14 void *DriverSection
+18 struct _DRIVER_EXTENSION *DriverExtension
+1c struct _UNICODE_STRING DriverName
+1c uint16 Length
+1e uint16 MaximumLength
+20 uint16 *Buffer
+24 struct _UNICODE_STRING *HardwareDatabase
+28 struct _FAST_IO_DISPATCH *FastIoDispatch
+2c function *DriverInit
+30 function *DriverStartIo
+34 function *DriverUnload
+38 function *MajorFunction[28]

DDK 中有对于一些域的说明

[00] IRP_MJ_CREATE
[01] IRP_MJ_CREATE_NAMED_PIPE
[02] IRP_MJ_CLOSE
[03] IRP_MJ_READ
[04] IRP_MJ_WRITE
[05] IRP_MJ_QUERY_INFORMATION
[06] IRP_MJ_SET_INFORMATION
[07] IRP_MJ_QUERY_EA
[08] IRP_MJ_SET_EA
[09] IRP_MJ_FLUSH_BUFFERS
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION
[0b] IRP_MJ_SET_VOLUME_INFORMATION
[0c] IRP_MJ_DIRECTORY_CONTROL
[0d] IRP_MJ_FILE_SYSTEM_CONTROL
[0e] IRP_MJ_DEVICE_CONTROL
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL
[10] IRP_MJ_SHUTDOWN
[11] IRP_MJ_LOCK_CONTROL
[12] IRP_MJ_CLEANUP
[13] IRP_MJ_CREATE_MAILSLOT
[14] IRP_MJ_QUERY_SECURITY
[15] IRP_MJ_SET_SECURITY
[16] IRP_MJ_POWER
[17] IRP_MJ_SYSTEM_CONTROL
[18] IRP_MJ_DEVICE_CHANGE
[19] IRP_MJ_QUERY_QUOTA
[1a] IRP_MJ_SET_QUOTA
[1b] IRP_MJ_PNP

struct _DRIVER_EXTENSION (sizeof=24)
+00 struct _DRIVER_OBJECT *DriverObject
+04 function *AddDevice
+08 uint32 Count
+0c struct _UNICODE_STRING ServiceKeyName
+0c uint16 Length
+0e uint16 MaximumLength
+10 uint16 *Buffer
+14 struct _IO_CLIENT_EXTENSION *ClientDriverExtension

设备对象结构 DEVICE_OBJECT ,定义如下

struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type
+02 uint16 Size
+04 int32 ReferenceCount
+08 struct _DRIVER_OBJECT *DriverObject
+0c struct _DEVICE_OBJECT *NextDevice
+10 struct _DEVICE_OBJECT *AttachedDevice
+14 struct _IRP *CurrentIrp
+18 struct _IO_TIMER *Timer
+1c uint32 Flags
+20 uint32 Characteristics
+24 struct _VPB *Vpb
+28 void *DeviceExtension
+2c uint32 DeviceType
+30 char StackSize
+34 union __unnamed62 Queue
+34 struct _LIST_ENTRY ListEntry
+34 struct _LIST_ENTRY *Flink
+38 struct _LIST_ENTRY *Blink
+34 struct _WAIT_CONTEXT_BLOCK Wcb
+34 struct _KDEVICE_QUEUE_ENTRY WaitQueueEntry
+34 struct _LIST_ENTRY DeviceListEntry
+34 struct _LIST_ENTRY *Flink
+38 struct _LIST_ENTRY *Blink
+3c uint32 SortKey
+40 byte Inserted
+44 function *DeviceRoutine
+48 void *DeviceContext
+4c uint32 NumberOfMapRegisters
+50 void *DeviceObject
+54 void *CurrentIrp
+58 struct _KDPC *BufferChainingDpc
+5c uint32 AlignmentRequirement
+60 struct _KDEVICE_QUEUE DeviceQueue
+60 int16 Type
+62 int16 Size
+64 struct _LIST_ENTRY DeviceListHead
+64 struct _LIST_ENTRY *Flink
+68 struct _LIST_ENTRY *Blink
+6c uint32 Lock
+70 byte Busy
+74 struct _KDPC Dpc
+74 int16 Type
+76 byte Number
+77 byte Importance
+78 struct _LIST_ENTRY DpcListEntry
+78 struct _LIST_ENTRY *Flink
+7c struct _LIST_ENTRY *Blink
+80 function *DeferredRoutine
+84 void *DeferredContext
+88 void *SystemArgument1
+8c void *SystemArgument2
+90 uint32 *Lock
+94 uint32 ActiveThreadCount
+98 void *SecurityDescriptor
+9c struct _KEVENT DeviceLock
+9c struct _DISPATCHER_HEADER Header
+9c byte Type
+9d byte Absolute
+9e byte Size
+9f byte Inserted
+a0 int32 SignalState
+a4 struct _LIST_ENTRY WaitListHead
+a4 struct _LIST_ENTRY *Flink
+a8 struct _LIST_ENTRY *Blink
+ac uint16 SectorSize
+ae uint16 Spare1
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension
+b4 void *Reserved

DDK 中有对于一些域的说明

struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type
+02 uint16 Size
+04 struct _DEVICE_OBJECT *DeviceObject
+08 uint32 PowerFlags
+0c *Dope
+10 uint32 ExtensionFlags
+14 void *DeviceNode
+18 struct _DEVICE_OBJECT *AttachedTo
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink
+20 struct _LIST_ENTRY *Blink

有一个载入内存的驱动程序文件,就会有一个驱动对象(DRIVER_OBJECT)。

比如,驱动 i8042prt 是在系统初始化阶段,IO 管理器调用函数 nt!IopLoadDriver 载入的。nt!IopLoadDriver 读取注册表,获得驱动程序文件 i8042prt.SYS 的路径,将这个文件载入内存。之后会调用 nt!ObCreateObject 创建一个驱动对象,并初始化这个驱动对象。

设备对象(DEVICE_OBJECT)由驱动创建。一个驱动可以创建多个设备对象(DEVICE_OBJECT)。通过驱动对象(DRIVER_OBJECT),可以找到由该驱动创建的所有设备对象(DEVICE_OBJECT)。一个驱动创建的所有设备对象(DEVICE_OBJECT)链成一条链,该驱动的驱动对象(DRIVER_OBJECT)可以找到这个链。一个设备对象(DEVICE_OBJECT)也可以找到创建它的驱动的驱动对象(DRIVER_OBJECT)。下面我们使用 WinDbg 实际观察驱动 i8042prt 的情况,i8042prt 是完成 ps/2 键盘驱动主要功能的驱动程序。

在这里我们先做个说明,对于同时插有 ps/2 键盘和 ps/2 鼠标的计算机上, i8042prt 会创建两个设备对象,一个用于键盘,一个用于鼠标。

首先我们从命名对象地址空间,找到 i8042prt 的 DRIVER_OBJECT 的地址

kd> !object \driver\i8042prt
Object: fe4f69f0 Type: (fe4ec3e0) Driver
ObjectHeader: fe4f69d8
HandleCount: 0 PointerCount: 5
Directory Object: fe51bf30 Name: i8042prt

下面我们看 i8042prt 的 DRIVER_OBJECT 中的内容

kd> !strct driver_object fe4f69f0
struct _DRIVER_OBJECT (sizeof=168)
+00 int16 Type = 0004
+02 int16 Size = 00a8
+04 struct _DEVICE_OBJECT *DeviceObject = FE4D3BA0
// 注意 DeviceObject 链上的第一个设备对象
+08 uint32 Flags = 00000012
+0c void *DriverStart = FE1BD000
+10 uint32 DriverSize = 00021000
+14 void *DriverSection = FE4F6CC8
+18 struct _DRIVER_EXTENSION *DriverExtension = FE4F6A98
+1c struct _UNICODE_STRING DriverName
+1c uint16 Length = 0020
+1e uint16 MaximumLength = 0020
+20 uint16 *Buffer = E127FE88
+24 struct _UNICODE_STRING *HardwareDatabase = 80541FC0
+28 struct _FAST_IO_DISPATCH *FastIoDispatch = 00000000
+2c function *DriverInit = FE1D8000
+30 function *DriverStartIo = FE1BF444
+34 function *DriverUnload = FE1CB920
+38 function *MajorFunction[28] = FE1CB000
80425354
FE1CB14E
80425354
80425354
80425354
80425354
80425354
80425354
FE1BE558
80425354
80425354
80425354
80425354
FE1CB243
FE1BE667
80425354
80425354
80425354
80425354
80425354
80425354
FE1D2C63
FE1D3633
80425354
80425354
80425354
FE1D1BFB

我们看到了 DeviceObject 上的第一个设备对象的地址 FE4D3BA0 ,我们使用 WinDbg 的 !devobj 命令,来获得一些信息

kd> !devobj FE4D3BA0
Device object (fe4d3ba0) is for:
\Driver\i8042prt DriverObject fe4f69f0
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt fe4d3c58 DevObjExt fe4d3ed8
ExtensionFlags (0xc0000000)
Unknown flags 0xc0000000
AttachedDevice (Upper) fe4d3a60 \Driver\vmmouse
AttachedTo (Lower) fe4dd610 \Driver\ACPI
Device queue is not busy.

从获得的信息来看,这是用于鼠标的那个设备对象,下面我们看这个设备对象 DEVICE_OBJECT 中的具体内容

kd> !strct device_object FE4D3BA0
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 0338
+04 int32 ReferenceCount = 00000000
+08 struct _DRIVER_OBJECT *DriverObject = FE4F69F0
// 正是 \Driver\i8042prt 的驱动对象的地址
+0c struct _DEVICE_OBJECT *NextDevice = FE4F5020
// DeviceObject 链的下一个
+10 struct _DEVICE_OBJECT *AttachedDevice = FE4D3A60
+14 struct _IRP *CurrentIrp = 00000000
...

我们看到了设备对象 +0c struct _DEVICE_OBJECT *NextDevice 处是 DeviceObject 链上的下一个设备对象的地址,值为 FE4F5020 ,我们使用 WinDbg 的 !devobj 命令,来获得一些信息

kd> !devobj FE4F5020
Device object (fe4f5020) is for:
\Driver\i8042prt DriverObject fe4f69f0
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt fe4f50d8 DevObjExt fe4f5358
ExtensionFlags (0xc0000000)
Unknown flags 0xc0000000
AttachedDevice (Upper) fe4f5df0 \Driver\Kbdclass
AttachedTo (Lower) fe4dd730 \Driver\ACPI
Device queue is not busy.

从获得的信息来看,这是用于键盘的那个设备对象,下面我们看这个设备对象 DEVICE_OBJECT 中的具体内容

kd> !strct device_object FE4F5020
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 0338
+04 int32 ReferenceCount = 00000000
+08 struct _DRIVER_OBJECT *DriverObject = FE4F69F0
// 正是 \Driver\i8042prt 的驱动对象的地址
+0c struct _DEVICE_OBJECT *NextDevice = 00000000
// 为空,表明链结束了。
+10 struct _DEVICE_OBJECT *AttachedDevice = FE4F5DF0
+14 struct _IRP *CurrentIrp = 00000000
...

我们观察初始化时,看到 i8042prt 调用 IoCreateDevice 创建设备对象,并且 IoCreateDevice 会把新创建的这个设备对象,链入驱动的设备链中。

现在我们对驱动对象和设备对象之间的联系,做一个总结,

驱动调用 IoCreateDevice 创建设备对象,一个驱动创建的所有设备对象链成一个链,这个链以空表示结束。驱动对象通过 +04 struct _DEVICE_OBJECT *DeviceObject 可以找到这个链。设备对象通过 +0c struct _DEVICE_OBJECT *NextDevice 链在一起。设备对象通过 +08 struct _DRIVER_OBJECT *DriverObject 可以找到创建它的驱动的驱动对象。

下面我们来讲讲设备栈。一个物理设备的驱动任务,通常由几个驱动程序一层一层的共同完成。每层一个设备对象,他们联系在一起,组成一个设备栈。一个设备栈上的设备对象,从上自下,联系在一起。从下自上,也联系在一起。我们以 ps/2 键盘驱动为例,使用 WinDbg 来观察它的设备栈,以及他们如何联系在一起。

ps/2 键盘驱动的设备栈,大概就是这个样子

kd> !devstack fe4f5020
!DevObj !DrvObj !DevExt ObjectName
fe4f5df0 \Driver\Kbdclass fe4f5ea8 KeyboardClass0
> fe4f5020 \Driver\i8042prt fe4f50d8
fe4dd730 \Driver\ACPI fe507468 0000000e
!DevNode fe4fed68 :
DeviceInst is "ACPI\PNP0303\4&5289e18&0"
ServiceName is "i8042prt"

最上面的 DEVICE_OBJECT 地址为 fe4f5df0,属于驱动 \Driver\Kbdclass
中间的 DEVICE_OBJECT 地址为 fe4f5020,属于驱动 \Driver\i8042prt
最下面的 DEVICE_OBJECT 地址为 fe4dd730,属于驱动 \Driver\ACPI

下面我们看这3个设备对象,如何联系在一起。

最上面一层的 DEVICE_OBJECT

kd> !devobj fe4f5df0
Device object (fe4f5df0) is for:
KeyboardClass0 \Driver\Kbdclass DriverObject fe4f6330
Current Irp fe43a1c8 RefCount 0 Type 0000000b Flags 00002044
DevExt fe4f5ea8 DevObjExt fe4f5fd8
ExtensionFlags (0000000000)
AttachedTo (Lower) fe4f5020 \Driver\i8042prt
Device queue is busy -- Queue empty.
看到这个设备对象有名字,叫 KeyboardClass0 ,属于驱动 Kbdclass

kd> !strct device_object fe4f5df0
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 01e8
+04 int32 ReferenceCount = 00000000
+08 struct _DRIVER_OBJECT *DriverObject = FE4F6330
// 正是 kbdclass 的 DRIVER_OBJECT 的地址
+0c struct _DEVICE_OBJECT *NextDevice = 00000000
+10 struct _DEVICE_OBJECT *AttachedDevice = 00000000
// 为空结束,表示上面没有其它设备对象了
+14 struct _IRP *CurrentIrp = FE43A1C8
...
+ae uint16 Spare1 = 0000
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension = FE4F5FD8
// 它的 DEVOBJ_EXTENSION 在 FE4F5FD8
+b4 void *Reserved = 00000000

kd> !strct DEVOBJ_EXTENSION FE4F5FD8
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type = 000d
+02 uint16 Size = 0000
+04 struct _DEVICE_OBJECT *DeviceObject = FE4F5DF0
+08 uint32 PowerFlags = 00000010
+0c *Dope = 00000000
+10 uint32 ExtensionFlags = 00000000
+14 void *DeviceNode = 00000000
+18 struct _DEVICE_OBJECT *AttachedTo = FE4F5020
// 下面一层的设备对象为 FE4F5020
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink = 00000000
+20 struct _LIST_ENTRY *Blink = 00000000

中间层的 DEVICE_OBJECT

kd> !devobj fe4f5020
Device object (fe4f5020) is for:
\Driver\i8042prt DriverObject fe4f69f0
Current Irp 00000000 RefCount 0 Type 00000027 Flags 00002004
DevExt fe4f50d8 DevObjExt fe4f5358
ExtensionFlags (0xc0000000)
Unknown flags 0xc0000000
AttachedDevice (Upper) fe4f5df0 \Driver\Kbdclass
AttachedTo (Lower) fe4dd730 \Driver\ACPI
Device queue is not busy.
看到这个设备对象没有名字,属于驱动 i8042prt

kd> !strct device_object fe4f5020
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 0338
+04 int32 ReferenceCount = 00000000
+08 struct _DRIVER_OBJECT *DriverObject = FE4F69F0
// 正是 i8042prt 的 DRIVER_OBJECT 的地址
+0c struct _DEVICE_OBJECT *NextDevice = 00000000
+10 struct _DEVICE_OBJECT *AttachedDevice = FE4F5DF0
// 上面一层的设备对象
+14 struct _IRP *CurrentIrp = 00000000
...
+ae uint16 Spare1 = 0001
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension = FE4F5358
// 它的 DEVOBJ_EXTENSION 在 FE4F5358
+b4 void *Reserved = 00000000

kd> !strct DEVOBJ_EXTENSION FE4F5358
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type = 000d
+02 uint16 Size = 0000
+04 struct _DEVICE_OBJECT *DeviceObject = FE4F5020
+08 uint32 PowerFlags = 00000000
+0c *Dope = 00000000
+10 uint32 ExtensionFlags = c0000000
+14 void *DeviceNode = 00000000
+18 struct _DEVICE_OBJECT *AttachedTo = FE4DD730
// 下面一层的设备对象
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink = 00000000
+20 struct _LIST_ENTRY *Blink = 00000000

最下面一层的 DEVICE_OBJECT

kd> !devobj fe4dd730
Device object (fe4dd730) is for:
0000000e \Driver\ACPI DriverObject fe4e8ad0
Current Irp 00000000 RefCount 1 Type 00000032 Flags 00001040
DevExt fe507468 DevObjExt fe4dd7e8 DevNode fe4fed68
ExtensionFlags (0000000000)
AttachedDevice (Upper) fe4f5020 \Driver\i8042prt
Device queue is not busy.
看到这个设备对象有名字,叫 0000000e ,属于驱动 acpi

kd> !strct device_object fe4dd730
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type = 0003
+02 uint16 Size = 00b8
+04 int32 ReferenceCount = 00000001
+08 struct _DRIVER_OBJECT *DriverObject = FE4E8AD0
// 正是 acpi 的 DRIVER_OBJECT 的地址
+0c struct _DEVICE_OBJECT *NextDevice = FE4DD850
+10 struct _DEVICE_OBJECT *AttachedDevice = FE4F5020
// 上面一层的设备对象
+14 struct _IRP *CurrentIrp = 00000000
...
+ae uint16 Spare1 = 0001
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension = FE4DD7E8
// 它的 DEVOBJ_EXTENSION 在 FE4DD7E8
+b4 void *Reserved = 00000000

kd> !strct DEVOBJ_EXTENSION FE4DD7E8
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type = 000d
+02 uint16 Size = 0000
+04 struct _DEVICE_OBJECT *DeviceObject = FE4DD730
+08 uint32 PowerFlags = 00000010
+0c *Dope = 00000000
+10 uint32 ExtensionFlags = 00000000
+14 void *DeviceNode = FE4FED68
+18 struct _DEVICE_OBJECT *AttachedTo = 00000000
// 为空结束,表示下面没有其它设备对象了
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink = 00000000
+20 struct _LIST_ENTRY *Blink = 00000000

从上自下。\Device\KeyboardClass0(DRIVER_OBJECT 是 kbdclass)可以找到 没有名字地址为fe4f5020的DEVICE_OBJECT(DRIVER_OBJECT 是 i8042prt)。没有名字地址为fe4f5020的DEVICE_OBJECT(DRIVER_OBJECT 是 i8042prt)可以找到 \Device\0000000e(DRIVER_OBJECT 是 ACPI)。

从下自上。\Device\0000000e(DRIVER_OBJECT 是 ACPI) 可以找到 没有名字地址为fe4f5020的DEVICE_OBJECT(DRIVER_OBJECT 是 i8042prt)。没有名字地址为fe4f5020的DEVICE_OBJECT(DRIVER_OBJECT 是 i8042prt)可以找到 \Device\KeyboardClass0(DRIVER_OBJECT 是 ACPI)。

现在我们对设备栈上的设备对象之间的联系,做一个总结,

设备栈上的设备对象,从上自下,通过 DEVICE_OBJECT 的 DEVOBJ_EXTENSION 的 +18 struct _DEVICE_OBJECT *AttachedTo 联系在一起。
设备栈上的设备对象,从下自上,通过 DEVICE_OBJECT 的 +10 struct _DEVICE_OBJECT *AttachedDevice 联系在一起。

在观察键盘驱动的初始化过程中,我们看到了设备栈是如何建立起来的。
驱动 i8042prt ,驱动 kbdclass 分别调用 IoAttachDeviceToDeviceStack ,把自己相应的设备对象加入到键盘设备栈中。IoAttachDeviceToDeviceStack 会设置 DEVICE_OBJECT 的 DEVOBJ_EXTENSION 的 +18 struct _DEVICE_OBJECT *AttachedTo 和 DEVICE_OBJECT 的 +10 struct _DEVICE_OBJECT *AttachedDevice ,把两个对象联系在一起。并设置新加入的设备对象的 +30 char StackSize

转载于:https://www.cnblogs.com/sunkang/archive/2011/04/19/2038823.html

驱动对象-设备对象-设备栈相关推荐

  1. 驱动开发笔记5—驱动对象、设备对象、IRP和派遣函数

    文章目录 驱动对象 设备对象 IRP和派遣函数 IRP IRP类型 设置派遣函数 处理IRP 举例说明 设备读写方式 缓冲区方式读写 直接方式读写 其他方式读写 驱动对象 每个驱动程序都会有唯一的驱动 ...

  2. Windows驱动开发 - 设备对象初步学习

    新建一个myhellodevice.c: 代码如下:makefile和sources如前文: #include <ntddk.h>#define NTDEVICE_NAME_STRING ...

  3. Linux通常把设备对象抽象为,linux 设备模型(1)

    设备模型(一) 一.概述 从2.6内核引入了sysfs文件系统,与proc, devfs, devpty同类别,属于虚拟的文件系统.目的是展示设备驱动模型中各组件的层次关系,第一层目录:block, ...

  4. 波形捕捉:(2)创建捕捉设备对象

    创建"捕捉设备对象"  你可以通过调用 DirectSoundCaptureCreate8 或 DirectSoundFullDuplexCreate8 函数来创建一个捕捉设备对象 ...

  5. DirectSound学习笔记(2):创建设备对象

    创建设备对象 创建设备对象最简单的方式是使用 DirectSoundCreate8 函数.函数的第一个参数指定了与对象关联的设备的GUID.你能够通过枚举设备获取这个GUID,也可以传递以下GUID中 ...

  6. IOT-OS之RT-Thread(七)--- I/O设备模型框架与PIN设备对象管理

    文章目录 一.I/O设备模型 1.1 I/O设备模型框架 1.2 I/O设备对象描述 1.3 I/O设备对象接口函数 二.PIN设备管理示例 2.1 PIN设备驱动框架层 2.2 PIN设备驱动层 2 ...

  7. IOT-OS之RT-Thread(十五)--- SDIO设备对象管理 + AP6181(BCM43362) WiFi模块

    文章目录 一.AP6181 Wi-Fi模块简介 1.1 AP6181 硬件接口 1.2 AP6181 驱动层级 二 SDIO设备对象管理 2.1 SDIO Bus Driver 2.1.1 Host ...

  8. Direc3D设备对象

    1.创建Direct3D设备对象 在创建Direct3D设备对象之前,先需要初始化交换链DXGI_SWAP_CHAIN_DESC. typedef struct DXGI_SWAP_CHAIN_DES ...

  9. Linux设备驱动01:Linux设备驱动概述

    目录 1. 设备驱动的作用 2. 有无操作系统时的设备驱动 2.1 无操作系统 2.1.1 硬件.驱动和应用程序的关系 2.1.2 单任务软件典型架构 2.2 有操作系统 2.2.1 硬件.驱动.操作 ...

最新文章

  1. 全球每年仅一位!中国数学家印卧涛荣获优化领域Egon Balas奖
  2. php 循环从数据库分页取数据批量修改数据
  3. 程序员辞职卖卷饼:4天挣1个月工资!摆摊真那么赚钱?
  4. How to save your Ethereum Dapp users from paying gas for transactions
  5. C和指针之动态内存分配堆、栈、全局区(静态区)、常量区对比总结学习笔记
  6. SQLServer之事务简介
  7. scss编译输出css并转换成rem
  8. ios点击推送闪退_苹果应用闪退是什么原因?如何解决进行ios签名后的苹果应用闪退问题?...
  9. [Postman]响应(7)
  10. 机器学习笔记(二):矩阵、环境搭建、NumPy | 凌云时刻
  11. SpringBoot整合sigar实现服务端监控
  12. sgx芯片服务器,英特尔SGX概述:SGX内部实现分析研究(part1)
  13. Linux如何用link命令停网卡,如何使用 ethtool 命令管理以太网卡 | Linux 中国
  14. 显卡服务器已停止响应,显卡驱动停止响应并已成功恢复问题,找到根本原因,彻底解决!...
  15. (15):响应式设计
  16. 虚拟机给openwrt添加硬盘并且配置smb
  17. 数据库字段属性的详解
  18. jenkins报错:java.lang.illegalstateexception already existed will not overwrite with
  19. 倍福 BECKHOFF CX9020 是一款适合 DIN 导轨安装的紧凑型以太网控制器,如何做CAN隔离
  20. 做到这些让你逃离奴隶的束缚

热门文章

  1. NetBPM工作流的一个示例-请假审批
  2. error This module isn‘t specified in a package.json file.
  3. HTML的基本知识(一)——标题标签
  4. erp管理系统都有哪些
  5. DOCX%20是什么格式
  6. 有人说如果车速每小时超过120公里,爆胎时无法挽回是真的吗?
  7. 未来茅台酒会怎样跌下神坛?
  8. 喜欢独自喝茶的人是什么样的人
  9. 有人说苹果手机的CPU非常强大,为什么会这样?苹果cpu又是谁设计的?
  10. CSS--CSS清除浮动的4种方式