驱动程序的同步处理


***【在线视频教程】***

好文章,来自【福优学苑@音视频+流媒体】

简介与章节概览:


基础知识:

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

);


快速互斥体  

  


   

其他同步方法       


使用自旋锁进行同步       


使用互锁操作进行同步


       

小结     



好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***