驱动开发(12)内核中的多线程和同步对象
来源:互联网 发布:linux怎么创建目录 编辑:程序博客网 时间:2024/05/22 06:55
本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/51301896
在内核模式下创建线程
在驱动程序中创建线程的方法是调用 PsCreateSystemThread 内核函数,此函数即可以创建系统线程,也可以创建用户线程。此函数的原型如下:
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_ PVOID StartContext);
- 参数1:一个 HANDLE 类型的指针,用于输出创建的线程句柄。此句柄必须在不需要使用时通过 ZwClose 释放。
- 参数2:创建线程的权限,一般设置为0。
- 参数3:指向指定对象的属性的结构,一般设置为 NULL 。
- 参数4:如果为 NULL ,则线程属于系统。如果指定一个进程句柄,则线程属于该进程,通过 NtCurrentProcess 宏可以得到当前进程句柄。
- 参数5:用于接收客户端ID,一般为 NULL 。
- 参数6:线程的启动函数指针。
- 参数7:传递给启动函数的数据。
线程启动函数原型:
KSTART_ROUTINE ThreadStart;VOID ThreadStart( _In_ PVOID StartContext){ ... }
需要注意,和用户模式线程不同,线程必须调用 PsTerminateSystemThread (或系统关机)才会退出,而不是函数返回即退出。
内核模式下的等待
驱动程序进行等待可以通过 KeWaitForSingleObject 和 KeWaitForMultipleObjects 进行等待,其实用户模式下的 WaitForSingleObject 和 WaitForMultipleObjects 就是调用了这两个函数,先来看看函数原型:
NTSTATUS KeWaitForSingleObject( _In_ PVOID Object, _In_ KWAIT_REASON WaitReason, _In_ KPROCESSOR_MODE WaitMode, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout);NTSTATUS KeWaitForMultipleObjects( _In_ ULONG Count, _In_ PVOID Object[], _In_ WAIT_TYPE WaitType, _In_ KWAIT_REASON WaitReason, _In_ KPROCESSOR_MODE WaitMode, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout, _Out_opt_ PKWAIT_BLOCK WaitBlockArray);
解释一下 KeWaitForSingleObject :
- 参数1:同步对象的指针。(不是句柄)
- 参数2:指定等待的原因。驱动程序应将该值设置为 Executive ,除非是做代表用户的工作,并在用户线程的上下文中,在这种情况下,应该将该值设置为运行 UserRequest 。
- 参数3:说明是在内核模式等待还是在用户模式等待(KernelMode or UserMode)一般设置为 KernelMode 。
- 参数4:设置等待是否“警惕”,一般为 FALSE 。
- 参数5:超时时间,若为 NULL ,则为无限等待(还记得上一篇中说过 IRQL 不小于 DISPATCH_LEVEL 的线程不能进行没有超时的等待操作吗)指向64位整数指针时,若是正数,则为从 January 1, 1601 ,若为负数,则从现在开始计时。
内核模式下的同步对象
和用户模式下的同步对象大致一样,因为用户模式同步对象就是通过调用内核同步对象函数创建的。
在应用程序中我们只能得到同步对象的指针,而在驱动程序中我们可以直接使用事件对象的指针!
对于各函数我想我不必一个个解释了,MSDN说的很清楚了,这里只起一个引导和区分作用。
1。事件
创建事件:KeInitializeEvent
创建命名事件:IoCreateNotificationEvent 和 IoCreateSynchronizationEvent
命名的事件对象的好处是,可以方便在不同驱动中找到事件对象的指针。
NotificationEvent(通知事件)和 SynchronizationEvent(同步事件)的区别:前者由未激发变为激发时,需要手动变成未激发,而后者激发后调用 KeWaitFor… 函数就会自动变为未激发。
2。自旋锁
获取自旋锁:KeAcquireSpinLock
释放自旋锁:KeReleaseSpinLock
自旋锁有“锁住”和“解锁”状态,当线程获取自旋锁时,如果处于解锁状态就可以被获取,获取会自动锁住自旋锁,必须释放后才能解锁;如果获取时处于锁住状态,那么线程就会不停地“自旋”,即线程不停地常数获取自旋锁,直到获取到为止。自旋锁不能工作在 IRQL DISPATCH_LEVEL 中断请求级。
特别需要注意:线程如果等待一个“事件”对象,那么线程就会休眠,操作系统会去调度其他线程,而获取自旋锁不同,线程会一直“自旋”,会浪费宝贵的 CPU 时间,因此获取自旋锁后到释放之前的时间不要过长。
3。互斥体/快速互斥体
创建互斥体:KeInitializeMutex
释放互斥体:KeReleaseMutex
创建快速互斥体:ExInitializeFastMutex
释放快速互斥体:ExReleaseFastMutex
快速互斥体不能被线程递归获取。
只有一个线程可以占用互斥体,获取互斥体的线程如果不释放互斥体,其他线程就不能得到互斥体,线程获取到一个互斥体时,互斥体变为激发,释放一个互斥体时,互斥体变为未激发。互斥体未激发时,等待互斥体就可以获取他,激发时则会使线程休眠,直到指定互斥体被释放后,才会有且仅有一个等待该互斥体的线程获取该互斥体。
4。信号量
创建信号量:KeInitializeSemaphore
释放信号量: KeReleaseSemaphore
信号量同样有激发和未激发两种状态,他的特殊之处是内部维护一个计数器,只要计数器不小于1就是激发状态,否则是未激发状态。
- 驱动开发(12)内核中的多线程和同步对象
- Windows驱动开发WDM (8)- 内核同步对象
- Delphi驱动开发研究之内核同步对象—Mutex
- 驱动开发(5)内核中的字符串
- Delphi驱动开发研究之内核同步对象—线程与定时器
- 多线程(二) 同步 锁对象和条件对象
- 驱动开发(4)内核中的内存分配和错误码
- .NET多线程同步方法详解(四):系统内核对象 互斥对象(Mutex)
- NET多线程同步方法详解(四):系统内核对象 互斥对象(Mutex)
- 内核同步对象(上)
- 内核同步对象(下)
- 内核同步对象(上)
- Java(8-2)多线程的同步和条件对象
- 嵌入式linux平台设备驱动(设备驱动模型)开发之linux内核中的设备驱动
- 内核对象和线程同步—WaitForSingleObject
- 白话windows多线程同步之可等待计时器内核对象
- 基于内核对象的一种多线程同步机制的本质
- 详解Java多线程开发中的数据同步
- git 使用详解(5)-- get log 查看提交历史
- 开发中注意下面几点:
- 代理模式(三)
- 多个storyboard实现tabbar
- C# 和Java区别
- 驱动开发(12)内核中的多线程和同步对象
- HTML5——新增表单元素与属性(3)
- git 使用详解(6)-撤消操作
- 线程监听文件小程序
- 集群、分布式、负载均衡区别与联系
- ABSTRACT FACTORY抽象工厂 - 对象创建型模式(四)
- 接口
- SqlServer2008维护计划(图解)
- Windows平台分布式架构实践 - 负载均衡