驱动程序的同步处理
好文章,来自【福优学苑@音视频+流媒体】
简介与章节概览:
基础知识:
A、同步与异步、中断请求级IRQL
B、自旋锁:KSpinLock
C、同步对象:事件、信号量、互斥体
D、内核模式下创建线程
数据结构与API:
KeWaitForSingleObject(...)
KeWaitForMultipleObjects(...)
PsCreateSystemThread(...):系统线程、用户线程
PsTerminateSystemThread(...)
IoGetCurrentProcess(...)
KEVENT kpevent;//计数管理器,refCount
KeInitializeEvent(...)
KeSetEvent(...)
通知事件:IoCreateNotificationEvent(...)
同步事件:IoCreateSynchronizationEvent(...)
ObReferenceObjectByHandle(..)
KSEMAPHORE
KeInitializeSemaphore(...)
KeReleaseSemaphore(...)
KeReadStateSemaphore(...)
KMUTEX
KeInitializeMutex(...)
KeReleaseMutex(...)
基本概念
问题的引出
多线程
“可重入”
“不可重入”
int i = 0;
void fun(){
i++;//c语句:3条汇编指令
//原子操作
//临界资源、临界区
InterchangedXXX(...)
Mov eax, ptr dword [i]
Add eax,1
Mov ptr dword[i], eax
}
Thread1:
Thread2:
同步与异步
同步:
Main(...)//main-thread
ReadFile(...)//1.synchronous, 2.asynchronous
//Sysenter;
//ntdll.dll,, NtReadFile(...)
//本地服务:
//ZwReadFile(...)
//IRP_MJ_Read(...){........}、派遣函数
异步:
中断请求级
中断请求(irq)与可编程中断控制器(pic)
软件中断、
硬件中断、
中断请求级
高级可编程控制器(apic)
中断请求级(irql)
线程调度与线程优先级
irql的变化
irql与内存分页
控制irql提升与降低
自旋锁
原理与使用方法
保存到设备扩展中,不要使用全局变量
KSPIN_LOCK
KeInitializeSpinLock(...)
KeAcquireSpinLock(...)
KeReleaseSpinLock(...)
//自旋锁:实现简单、空耗cpu
Void kspinlockMe(..)
Int i=0;
While(i<100000){
}
If(...){}
Else{kspinlockMe(...)}
用户模式下的同步对象
用户模式的等待
WaitForSingleObject(...)
WaitForMultiObjects(...)
用户模式开启多线程
CreateThread(...)
_beginthreadex(...)
用户模式的事件
Main(....){//主线程
hevent = CreateEvent(...)
//
_beginthreadex(....)//funenter, paras:&hevent
//SetEvent(hevent);
WaitForSingleObject(hevent, ms);
}
1
1 2 3
用户模式的信号灯
CreateSemaphore(...)
用户模式的互斥体
CreateMutex(...)
等待线程完成
WaitForXXX(...)
内核模式下的同步对象
内核模式下的等待
KeWaitForSingleObject(...)
KeWaitForMultipleObjects(...)
内核模式下开启多线程
类型: 用户线程, 系统线程
PsCreateSystemThread(...)
PsTerminateSystemThread(...)
IoGetCurrentProcess(...)
NTSTATUS
PsCreateSystemThread(
_Out_ PHANDLE ThreadHandle,
_In_ ULONG DesiredAccess,
_In_opt_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ HANDLE ProcessHandle,
_Out_opt_ PCLIENT_ID ClientId,
_In_ PKSTART_ROUTINE StartRoutine,
_In_opt_ _When_(return >= 0, __drv_aliasesMem) PVOID StartContext
);
NTSTATUS
PsTerminateSystemThread(
_In_ NTSTATUS ExitStatus
);
内核模式下的事件对象
KEVENT kpevent;
KeInitializeEvent(...)
KeSetEvent(...)
PsCreateSystemThread(...)
KeWaitForSingleObject(...)
VOID
KeInitializeEvent (
_Out_ PRKEVENT Event,
_In_ EVENT_TYPE Type,//同步,通知
_In_ BOOLEAN State
);
驱动程序与应用程序交互事件对象
//app:
hevent2 = CreateEvent(...)
DeviceIoControl(...)
DeviceIoControl(hdevice, octl_code,
&hevent2, sizeof(hevent2),
NULL,0,
&dwout,
NULL);
------------
BOOL
WINAPI
DeviceIoControl(
_In_ HANDLE hDevice,
_In_ DWORD dwIoControlCode,
_In_reads_bytes_opt_(nInBufferSize) LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_writes_bytes_to_opt_(nOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
//kernel:
事件句柄
ObReferenceObjectByHandle(..)
ObDereferenceObject(...)
NTSTATUS
ObReferenceObjectByHandle(
_In_ HANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ POBJECT_TYPE ObjectType,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PVOID *Object,
_Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
);
驱动程序与驱动程序交互事件对象
通知事件:IoCreateNotificationEvent(...)
同步事件:IoCreateSynchronizationEvent(...)
ObReferenceObjectByHandle(..)
PKEVENT
IoCreateNotificationEvent(
_In_ PUNICODE_STRING EventName,
_Out_ PHANDLE EventHandle
);
PKEVENT
IoCreateSynchronizationEvent(
_In_ PUNICODE_STRING EventName,
_Out_ PHANDLE EventHandle
);
内核模式下的信号灯
KSEMAPHORE
KeInitializeSemaphore(...)
KeReleaseSemaphore(...)
KeReadStateSemaphore(...)
VOID
KeInitializeSemaphore (
_Out_ PRKSEMAPHORE Semaphore,
_In_ LONG Count,
_In_ LONG Limit
);
内核模式下的互斥体
KMUTEX
KeInitializeMutex(...)
KeReleaseMutex(...)
VOID
KeInitializeMutex (
_Out_ PRKMUTEX Mutex,
_In_ ULONG Level
);
快速互斥体
其他同步方法
使用自旋锁进行同步
使用互锁操作进行同步
小结
***【在线视频教程】***