自旋锁同步
- 一般是为了内核态下各个派遣函数之间做同步作用的。
- 原理是(单CPU)将IRQL从软件中断提升到硬件中断。PASSIVE_LEVEL->DISPATCH_LEVEL。因为在DISPATCH_LEVEL中是不会出现线程切换的(只有高级别能打断低级别,而低级别不能打断高级别)。
- 因为分页内存将导致如果线程切换的时候会引起分页数据交换,数据交换是通过引发页故障来实现的,而页故障是不允许出现在DISPATCH_LEVEL中的,否则将引起系统崩溃(PASSIVE_LEVEL则允许)。驱动程序的StartIO例程、DPC例程、中断服务例程都运行在DISPATCH_LEVEL或者更高的IRQL。因此这些例程不能使用分页内存,否则将导致系统崩溃。
- 自旋锁在不同IRP之间同步的时候,则需要放在DeviceExtension中传递。
互锁
- 类似于number++; //汇编后将不止一条语句,非原子操作number--; //同上因为语句会变成多句,在线程切换的时候,两个线程下的该例程将会交织在一起执行,导致错误。可以:
先加锁
number++;
解锁
再加锁
number--;
解锁
来实现两句话的同步(按指定顺序执行,而不受到线程切换的影响)加锁解锁可以使用自旋锁 - 在系统中提供了Interlocked***/ExInterlocked***实现
信号灯同步
- 线程1关闭信号灯,以至于使用Wait****的时候,当前线程处于暂停状态。
- 线程2的作用就是在执行结束后,点亮信号灯(增加计数器)。当线程切换回来的时候,线程1就因为计数器不是0而使信号灯处于激活状态,从而继续执行线程1。
事件的同步
(不能递归获取互斥体)
- 主线程在辅助线程上设置了事件,如果不使用Wait**等待事件返回,则主线程可能直接执行完毕了,而导致辅助线程还在执行。
- 使用Wait****可以使主线程等待事件执行完成。
互斥体同步
(允许递归获取互斥体(得到互斥体的线程还可以再次获得这个互斥体,或者说互斥体对于已经获得互斥体的线程不产生“互斥”关系))
- 创建一个互斥体对象,将互斥体对象传递给多个线程。
- 在每个线程操作的步骤中,调用Wait*****,如果互斥体处于激活(内部维护一个计数器),则继续执行后续代码,并在调用结束后恢复互斥体Release****,这样当别的线程试图使用互斥体后面的代码的时候,因为互斥体状态未激活,则无法继续执行代码。
快速互斥体同步
- 与互斥体同步类似,唯一区别是不允许递归获取互斥体