进程阻塞(block)、挂起(suspend)与休眠(sleep)的区别及状态疑问
关于阻塞、Sleep与挂起状态的疑问解答
这个问题问得很到位!咱们先把几个关键状态的定义掰扯清楚,再逐个解答你的疑问~
首先:明确几个核心状态的区别
先理清楚操作系统里两个容易混淆的维度:
- 阻塞状态(Blocked):进程因为等待某个外部事件(比如I/O就绪、信号量释放、睡眠时间到)而无法继续执行,此时进程虽然还在内存里,但完全不会被调度到CPU上运行。
- 挂起状态(Suspended):这是从内存驻留的角度来说的——进程被移出物理内存,放到外存(比如磁盘的交换分区),暂时不参与任何调度,直到被系统或用户唤醒并重新加载回内存。
这俩是不同维度的状态:一个描述进程是否在等待事件,一个描述进程是否在内存中。
1. 处于阻塞状态的进程是否可称为挂起状态?
答案是不能直接划等号。
- 单纯的阻塞状态(业内常叫「活动阻塞」):进程还在内存里,只是等着事件发生,这时候它不属于挂起状态。
- 不过有些操作系统会有组合状态,比如「阻塞挂起」:当内存不足时,系统会把已经阻塞的进程换出到外存,这时候进程同时处于阻塞+挂起状态,但这是两个属性的叠加,不是阻塞等于挂起。
举你给的代码例子:
while (true) { msg = recv(port, BLOCKING_FLAG); // blocks here cout<<msg<<endl; }
当recv没收到数据时,进程进入活动阻塞状态——留在内存里等网络数据,但不会占用CPU,这时候它不是挂起状态。
2. 阻塞状态的进程会被CPU换出吗?
这里要分两种“换出”来理解:
- 如果指的是从CPU的运行/就绪队列中移除:那肯定会!阻塞的进程已经主动放弃了CPU,调度器会立刻把它从就绪队列移到阻塞队列,不会再给它分配时间片,直到它等待的事件发生(比如收到网络数据),才会被移回就绪队列等待调度。
- 如果指的是从物理内存换出到外存:这不一定。只有当系统内存资源紧张时,操作系统才可能把阻塞的进程换出到磁盘(变成「阻塞挂起」状态);如果内存充足,进程会一直留在内存里等待事件。
3. Sleep状态的进程:本质是特殊的阻塞,情况类似
sleep(1000)这种主动休眠的进程,本质上也是阻塞状态——它在等待「时间到达」这个特定事件。
- 那sleep进程算不算挂起状态?和普通阻塞一样,单纯的sleep状态(活动阻塞)不是挂起状态,只有内存不足时才会被换出外存变成挂起状态。
- 会不会被CPU换出?当然会!调用
sleep后,进程会立刻让出CPU,被调度器移到阻塞队列,直到睡眠时间结束,才会被唤醒回到就绪队列。
内容的提问来源于stack exchange,提问作者Yves




