原语¶
来源:
操作系统 / note/进程管理/进程/原语.md
原语就是操作系统中一种不可被中断的操作序列。
也就是说:
原语一旦开始执行,就必须执行完,中间不能被打断。
英文一般叫 primitive,在操作系统里常说的是 原子操作 atomic operation。
1. 为什么需要原语?¶
操作系统里有很多共享资源,比如:
这些数据可能会被多个进程同时访问。
如果一个操作执行到一半被打断,另一个进程又来修改同一个数据,就可能出错。
比如两个进程同时申请一个资源:
进程 A 判断:
此时发现 count = 1,可以申请。
但是还没来得及执行:
CPU 切换到了进程 B。
进程 B 也判断 count > 0,也认为可以申请,于是也申请成功。
结果:
这就出错了。
所以某些关键操作必须设计成不可中断,这就是原语。
2. 原语的核心特点¶
原语有两个重要特点:
| 特点 | 含义 |
|---|---|
| 原子性 | 要么全部执行,要么完全不执行 |
| 不可中断性 | 执行过程中不能被调度、中断打断 |
比如:
这些通常都需要做成原语。
3. 举个信号量的例子¶
信号量里的 P 操作 和 V 操作 就是经典原语。
P 操作,也叫 wait 操作¶
意思是:申请一个资源。
V 操作,也叫 signal 操作¶
意思是:释放一个资源。
这两个操作必须是原语。
因为如果 S-- 执行完,还没来得及判断 S < 0 就被打断,其他进程也来操作 S,信号量的值和等待队列就可能乱掉。
4. 原语和普通函数的区别¶
普通函数可以在执行过程中被中断或被调度走。
比如:
执行完 a++ 后,CPU 可能切到别的进程。
但原语不允许这样。
中间不能被打断。
所以:
5. 原语怎么实现不可中断?¶
常见方法有两种。
第一种是关中断。
在单处理器系统中,关中断后,时钟中断不能打断当前操作,所以不会发生进程切换。
第二种是使用硬件提供的原子指令。
比如:
这些指令本身由 CPU 保证不可分割。
在多核系统中,仅仅关当前 CPU 的中断不够,因为其他 CPU 核心还可能同时访问共享数据,所以更依赖锁和硬件原子指令。
6. 放到进程管理里理解¶
比如操作系统要把一个进程从运行态变成阻塞态:
这些步骤必须保持一致。
如果执行到一半被打断,就可能出现:
这样调度器可能错误地再次调度它。
所以这种修改系统核心数据结构的操作通常要作为原语实现。
7. 一句话总结¶
原语就是:
操作系统中完成某个核心功能的一段不可中断程序,具有原子性,要么全部完成,要么不被执行到一半就停下。
你可以把它理解成操作系统里的“最小安全操作单位”。