Terminate_and_stay_resident_program

**終止及常駐程式** （英語：Terminate and stay resident，縮寫為 TSR），簡稱**常駐程式**，是 DOS 系統下特殊的電腦程式，此程式利用 DOS 的系統呼叫，將電腦控制權交給作業系統，彷彿程式已經結束。但程式仍保留在電腦記憶體中，可以通過硬體或軟體中斷重新喚醒它。該技術某部分克服了 DOS 同一時間只能執行一個任務（Task）的限制。TSR 是 DOS 特有的程式，不會在 Windows 系統中執行。

常駐程式中有些是工具軟體，使用者在日常使用電腦時，可能每天會用熱鍵多次呼叫工具軟體。像 Borland 公司的 SideKick 就是早期流行的應用軟體。有些常駐程式則是作業系統不直接支援的硬體裝置驅動程式，。

## 使用 TSR

通常在 DOS 中，任何指定時間只能執行一個程式。要停止執行，它將使用系統呼叫 INT 21h/4Ch 將控制權交回給 DOS shell 程式 COMMAND.COM。然後將程式使用的記憶體和系統資源標示為未使用。事實上，這使得無法重新啟動程式的某些部分而不必從頭開始重新載入整個程式。但是，如果程式以系統呼叫 INT 27h 或 INT 21h/31h 結尾，則作業系統不會重用程式暫存器的特定部分。

原本呼叫 INT 27h 被稱為「停止但仍駐留」，因此名稱為「 TSR」。使用此呼叫，程式最多可佔用其記憶體 64 KB。MS-DOS 2.0 版引入了改進的呼叫 INT 21h / 函數 31h（「保留程式」），該呼叫拿掉了此限制，並允許程式返回一個返回碼。在進行此呼叫之前，程式可以安裝一個或多個指向其自身的中斷處理程式，以便可以再次呼叫它。安裝硬體中斷向量可使此類程式對硬體事件做出反應。安裝軟體中斷向量可使當前執行的程式呼叫它。安裝計時器中斷處理程式可使 TSR 定期執行（請參閱 ISA）和可編程間隔計時器。

使用中斷向量的典型方法包括讀取其當前值（位址），將其儲存在 TSR 的儲存空間中以及安裝指向其自身程式碼的指標。在 TSR 接收到中斷並完成其處理之前或之後，將呼叫儲存的位址，事實上形成了中斷處理程式的單連結列表，也稱為中斷服務程式（ISR）。安裝 ISR 的過程稱為連結或 hooking 中斷（或中斷向量）。

通過連結中斷向量，TSR 程式可以完全控制電腦。TSR 可以具有以下兩種行為之一：

* 通過不呼叫先前已更改相同中斷向量的其他 TSR，來完全控制中斷。
* 通過呼叫舊的中斷向量與其他 TSR 串連。這可以在他們執行實際程式碼之前或之後完成。這樣，TSR 可以形成一系列程式，其中每個程式都呼叫下一個程式。

大多數 DOS 電腦病毒和其他惡意軟體都使用暫停並駐留方法，這些方法可以控制 PC 或使其處於後端。該惡意軟體將在執行時感染可執行檔（.EXE 或.COM），並在打開資料檔時對磁盤讀寫或執行檔案做出反應。

DOS 本身的某些部分（尤其是在 DOS 5.0 及更高版本中）使用相同的技術來執行有用的功能，例如 DOSKEY 命令列編輯器和各種其他可安裝的工具程式，這些工具程式是通過在命令列上執行它們來安裝的（通常是從 AUTOEXEC .BAT 或 `INSTALL` 從 CONFIG.SYS 內部執行），而不是通過 `DEVICE` 在 CONFIG.SYS 中的語法將它們作為裝置驅動程式載入。

TSR 程式可以隨時被載入。有時會在作業系統啟動後透過 AUTOEXEC.BAT 批次處理檔中來載入，也可以根據使用者的要求載入（例如，Borland 的 Sidekick 和 Turbo Debugger，Quicken 的 QuickPay 或 FunStuff 軟體的 Personal Calendar）。正如「 TSR」所暗示的那樣，這些程式將在執行其他程式時保持駐留在記憶體中。它們中的一些沒有辦法從記憶體中將自身卸載，因此呼叫 TSR 意味著程式將保留在記憶體中，直到重新啟動電腦為止。但是，可以使用 MARK.EXE/RELEASE.EXE 搭配 TurboPower Software 或 _soft reboot_ TSRs 等工具程式從外部進行卸載。它們將被特定的鍵組合觸發，然後釋放在它們之後載入的所有 TSR。由於 ISR 鏈是單個連結的，因此沒有發現前一個處理程式的位址的方法（除了嘗試回溯中斷鍊之外），或通知其前任它需要更新其「要跳轉到的下一個位址」。不要指向要刪除自身的 TSR，以便為了安全地卸載鏈中間的 TSR，在大多數情況下，必須在記憶體中保留存根，從而導致記憶體碎片。這產生了諸如 TesSeRact 和 AMIS 之類的 TSR 合作架構。

## 中斷共享

為了處理共享相同中斷的許多 TSR 程式的問題，Ralf D. Brown 提出了一種稱為「輪流多路中斷規範」（AMIS）的方法，作為對以前通過 INT 2Fh 提供的服務的改進。AMIS 提供了以受控方式共享軟體中斷的方法。它以 IBM 的中斷共享協定為模型，該協定最初是為共享 x86 處理器的硬體中斷而發明的。AMIS 服務可通過 Int 2Dh 獲得。

該提案在當時未受到程式設計師的廣泛關注。它與其他幾個複雜程度各異的競爭規範並存。

