概述
Windows中的并发和同步
并发是指多个控制流同时在执行,既可能是真正的并行执行(如多处理器或多核的硬件环境),也可能是分时方式的并发执行。
同步时保证在并发执行的环境中各个控制流可以有序地执行,包括对于资源的共享或互斥访问,以及代码功能的逻辑顺序。
1 进程和线程同步基础
1.1 并发性基础
进程或线程的并发性可能的来源:
多处理器环境、多核环境、超线程环境、处理器外部中断、内部中断、线程放弃执行权。
Intel X86 指令体系中,运算指令加上lock 前缀保证其原子性。
使用lock 前缀的两个条件:
- 指令的目标操作数必须是一个内存操作数;
- 仅适用于ADD、ADC、AND、BTC、BTR、BTS、CMPXCHG、CMPXCHB、DEC、INC、NEG、NOT、OR、SBB、SUB、XOR、XADD、XCHG指令。如图:
指令 | 含义 | 指令 | 含义 |
ADD | 带进位的加法 | INC | 加1 |
ADC | 加法 | NEG | 二进制求补数 |
AND | 逻辑与 | NOT | 按位求反 |
BTC | 指定的位保存到CF中,再取反 | OR | 逻辑或 |
BTR | 指定的位保存到CF中,再清零 | SBB | 带借位的整数减法 |
BTS | 指定的位保存到CF中,再置位 | SUB | 减法 |
CMPXCHG | 比较并交换 | XOR | 逻辑异或 |
CMPXCH8B | 8字节的比较并交换指令 | XADD | 交换两个操作数,并做加法 |
DEC | 减1 | XCHG | 交换两个操作数 |
如InterlockedIncrement 实现原子操作。
LONG FASTCALL InterlockedIncrement(IN OUT LONG volatile* Addend)
{
_asm{
Mov eax,1
Mov ecx,Addend
Lock xadd [ecx],eax
Inc eax
}
}
1.2 进程或线程之间的通讯
互斥或互斥体(mutex)、信号量、锁(lock)、临界区(critical section) 、自旋锁(spinlock) 和忙等待、消息。
1.3 经典的同步问题
死锁、饥饿(starvation)、优先级反转(priority inversion)、哲学家进餐问题(dining philosophers problem)
2 Windows中断与异常
中断(interrupt) 是异步的,异常是同步的。
2.1 硬件中断的发生和处理
在Intel X86 体系结构中,处理器的中断向两边也称为中断描述符表(IDT,Interrupt Descriptor Table)。IDT将每个中断或异常与一个处理该中断或异常的服务例程关联了起来。IDT中最多可有256 项。处理器内部的IDTR 寄存器记录了IDT的位置和最大限制。
如图,IDT和IDTR的关系:
异常分为三种类型:错误(fault)、陷阱(trap)和中止(abort)。
Intel x86 的中断和异常一览表,如图:
向量号 | 名称 | 类型 | 错误码 | 描述(或来源) |
0 | 除法错 | 错误 | 无 | DIV和IDIV指令产生的错误 |
1 | 调试 | 错误/陷阱 | 无 | 调试异常 |
2 | NMI中断 | 中断 | 无 | 不可屏蔽外部中断 |
3 | 断点 | 陷阱 | 无 | INT3指令 |
4 | 溢出 | 陷阱 | 无 | INTO指令 |
5 | BOUND越界 | 错误 | 无 | BOUND指令 |
6 | 无效操作码 | 错误 | 无 | UD2指令或保留的操作码(opcode) |
7 | 协处理器不可用 | 错误 | 无 | 浮点或WAIT/FWAIT指令 |
8 | 双重错误 | 中止 | 是(零) | 可产生异常、NMI或INTR的任何指令 |
9 | 协处理器段溢出 | 错误 | 无 | 浮点指令 |
10 | 无效TSS | 错误 | 是 | 任务切换或TSS访问 |
11 | 段不存在 | 错误 | 是 | 装载段寄存器或访问系统段 |
12 | 栈段错误 | 错误 | 是 | 栈操作和SS寄存器装载 |
13 | 一般保护错 | 错误 | 是 | 任何内存引用或其他保护检查 |
14 | 页面错误 | 错误 | 是 | 任何内存引用 |
15 | Intel 保留 | |||
16 | X87 浮点 | 错误 | 无 | X87FPU浮点或WAIT/FWAIT指令 |
17 | 对齐检查 | 错误 | 是(零) | 对内存中数据的引用 |
18 | 机器检查 | 中止 | 无 | 错误码和异常来源与特定模型相关 |
19 | SIMD浮点异常 | 错误 | 无 | SSE/SSE2/SSE3浮点指令 |
20~31 | Intel 保留 | |||
32~255 | 用户定义的中断 | 中断 | 外部中断或INT n 指令(n>=32) |
2.2 中断请求级别(IRQL)
Windows 使用0~31 表示优先级,数值越大,优先级越高。
#define PASSIVE_LEVEL 0 // Passive release level
#define LOW_LEVEL 0 // Lowest interrupt level
#define APC_LEVEL 1 // APC interrupt level
#define DISPATCH_LEVEL 2 // Dispatcher level
#define PROFILE_LEVEL 27 // timer used for profiling.
#define CLOCK1_LEVEL 28 // Interval clock 1 level - Not used on x86
#define CLOCK2_LEVEL 28 // Interval clock 2 level
#define IPI_LEVEL 29 // Interprocessor interrupt level
#define POWER_LEVEL 30 // Power failure level
#define HIGH_LEVEL 31 // Highest interrupt level
#if defined(NT_UP)
// synchronization level - UP system
#define SYNCH_LEVEL DISPATCH_LEVEL
#else
// synchronization level - MP system
#define SYNCH_LEVEL (IPI_LEVEL-2) // ntddk wdm ntosp
#endif
2.3 中断对象
Wrk 中中断对象KINTERRUPT 定义:
typedef struct _KINTERRUPT {
CSHORT Type;
CSHORT Size;
LIST_ENTRY InterruptListEntry;
PKSERVICE_ROUTINE ServiceRoutine;
PVOID ServiceContext;
KSPIN_LOCK SpinLock;
ULONG TickCount;
PKSPIN_LOCK ActualLock;
PKINTERRUPT_ROUTINE DispatchAddress;
ULONG Vector;
KIRQL Irql;
KIRQL SynchronizeIrql;
BOOLEAN FloatingSave;
BOOLEAN Connected;
CCHAR Number;
BOOLEAN ShareVector;
KINTERRUPT_MODE Mode;
ULONG ServiceCount;
ULONG DispatchCount;
#if defined(_AMD64_)
PKTRAP_FRAME TrapFrame;
PVOID Reserved;
ULONG DispatchCode[DISPATCH_LENGTH];
#else
ULONG DispatchCode[DISPATCH_LENGTH];
#endif
} KINTERRUPT;
InterruptListEntry :将一组中断对象相互链接起来
SeviceRoutine : 中断对象的处理例程
Vector : 一个中断对象的向量编号
Irql :表示该中断处理例程执行时的IRQL
DispatchCode :包含了基本的中断处理代码
Mode :中断对象的模式,有LevelSensitive 或Latched。LevelSensitive 模式是指,当中断请求信号出现(asserted)时,中断就会发生,因此,中断对象的例程必须消除中断的原因;Latched 模式是指,仅当中断请求信号从无信号(deasserted) 到有信号(asserted)发生变化时,中断才会发生。
当一个中断发生时,其处理过程如下:
- 中断对象得DispatchCode 代码块首先获得控制权, 把该代码块所在得中断对象放到edi寄存器中,然后跳转到对应得中断分发函数。
- 在中断分发函数中,提升IRQL,获得自旋锁,然后调研中断对象得服务例程,即KINTERRUPT 得ServiceRoutine ,待返回后,释放自旋锁,恢复IRQL。
- 中断分发函数通过Kei386EoiHelper 辅助函数返回。Kei386EoiHelper的iretd 指令结束整个中断处理。
如图:两个中断对象连接到同一个中断向量情形下的控制流程。
最后
以上就是欣喜棉花糖为你收集整理的Windows内核原理与实现读书笔记之并发和同步基础的全部内容,希望文章能够帮你解决Windows内核原理与实现读书笔记之并发和同步基础所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复