這個問題純粹是學術問題,因為現在沒有人使用 MS-DOS,但我仍然想知道為什么。
在一些書籍和文章中,他們說如果您在另一個程序中呼叫 DOS 中斷,可能會導致死鎖。這就是為什么 MS-DOS 不能重入的原因。例如,RESIDENT PROGRAMS和另一本書,如下所述:
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
它說,當我完成時,轉到 J,它試圖回傳第一個 DOS 命令被中斷的點,但是由于所有 DOS 變數和堆疊都被 F 和 G 更改,當你嘗試回傳到原來的中斷(B),你實際上回到第二個中斷(E),這會導致死鎖。
但就我而言,中斷就像一個呼叫。保存當前的CS:IP,檢查向量,找到中斷處理程式,執行,回傳中斷發生的地方。完全一樣call
。甚至可能發生死鎖是沒有意義的。
所以我的問題是究竟是什么可能導致死鎖?一個具體的例子將不勝感激。
uj5u.com熱心網友回復:
主要原因有兩個:
DOS 內核不是為可重入而設計的
當代碼應該是可重入的時,它必須在設計時考慮到這一點,并且您不能使用某些設計模式,例如臨時資料的靜態緩沖區。避免這些設計模式對于 DOS 的作者來說并不是一個優先事項,因此代碼通常不是可重入的。
對于其他功能,很難以可重入的方式實作它們。例如,采用一個將字符輸出到螢屏的函式。這是通過首先推進游標然后將字符繪制到幀緩沖區來完成的。假設在游標前進之后但在繪制字符之前發生了中斷。然后,會發生以下情況:
- 外部呼叫:游標從位置 1 前進到位置 2
- 打斷!
- 內部呼叫:游標從位置 2 前進到位置 3
- 內部呼叫:字符繪制在位置 3
- 中斷結束
- 外部呼叫:字符繪制在位置 3
所以不是兩個字符,而是只繪制一個,中間有一個空白。
雖然在某些情況下可以通過關閉中斷來避免此類問題,但實際上一直這樣做并不是一個好的設計,因為這會增加中斷延遲。此外,對于像檔案系統這樣更復雜的子系統,它可能需要完全不同的設計才能做到這一點。
可重入性(與多執行緒安全性相反)的另一個問題是您不能真正使用臨界區。當您是中斷處理程式并嘗試進入臨界區但不能進入時,您將無法等待臨界區空閑,因為保存它的代碼在中斷處理程式完成之前不會繼續執行。所以這是一個難題,要正確處理這種情況真的很困難。
DOS內核有自己的堆疊
DOS 應用程式往往具有非常小的堆疊。同時,DOS 多年來不斷發展,可能需要大量的堆疊空間來執行其功能。為了解決這個問題,DOS 設計者從 DOS 2 開始添加了 DOS 內部堆疊。每當呼叫 DOS 中斷時,中斷處理程式首先切換到 DOS 堆疊,然后執行用戶呼叫的功能。如果在 DOS 內部就嘗試這樣做,堆疊切換會破壞外部 DOS 呼叫的呼叫堆疊。
幸運的是 DOS 阻止了你這樣做:有一個“in DOS”標志來跟蹤一個 DOS 呼叫是否正在運行。如果呼叫正在運行,堆疊切換將中止,您的 DOS 呼叫將失敗。
順便說一句,在撰寫彈出式 TSR 時,這是一個巨大的問題,并且有關此主題的書籍會用長篇大論介紹 DOS 呼叫時您可以做什么和不能做什么,以及如何解決這些問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/472519.html
上一篇:在python中平方所需的時間
下一篇:匯編語言中的“標簽”-操作碼