来自维基百科关于轮询的文章
在计算机科学中,轮询或轮询操作是指客户端程序作为同步活动主动采样外部设备的状态。轮询最常用于输入/输出(I/O),也称为轮询I/O或软件驱动I/O。
轮询有时与忙等待轮询(忙等待)同义。在这种情况下,当需要I/O操作时,计算机除了检查I/O设备的状态外,什么也不做,直到它准备就绪,这时设备就可以访问了。换句话说,计算机等待,直到设备准备就绪
轮询还指的是重复检查设备的准备情况,如果不是,则计算机返回到不同的任务。虽然这不像繁忙等待那样浪费CPU周期,但通常不如轮询、中断驱动的I/O那样高效。
因此,当线程不使用";条件变量";,它会被称为";轮询";对于数据改变或"改变";忙着等着"?
两者的区别在于应用程序在轮询之间所做的操作。
如果一个程序每隔一秒轮询一个设备,并且在没有数据可用的情况下同时做其他事情(包括可能只是睡觉,让CPU留给其他人使用),那就是轮询
如果程序连续轮询设备(或资源或其他),而在检查之间没有做任何事情,则称为忙等待。
这与同步没有直接关系。阻止条件变量(当设备或资源可用时应发出信号)的程序既不轮询也不忙于等待。这更像是事件驱动/中断驱动的I/O
(但例如,围绕try_lock
循环的线程是一种轮询形式,如果循环很紧,可能会忙于等待。)
假设有一个微处理器或微控制器,当它注意到按钮被按下时,它应该执行一些操作。
第一种方法是让程序进入一个循环,这个循环除了查看按钮是否已经更改之外什么都不做,一旦更改,就执行所需的操作。
在某些情况下,第二种方法是对硬件进行编程,以在按下按钮时触发中断,假设按钮与有线输入相连,从而可以引起中断。
第三种方法是配置一个定时器,以某种速率(例如,1000x/秒)中断处理器,并让中断的处理程序检查按钮的状态并对其采取行动
第一种方法使用繁忙等待。它可以为一种特定的刺激提供非常好的反应时间,而牺牲了完全忽略其他一切。第二种方法使用事件触发的中断。它通常会提供比繁忙等待稍慢的响应时间,但会允许CPU在等待I/O时做其他事情。它还可以允许CPU进入低功耗睡眠模式,直到按下按钮。第三种方法将提供远不如其他两种方法的响应时间,但即使硬件不允许按钮按下触发中断,也可以使用。
在需要快速响应的情况下,通常需要使用事件触发的中断或繁忙等待。然而,在许多情况下,轮询方法可能是最实用的。硬件的存在可能不支持人们可能感兴趣的所有事件,或者人们感兴趣的事件的数量可能大大超过可用中断的数量。此外,可能希望某些条件产生延迟响应。例如,假设一个人希望根据以下标准计算开关被激活的次数:
- 每个合法的开关事件将包括从0到900us(微秒)的间隔,在此期间开关可以任意闭合和重新闭合,然后是至少1.1ms的间隔,在该间隔期间开关将保持闭合,接着是从0到900 us的间隔,此间隔期间开关可以随意断开和重新闭合,随后是开关将断开的至少1.1ms的间隔。
- 在任何未被忽略的开关打开或关闭后,软件必须忽略开关的状态950us。
- 允许软件任意计数或忽略在上述要求的消隐间隔之外发生但持续时间小于1.1ms的开关事件。
- 软件报告的计数必须在开关稳定"闭合"后1.99ms内有效
执行此要求的最简单方法是观察开关的状态1000x/秒;如果在上一个状态为"打开"时显示为"关闭",则递增计数器。非常简单;即使开关以各种奇怪的方式打开和关闭,在真实事件前后的900多个小时内,软件也不会在意。
可以将开关输入触发的中断与计时器一起使用,以对开关输入产生更快的响应,同时满足所需的消隐要求。最初,输入将被配置为在下次开关闭合时触发。一旦中断被触发,软件会禁用它,但会设置一个定时器,在950us后触发中断。一旦定时器到期,它将触发一个中断,该中断将在下次开关"断开"时触发中断。该中断将反过来禁用开关中断,并再次将计时器设置为950us,因此计时器中断将再次重新启用开关中断。有时这种方法可能很有用,但软件比简单的轮询方法复杂得多。当基于定时器的方法足够时,它通常是优选的。
在使用多任务操作系统而不是直接中断的系统中,许多相同的原理也适用。与操作系统在某些事件发生之前不会运行的代码相比,定期I/O轮询会浪费一些CPU时间,但在许多情况下,使用定期轮询时,事件响应时间和没有事件发生时浪费的时间都是可以接受的。事实上,在某些缓冲I/O情况下,定期轮询可能会非常有效。例如,假设一个人通过串行端口从远程机器接收大量数据,每秒最多到达11520个字节,设备将在最后一个确认的数据包之前发送多达2K的数据,并且串行端口有4K的输入缓冲区。虽然可以使用"数据接收"事件来处理数据,但简单地检查端口100x/秒并处理到那时为止接收到的所有数据包可能同样有效。当远程设备没有发送数据时,这样的轮询将是浪费时间,但如果预期会有传入数据,那么以大约1.15K的数据块处理它可能比一收到就处理每一小块传入数据更有效