Linux 里进程阻塞是如何实现的

首先,有一个概念,Linux 里“一切皆文件”。

误区一:进程阻塞消耗 CPU 资源

我以前以为进程阻塞是不好的,比如 NIO 里 Socket socket = serverSocket.accept(); 会一直阻塞直到连接到来。程序要一直等待不能往下运行,感觉上是一个不好的事情。

其实,对于 CPU 来说,在这个进程阻塞的时候完全可以去跑别的程序。而对于上面的程序来说,这个阻塞也是有益的,它提供了一个等待的时间让程序能够等待连接到来。

你可能会想,进程阻塞了之后,CPU 会立马跑别的进程吗?CPU 还会回来尝试跑这个进程吗?这些问题都会影响 CPU 性能。

你需要了解 CPU 的时间片轮转机制解决第一个问题。

CPU 的时间片轮转机制

单核 CPU 在某一时刻只能跑一个进程。但小时候用的单核 CPU 的电脑一样可以“同时”运行多个程序,为什么?这是因为操作系统提供了一种CPU时间片轮转机制。

时间片轮转调度是一种最古老、最简单、最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。

如果在时间片结束时进程还在运行,则CPU使用权将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则CPU当即进行切换。

由于切换的时间很短(大概为5毫秒),切片时间也很短(一般为100毫秒),以人的反应结果就是感觉多个程序同时运行,且没有停顿(切换的时间和在别的切片上的时间)。当然如果我们开多了程序,也会很直观的感觉卡,玩游戏的时候会把其它软件关掉,也有这个道理。

知道了 CPU 的时间片轮转机制,你就知道了程序阻塞了它的进程之后,CPU 会立马跑别的进程。

但是你想知道CPU 还会不会回来尝试跑这个进程,你需要知道工作队列等待队列

工作队列和等待队列

如下图所示,Linux 内核空间里会维持一个工作队列,因为时间片轮转机制,系统会在进程A、B、C等多个进程间切换着跑。
在这里插入图片描述

假如现在进程 A 里跑的程序有一个对象执行了某个方法将当前进程阻塞了,内核会立刻将进程A从工作队列中移除,同时在该对象里创建等待队列,并新建一个引用指向进程A。如下图:
在这里插入图片描述
从图中可以看到,进程A被排在了工作队列之外,不受系统调度了,这就是我们常说的被操作系统“挂起”。
这也提现了阻塞和挂起的关系。阻塞是人为安排的,让你程序走到这里阻塞。而阻塞的实现方式是系统将进程挂起。

当这个对象受到某种“刺激”(某事件触发)之后, 操作系统将该对象等待队列上的进程重新放回到工作队列上就绪,等待时间片轮转到该进程。

所以,我们可以知道了上面第二个问题的答案,操作系统不会去尝试运行被阻塞的进程,而是由对象去等待某种“刺激”。

补充一点:这个“刺激”有的时候是说来就来的。操作系统在跑进程时,会有优先级的区别。而硬件产生的信号,CPU 收到后往往会直接中断正在执行的程序,去做出响应,执行中断程序,这个优先级是很高的。这也很好理解,我们的鼠标、键盘一有动作,计算机会立即给出反应,就是这个道理。

误区二:进程阻塞不会消耗系统资源

这两个误区对新手来说容易混淆,尤其是你在看完上面的文字之后容易进入这样的误区。

其实也很简单,系统资源不仅包括 CPU,还有内存、磁盘IO等。进程阻塞不会消耗 CPU 资源,当然不代表不会消耗系统资源。

而且进程正式系统进行资源分配的最小单位。进程虽然阻塞了,但仍然存在,存在就会占用系统资源。

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值