首先,我很佩服这种深究的精神。你提到的,应该是IA-32手册第一卷中下面的6.4节中的解释吧,即:
• An interrupt is an asynchronous event that is typically triggered by an I/O device. • An exception is a synchronous event that is generated when the processor detects one or more predefined conditions while executing an instruction. The IA-32 architecture specifies three classes of exceptions: faults, traps, and aborts.
《软件调试》确实没有直接翻译这种说法(顺便证实了《软件调试》可不是IA-32的复制和翻译^-^)。原因就是把同步和异步这个概念用进去,那么就不够浅显。事实上,上面的话包含了两个角度,一个角度是同步与异步,另一个角度是来源,软件调试重点突出了比较容易理解的后一个角度。也就是(《软件调试》P67):
我们可以归纳出中断和异常的根本差异是:异常来自于CPU本身,是CPU主动产生的;而中断来自外部设备,是中断源发起的,CPU是被动的。
之所以这样写,是因为我觉得这种区分方法容易理解,而且理解到这个程度对大多数软件工程师也就够了。
当然,学无止境,像你这样的读者就不满足停留在这个地步,那么下面就谈谈我对synchronous(同步)和asynchronous(异步)的理解。
简单说,无论是同步还是异步,都是用来描述两个对象之间协作方式的(就像你问的和谁同步)。所谓同步事件(请求)就是指发起者会一直等待目标的回复,直到等待到结果,才继续做别的事。所谓异步事件就是指发起者发出请求后,就去做别的事了,等被请求目标准备好了后再通知它。
以买火车票(~-~)为例,大多数农民工兄弟是以同步方式做这件事的,他们带着行李到售票处,等在那里直到有结果(买到或者没有)。但是这种方式显然太辛苦。于是略有门路的人都会选择异步方式,打一个电话发出请求,然后就干别的事了,等有了结果再去付钱拿票。
如果觉得上边的例子与计算机没关,不沾科技的边。那么再举个ReadFile API(http://msdn.microsoft.com/en-us/library/aa365467%28VS.85%29.aspx )的例子。
BOOL WINAPI ReadFile( __in HANDLE hFile, __out LPVOID lpBuffer, __in DWORD nNumberOfBytesToRead, __out_opt LPDWORD lpNumberOfBytesRead, __inout_opt LPOVERLAPPED lpOverlapped );
大多数程序员使用这个API时都会用NULL作为最后一个参数lpOverlapped。这样的话,这个API便是以同步方式工作的,只有读到了指定长度的内容或者遇到特殊情况(比如遇到错误)才返回。但是,这个API也可以以异步方式工作,也就是通过最后一个参数指定一个结构,结构中有事件句柄等信息,那么如果目前没有要读长度的数据,那么这个API也会返回,等有数据了再通知读取者。
有点说远了(?!),赶紧回来,之所以说中断是异步的?是因为发出中断的设备通过某种方式(电平或者脉冲)提出申请后,它不知道什么时候会有人来处理。举个串口设备的例子,当它的缓冲区中有了一定数量的数据时,它就发出中断请求,但是此时CPU可能屏蔽所有中断,根本不来处理这件事。而串口设备也很“理解”这个道理,它会继续干手里的其它工作,比如,接收更多的数据放到缓冲区,并不像农民工买票那样在那干等。
那么为什么说异常就是同步的呢?首先这里的异常严格指CPU的异常,不包括程序里用throw抛出来的。这是因为CPU一旦产生一个异常,那么它一定要等这个异常处理好了,才能回过头继续执行被异常打断的那个任务。
理解了上面的内容,就比较好回答上面的三个问题了。
Q1:对于中断,发起中断请求的设备和它希望处理请求的CPU(软件)之间是异步的。对于异常,触发异常的当前任务和处理异常的代码二者之间是同步的。
Q2:对的,软中断严格来说是异常,《软件调试》的67页特意做了说明。
Q3:AFAIK,本意就是陷阱,CPU本来沿着一个路线跑,突然遇到一个“坑”…掉进去了,必须爬出来才能继续跑,所以是同步的……
|