Windows内核原理与实现读书笔记之并发和同步基础

Windows中的并发和同步

并发是指多个控制流同时在执行,既可能是真正的并行执行(如多处理器或多核的硬件环境),也可能是分时方式的并发执行。

同步时保证在并发执行的环境中各个控制流可以有序地执行,包括对于资源的共享或互斥访问,以及代码功能的逻辑顺序。

进程和线程同步基础

1.1  并发性基础

进程或线程的并发性可能的来源:

多处理器环境、多核环境、超线程环境、处理器外部中断、内部中断、线程放弃执行权。

Intel X86 指令体系中,运算指令加上lock 前缀保证其原子性。

使用lock 前缀的两个条件:

  1. 指令的目标操作数必须是一个内存操作数;
  2. 仅适用于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)发生变化时,中断才会发生。

当一个中断发生时,其处理过程如下:

  1. 中断对象得DispatchCode 代码块首先获得控制权, 把该代码块所在得中断对象放到edi寄存器中,然后跳转到对应得中断分发函数。
  2. 在中断分发函数中,提升IRQL,获得自旋锁,然后调研中断对象得服务例程,即KINTERRUPT 得ServiceRoutine ,待返回后,释放自旋锁,恢复IRQL。
  3. 中断分发函数通过Kei386EoiHelper 辅助函数返回。Kei386EoiHelper的iretd 指令结束整个中断处理。

如图:两个中断对象连接到同一个中断向量情形下的控制流程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值