内核模式下的同步对象

内核模式下的等待
在内核模式下,有两个函数负责等待内核同步对象。 分别是KeWaitForSingleObject和KeWaitForMultipleObject函数。

NTSTATUS
KeWaitForSingleObject (
    PVOID Object,  //同步内核对象的指针
    KWAIT_REASON WaitReason,	//内核模式下设置此值为Executive
    KPROCESSOR_MODE WaitMode,	//驱动中应该设置为KernelMode 
    BOOLEAN Alertable,		//是否是课唤醒的。一般设置为FALSE
    PLARGE_INTEGER Timeout	//已经转换为NT时间的格式,负数表示相对于现在的时间单位是-100nm
    );

内核模式下开始多线程

一般在多线程中才需要同步处理机制,这里介绍一下如何在内核模式下创建新线程。
内核函数PsCreateSystemThread负责创建新线程。该函数可以创建两种线程,一 种是用户
线程,一种是系统线程。用户线程是属于当前进程中的线程。当前进程指的是当前I/O操
作的发起者。如果在IRP_MJ_READ的派遣函数中调用PsCreateSystemThread 函数创建用
户线程,新线程就属于调用ReadFile的进程。
系统线程不属于当前用户进程,而属于系统进程。系统进程是操作系统中一个特殊的
进程。这个进程的ID - -般为4。

NTSTATUS PsCreateSystemThread(
  PHANDLE            ThreadHandle,	//新创建线程的句柄
  ULONG              DesiredAccess,	//创建的权限
  POBJECT_ATTRIBUTES ObjectAttributes,	//该线程的属性,一般设置为NULL
  HANDLE             ProcessHandle,// 第四个参数ProcessHandle指定是创建用户线程还是系统进程。如果该值为NULL,则为创建系统线程。如果该值是一个进程句柄,则新创建的线程属于这个指定的进程。DDK提供的宏NtCurrentProcess可以得到当前进程的句柄。

  PCLIENT_ID         ClientId,	//该线程ID
  PKSTART_ROUTINE    StartRoutine,	//新线程的运行地址
  PVOID              StartContext	//新线程接收的参数
);

在内核模式下,创建的线程必须用函数PsTerminateSystemThread强制线程结束,否则该线程是无法自动退出的。

内核模式下的事件对象

使用事件对象前需要调用KeInitializeEvent对事件对象进行初始化。
void KeInitializeEvent(
  PRKEVENT   Event,//	初始化事件对象的指针
  EVENT_TYPE Type,//指定事件的类型是NotificationEvent(通知类型) 还是SynchronizationEvent(同步)
  BOOLEAN    State	//指定事件的初始状态。True表示已发出信号的状态。
);

如果创建的事件对象是“通知事件”,当事件对象变为激发态时,程序员需要手动将
其改回未激发态。如果创建的事件对象是“同步事件”,当事件对象为激发态时,如遇到
KeWaitForXX等内核函数,事件对象则自动变回未激发态。

事件对象的使用

VOID kThreadProc(PVOID pEvent)
{
	KeSetEvent( pEvent, 
				IO_NO_INCREMENT,
				FALSE  //是否立即调用KeWaitFOrXXX函数,如果为真,该函数返回而不降低IRQL,不会发生线程切换,直接调用WaitForxxx
			);
	DbgPrint("线程正在运行\n");
	//在内核中,需要自己结束线程
	PsTerminateSystemThread(STATUS_SUCCESS);
}


VOID CreateThreadProc()
{
	KEVENT kEvent;
	HANDLE hThread;
	KeInitializeEvent(&kEvent, NotificationEvent, FALSE);
	PsCreateSystemThread(&hThread,0,0,NtCurrentProcess(),0,kThreadProc,&kEvent);
	//如果这里不使用等待,KeSetEvent使用的pEvent就会是无效的,因为它是在这个函数中。
	KeWaitForSingleObject(&kEvent, Executive, KernelMode,FALSE,NULL);
	DbgPrint("完成线程等待\n");
}

在两个不同的驱动中交互事件对象
这就需要创建带有名字的事件对象,使用IoCreateNotificationEvent和IoCreateSynchronizationEvent
函数。