## 缺點

儘管 TSR 程式對克服 DOS 的限制非常有用，甚至是必不可少的，但它在製造麻煩方面享有盛譽。許多程式以各種明文或無規範的方式有效劫持了作業系統，當與特定應用程式或其他 TSR 一起使用時，通常會導致系統在啟動或停用時當機。如上所述，某些電腦病毒和其他惡意軟體被編碼為 TSR，因此存在一定的麻煩。此外，DOS 系統中的所有程式程式碼，甚至那些具有大量物理 RAM 的程式碼，都必須載入到前 640KB 的 RAM 中（常規記憶體）。TSR 也不例外，它佔用了 640 KB 的塊，因此應用程式無法使用這些塊。這意味著編寫一個 TSR 是一個挑戰，要使其達到最小尺寸，並檢查它與不同供應商的許多軟體產品的相容性 - 這通常是一項非常令人沮喪的工作。

在 1980 年代末期和 1990 年代初，許多 PC 平台上的電視遊戲都打破了這一限制，並為 TSR（甚至是 CD-ROM 驅動程式之類的基本驅動器）留下了越來越少的空間，並進行了整理，以便有足夠的可用 RAM 執行這些遊戲在保留必要的 TSR 的同時，變成了一種黑色藝術。許多遊戲玩家都有幾個啟動分割區具有針對不同遊戲的不同配置。在更高版本的 MS-DOS 中，「啟動選單」命令搞允許通過單個啟動磁碟選擇各種配置。在 1990 年代中期到後期，儘管仍然為 DOS 編寫許多遊戲，但通過將游戲資料和 / 或程式程式碼的部分放在前 1 MB 記憶體之上並使用 640 KB 以下的程式碼，最終克服了 640 KB 的限制。 （使用 DOS 擴展器的方法）訪問擴展的記憶體，並將程式碼交換為最低的 1 MB RAM 作為一層覆蓋。因為具有許多覆蓋層的程式設計本身就是一個挑戰，所以一旦程式太大而無法完全容納大約 512 KB，幾乎總是使用第三方 DOS 擴展器來實現擴展記憶體，該擴展器實作了 VCPI 或 DPMI，因為當 x86 處理器從真實模式切換到保護模式時，訪問 1 MB 邊界以上的記憶體變得更加容易和方便，並且可以在該區域中執行程式碼。但是，由於 DOS 和大多數 DOS 程式以真實模式執行（VCPI 或 DPMI 通過在兩種模式之間來回切換，使得受保護模式程式對於 DOS 和系統的其餘部分而言看起來像真實模式程式），因此，DOS TSR 和裝置驅動程式也以真實模式執行，因此，只要有人獲得控制，DOS 擴展器就必須切換回真實模式，直到放棄控制，這會造成時間損失（除非他們使用諸如 DPMS 或 CLOAKING 之類的技術）。

## 回歸

隨著擴展記憶體板（尤其是 Intel 80386 處理器）在 1980 年代下半年的到來，使用 640 KB 以上的記憶體來載入 TSR 成為可能。這需要復雜的軟體解決方案，稱為擴展記憶體管理器。一些記憶體管理器 QRAM 和 Quarterdeck 的 QEMM，Qualitas 的 386MAX，康柏的 CEMM ，後來微軟的 EMM386。可用於載入 640 KB 以上的 TSR 的儲存區稱為「 上層記憶體」（UMB）並將程式載入到其中被稱為載入上層記憶體。後來，記憶體管理器開始包括一些程式，這些程式試圖自動確定如何在低記憶體和高記憶體之間最佳地分配 TSR（Quarterdeck 的 Optimize 或 Microsoft 的 MemMaker），以嘗試最大程度地提高底層 640 KB 記憶體的利用率和可用空間。

## 滅亡

隨著使用 DOS 擴展器的遊戲的發展（早期的例子是 Doom）繞過了 640 KB 的障礙，許多與 TSR 相關的問題都消失了，並且 Microsoft Windows 尤其是 Windows 95 的廣泛採用（隨後是 Windows 98）–這使得大多數 TSR 變得不必要，並且某些 TSR 不相容 - 儘管 Win16 應用程式可以執行類似 TSR 的技巧，例如修補中斷描述表（IDT），因為 Windows 允許，但 TSR 逐漸變得過時了。由於多工作業系統（例如 Windows Vista，Windows 7，Mac OS X 和 Linux 提供了多個程式和裝置驅動程式可以同時執行的功能，而無需特殊的程式設計技巧，而現代的受保護記憶體概念使核心及其模組專門負責修改中斷表。

## 參見

* 守護進程（Unix）
* DOS 保護模式服務（DPMS）
* 桌面附屬程式
* 擴展程式 (Mac OS)
* Windows 服務

## 參考文獻

## 外部連結

* An early TSR （頁面存檔備份，存於網際網路檔案館）
* comp.os.msdos.programmer FAQ – How can I write a TSR (Terminate-and-Stay-Resident) utility? （頁面存檔備份，存於網際網路檔案館）
* The Alternate Multiplex Interrupt Specification （頁面存檔備份，存於網際網路檔案館） (AMIS), v.3.5
* AMISLIB （頁面存檔備份，存於網際網路檔案館） – a function library to write self-highloading, removable TSRs in assembler
* A to Z of C （頁面存檔備份，存於網際網路檔案館）; a free book on DOS programming in C; Chapter 27 – TSR programming (PDF). [2020-08-05]. （原始內容存檔 (PDF) 於 2020-06-12）.  (80 KB)
* IBM's Interrupt-Sharing Protocol, zip archive, 6.5 KB (Simtel)