这是我上一个问题的延伸
How does blocking mode in unix/linux sockets works?
我现在从互联网上收集到的信息是,所有调用阻塞调用的进程都被置于睡眠状态,直到调度程序找到解除阻塞的原因。原因可以是缓冲区空、缓冲区满或任何其他情况。
但是,这是否是实现实时的有效方法,比如说硬实时应用程序?因为当解阻塞条件为真时,进程不会被解阻塞,而是当调度器给它CPU片,并且解阻塞条件都为真时。
如果你想要一个响应的解决方案,我不认为“旋转锁”或“忙碌等待”是正确的方式,CPU片被浪费,总的来说,系统将变得没有响应或可能响应不良。
有人能帮我理清这些矛盾的想法吗。
6条答案
按热度按时间44u64gxh1#
进入睡眠状态直到调度程序唤醒你是正常/首选的事情。
旋转(等待的替代方法,不休眠)不太常见,具有以下效果:
如果延迟的长度 * 非常 * 短(例如,如果延迟仅为执行100个CPU指令所需的时间),则旋转可以比进入休眠更高效(更少的总CPU)。
zbsbpyhn2#
旋转锁定会在所需事件未发生时消耗CPU和轮询的资源路径,从而继续浪费资源。
Blocking操作最重要的不同之处在于,不使用CPU和关联的资源路径,而是在预期从中发生所需事件的资源上安装某种形式的
wait
。在多任务或多线程/处理器环境中(这是很长一段时间以来的常见情况),当所需事件尚未到达时,可能会有其他操作,因此占用CPU和资源访问路径会导致处理能力和时间的严重浪费。
当我们有一个超线程系统时(就像我认为你在你的问题中提到的那样),重要的是要注意CPU线程被划分的粒度是非常高的。我也会冒险观察到所有的事件--你倾向于阻塞的事件--都需要足够的时间才能出现,以补偿它们在解除阻塞之前不得不额外等待的小时间片。
我认为
J-16
的观点是针对这样一种情况,即一个休眠(阻塞)线程在阻塞状态下让它的代码和数据空间闲置。这可能会使系统放弃资源(如数据/代码缓存),当块被释放时,这些资源需要重新填充。因此,根据条件,块可能会导致更多的资源浪费。这也是一个有效的注解,应该在设计和实现中检查。
但是,在大多数情况下,阻塞通常比自旋锁更好。
3j86kqsm3#
如果在应用程序的用例中,上下文切换比消耗几个CPU周期要昂贵,因为可以保证在短时间内满足您的条件,那么忙碌等待可能对您有好处。
否则,您可以通过休眠或
cond_wait()
ing强制放弃CPU。我能想到的另一个强制上下文切换的场景如下:
8aqjt8rx4#
首先,你有一个误解
阻塞调用不是“忙碌等待”或“自旋锁”。阻塞调用是可休眠的--这意味着CPU将工作在其他任务上,没有CPU被浪费。
关于你的电话屏蔽问题
阻塞调用更容易--它们更容易理解、更容易开发、更容易调试。
但是它们是资源占用者,如果不使用线程,会阻塞其他客户端;如果使用线程,每个线程都会占用内存和其他系统资源,即使内存足够,切换线程也会使该高速缓存变冷,降低性能。
这是一种权衡--更快的开发和可维护性?或可伸缩性。
6yt4nkrj5#
我会尽量切中要害,因为这里通过其他答案提供了足够的解释,是的,从所有这些答案中学习,我认为应该是一个完整的画面。
我认为应在系统的响应性与吞吐量之间进行权衡。
我认为对于系统的响应性来说,阻塞调用是最好的方法。因为它把CPU给了准备队列中的其他进程,当阻塞调用处于阻塞状态时。
当然,对于 * 特定进程或每个进程的响应性 *,我们将考虑忙等待/自旋锁模型。
现在,同样为了提高整体 * 系统响应能力 *,我们不能减少时间片(细粒度),因为这会在上下文切换中浪费太多的CPU资源。因此,系统的 * 吞吐量 * 会急剧下降。当然,很明显,阻塞模型增加了系统的吞吐量,因为被阻塞的调用不消耗CPU片并且将其给予就绪队列中的另一/下一进程。
我认为最好的办法是--设计一个系统时考虑到每个进程的响应性,而不影响整体的响应性和吞吐量--通过实现一个基于优先级的调度程序,如果增加复杂性不会困扰您的话,考虑优先级反转问题:)。
ruarlubt6#
//改编ASPI原始源代码...