内核模式下的信号量

同样的使用信号量也需要使用KeInitializeSemaphore来进行初始化

void KeInitializeSemaphore(
  PRKSEMAPHORE Semaphore,	//信号量的指针
  LONG         Count,		//初始化信号的个数
  LONG         Limit		//信号量计数的上限
);

信号量可以一次性通知多个WaitForxxx函数。

内核模式下的互斥体

初始化互斥体对象使用KeInitializeMutex函数。

void KeInitializeMutex(
  PRKMUTEX Mutex,	//互斥体对象指针
  ULONG    Level	//保留值,一般设置为0
);

互斥体是与线程相关的。在一个线程获得该互斥体对象是,别的同时也在等待该互斥体对象的线程是不能执行的,必须在该线程调用KeReleaseMutex释放互斥体后吗,才能被别的线程拥有。

快速互斥体

快速互斥体的执行速度比普通互斥体块,唯一的区别是快速互斥体不能被同一个线程拥有两次。
除此之外,对快速互斥体的初始化、获取和释放对应的内核函数也和普通互斥体不同。
初始化快速互斥体的内核函数是ExInitializeFastMutex, 获取快速互斥体的内核函数是
ExAcquireFastMutex,释放快速互斥体的内核函数是ExReleaseFastMutex。下面的例子演示
了如何在驱动程序中使用快速互斥体。

使用自旋锁进行同步

对于要同步的代码,需要用同一把自旋锁进行同步。如果程序得到了自旋锁,其他程
序希望获取自旋锁时,则不停地进入自旋状态。获得自旋锁的内核函数是KeAcquire
SpinLock。直到自旋锁被释放后,另外的程序才能获取到自旋锁。释放自旋锁的内核函数
是KeReleaseSpinIock。

使用互锁操作进行同步

DDK提供了两类互锁操作来提供简单的同步处理,一类 是InterlockedXX 函数,另一
类是ExInterlockedXX函数。其中,InterlockedXX 系列的函数不通过自旋锁实现,而
ExInterlockedXX系列函数通过自旋锁实现。InterlockedXX 系列函数不需要程序员提供自
旋锁,内部不会提升IRQL,因此InterlockedXX函数可以操作非分页的数据,也可以操作
分页的数据。而ExInterlockedXX需要程序员提供一个自旋锁,内部依靠这个自旋锁实现
同步,所有ExInterlockedXX不能操作分页内存的数据。(因为操作了内存,且提升了IRQL 如果内存不存在,处理页异常的程序是不能执行的,从而引发错误蓝屏)

ExInterLockedXX系列互锁操作函数

内核函数功能
ExInterlockedAddlargeInteger6464位整数加法互锁操作
ExInterlockedAddLargeStatistic6464位整数加法互锁操作
ExInterlockedAddUlong32位整数加法互锁操作
ExInterlockedAllocateFromZone分配互锁操作
ExInterlockedCompareExchange64两个32位整数互换互锁操作
ExInterlockedDecrementLong32位整数减法互锁操作
ExInterlockedExchangeAddLargelnteger64位整数加法互锁操作
ExInterlockedExchangeUlong两个整数交换互锁操作
ExInterlockedFlushSList删除链表全部元素的互锁操作
ExInterlockedIncrementLong32位整数自增互锁操作
ExInterlockedInsertHeadList插入双向链表互锁操作
ExInterlockedInsertTaillist插入双向链表互锁操作
ExInterlockedPopEntryList删除单向链表互锁操作
ExInterlockedPopEntrySList删除单向链表互锁操作
ExInterlockedPushEntryList插入单向链表互锁操作
ExInterlockedPushEntrySList插入单向链表互锁操作
ExInterlockedRemoveHeadList插入双向链表互锁操作

InterLockedXX系列互锁操作函数

内核函数功能
InterlockedCompareExchange比较互锁操作
InterlockedCompareExchangePointer比较互锁操作
InterlockedDecrement整型自减互锁操作
InterlockedExchange整型交换互锁操作
InterlockedExchangeAdd两个整型相加互锁操作
InterlockedExchangePointer为指针赋值互锁操作
InterlockedIncrement整型自增互锁操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值