为什么MS-DOS“不可重入”,而且DOS中断不能调用另一个中断? 为什么MS-DOS“不可重入”,而且DOS中断不能调用另一个中断?

4

这个问题是纯粹学术性质的,因为现在没有人再使用MS-DOS了,但我仍然想知道原因。

一些书籍和文章中指出,如果在调用DOS中断时再次调用另一个DOS中断,可能会导致死锁。这就是为什么MS-DOS不可重入的原因。 例如,驻留程序,还有另一本书,如下所述:

A  interrupt occurs
B  interrupt handling
C DOS command starts
D new interrupt occurs
E interrupt handling
F DOS COMMAND starts
G DOS command finished
H interrupt finished
I return to the original interrupt handling
J return to original DOS command

It says, when I is finished, going to J, which is trying to return to the point the first DOS command was interrupted, but as all DOS variables and stack are changed by F and G, when you try to go back to the original interrupt (B), you actually go back to the second interrupt (E), and that causes the deadlock.

但就我而言,中断就像是一个调用。保存当前的CS:IP状态,检查向量,找到中断处理程序,执行,然后返回到中断发生的地方。就像call一样。
这种死锁情况根本就不合理。

所以我的问题是,是什么原因导致了死锁?能提供一个具体的例子吗?


6
"因为现在没有人使用MS-DOS了。" 我认为你会感到惊讶的。我的猜测是,仍然有一些版本或变种的DOS在生产系统中运行,其中一些机器仍然正常工作。 - Mark Rotteveel
6
DOS 的操作非常可预测,很可能永远不会再次更新,并具有硬实时特性。这对许多嵌入式应用非常有吸引力。 - fuz
1个回答

8

有两个主要原因:

DOS内核没有被设计为可重入

当代码需要是可重入的时候,必须考虑到这一点,并且不能使用某些设计模式,比如用于临时数据的静态缓冲区。避免这些设计模式不是DOS作者的首要任务,所以代码通常不可重入。

在其他函数中,很难或者几乎不可能以可重入的方式实现它们。例如,考虑一个输出字符到屏幕的函数。这是通过先移动光标,然后将字符绘制到帧缓冲区中来完成的。假设在光标已经移动但字符还没有绘制之前发生了中断。那么会发生以下情况:

  1. 外部调用:光标从位置1向前移动到位置2
  2. 中断!
  3. 内部调用:光标从位置2向前移动到位置3
  4. 内部调用:字符绘制在位置3
  5. 中断结束
  6. 外部调用:字符绘制在位置3

因此,只有一个字符被绘制,并且中间有一个空白。

虽然在某些情况下可以通过关闭中断来避免这种问题,但总体上这并不是一个好的设计,因为它会增加中断延迟。此外,对于像文件系统这样更复杂的子系统,可能需要采用完全不同的设计。

与多线程安全(而非可重入)相比,另一个问题是您无法真正使用关键段。当您是中断处理程序并尝试进入关键段但无法进入时,您将无法等待关键段变为空闲状态,因为持有该关键段的代码将一直等到您的中断处理程序完成才继续执行。这是一个棘手的问题,而且在正确处理这种情况方面确实很困难。

DOS内核有自己的堆栈

DOS应用程序往往具有非常小的堆栈。与此同时,DOS随着时间的推移已经发展壮大,并且可能需要大量的堆栈空间来执行其功能。为解决这个问题,DOS设计者从DOS 2开始添加了DOS内部堆栈。每当调用DOS中断时,中断处理程序首先切换到DOS堆栈,然后执行用户请求的功能。如果在DOS内部尝试这样做,堆栈切换将破坏外部DOS调用的调用堆栈。

幸运的是,DOS阻止了您这样做:有一个“在DOS中”的标志,用于跟踪当前是否正在运行DOS调用。如果正在执行调用,则堆栈切换将被中止,您的DOS调用将失败。

顺便说一句,当编写弹出式TSR(Terminate and Stay Resident)时,这是一个巨大的问题,关于此主题的书籍会花费很长时间讨论在调用TSR时可以和不能执行的DOS调用以及如何解决这些问题。


1
如果你想从TSR的中断处理程序中调用DOS,那么你应该自己检查InDOS标志。 - ecm
3
这是简略回答,但关于这个问题还有很多细节。人们做了各种疯狂的事情,包括复制内部DOS堆栈并稍后恢复它们。 - fuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接