Введение
Программа "terminate and stay resident" (обычно TSR) — это компьютерная программа, работающая в среде DOS, которая использует системный вызов для возврата управления DOS, как если бы она завершила работу, но при этом остаётся в памяти компьютера, чтобы её можно было повторно активировать позднее. Эта техника частично обходила ограничение DOS на одновременное выполнение только одной программы или задачи. TSR используются исключительно в DOS, а не в Windows. Некоторые TSR представляют собой утилиты, которые пользователь может вызывать несколько раз в день, работая в другой программе, с помощью горячей клавиши. Borland Sidekick был одним из ранних и популярных примеров такого рода. Другие же выполняют функции драйверов устройств для оборудования, которое операционная система не поддерживает напрямую.
Использование
Обычно DOS может запускать только одну программу за раз. Когда программа завершается, она возвращает управление DOS с помощью системного вызова API DOS. Используемые ресурсы памяти и системы затем помечаются как свободные. Это делает невозможным перезапуск частей программы без полной перезагрузки. Однако, если программа завершается системным вызовом или , операционная система не повторно использует определенную часть своей памяти. Исходный вызов, , называется "завершить, но остаться в памяти", отсюда и название "TSR". Используя этот вызов, программа может зарезервировать до 64 КБ своей памяти. MS DOS версии 2.0 представила улучшенный вызов ('Keep Process'), который снял это ограничение и позволил программе возвращать код завершения. Перед выполнением этого вызова программа может установить один или несколько обработчиков прерываний, указывающих на себя, чтобы её можно было вызвать снова. Установка вектора аппаратного прерывания позволяет такой программе реагировать на аппаратные события. Установка вектора программного прерывания позволяет ей быть вызванной текущей запущенной программой. Установка обработчика таймерного прерывания позволяет TSR периодически выполняться (см. ISA и программируемый интервальный таймер, особенно раздел "IBM PC compatible"). Типичный метод использования вектора прерывания включает чтение его текущего значения (адреса), сохранение его в адресном пространстве TSR и замену его адресом в собственном коде. Сохраненный адрес вызывается из TSR, фактически формируя односвязный список обработчиков прерываний, также называемых подпрограммами обработки прерываний или ISR. Эта процедура установки ISR называется связыванием или перехватом прерывания или вектора прерывания. Связывая векторы прерываний, TSR могут получить полный контроль над компьютером. TSR может вести себя двумя способами:
- Получить полный контроль над прерыванием, не вызывая другие TSR, которые ранее изменяли тот же вектор прерывания.
- Каскадироваться с другими TSR, вызывая старый вектор прерывания. Это можно сделать до или после выполнения их собственного кода. Таким образом, TSR могут сформировать цепочку, где каждый вызывает следующий. Метод "завершить и остаться в памяти" используется большинством вирусов DOS и других вредоносных программ, которые могут либо взять под контроль ПК, либо оставаться в фоновом режиме. Эти вредоносные программы будут реагировать на операции ввода-вывода диска или события выполнения, заражая исполняемые файлы (.EXE или COM) при их запуске и файлы данных при их открытии. TSR могут быть загружены в любое время: либо во время последовательности запуска DOS (например, из AUTOEXEC.BAT), либо по запросу пользователя (например, Sidekick и Turbo Debugger от Borland, QuickPay от Quicken или Personal Calendar от FunStuff Software). Части самой DOS используют эту технику, особенно в версиях DOS 5.0 и более поздних. Например, редактор командной строки DOSKEY и различные другие утилиты устанавливаются путем их запуска в командной строке (вручную или из AUTOEXEC.BAT или через INSTALL из CONFIG.SYS), а не загружаются как драйверы устройств через инструкции DEVICE в CONFIG.SYS. Некоторые TSR не имеют возможности выгрузиться самостоятельно, поэтому они останутся в памяти до перезагрузки. Однако выгрузка возможна внешне, с помощью таких утилит, как MARK.EXE/RELEASE.EXE от TurboPower Software или TSR с "мягкой" перезагрузкой, которые будут перехватывать определенную комбинацию клавиш и освобождать все TSR, загруженные после них. Поскольку цепочка ISR является односвязной, и TSR может хранить ссылку на своего предшественника в любом месте по своему выбору, нет универсального способа для TSR удалить себя из цепочки. Поэтому обычно при выгрузке TSR в памяти должен оставаться "заглушка", вызывающая фрагментацию памяти. Эта проблема привела к созданию фреймворков для сотрудничества TSR, таких как TesSeRact и AMIS.
Take complete control of an interrupt by not calling other TSRs that had previously altered the same interrupt vector. Cascade with other TSRs by calling the old interrupt vector. This can be done before or after they executed their actual code. This way TSRs can form a chain where each calls the next. The terminate and stay resident method is used by most DOS viruses and other malware, which can either take control of the PC or stay in the background. This malware will react to disk I/O or execution events by infecting executable (. EXE or COM) files when it is run and data files when they are opened. TSRs can be loaded at any time; either during the DOS startup sequence (for example, from AUTOEXEC. BAT), or at the user's request (for example, Borland's Sidekick and Turbo Debugger, Quicken's QuickPay, or FunStuff Software's Personal Calendar). Parts of DOS itself use this technique, especially in DOS versions 5.0 and later. For example, the DOSKEY command line editor and various other utilities are installed by running them at the command line (manually, or from AUTOEXEC. BAT or through INSTALL from within CONFIG. SYS) rather than loading them as device drivers through DEVICE statements in CONFIG. SYS. Some TSRs have no way to unload themselves, so they will remain in memory until a reboot. However unloading is possible externally, using utilities like the MARK. EXE/RELEASE. EXE combo by TurboPower Software or soft reboot TSRs which will catch a specific key combination and release all TSRs loaded after them. As the chain of ISRs is singly linked, and a TSR may store the link to its predecessor anywhere it chooses, there is no general way for a TSR to remove itself from the chain. So usually a stub must be left in memory when unloading a TSR, causing memory fragmentation. This problem gave rise to TSR cooperation frameworks such as TesSeRact and AMIS.
Прервать обмен
Для решения проблем, возникающих при использовании большого количества TSR, совместно использующих один и тот же прерывание, Ральф Д. Браун предложил метод Alternate Multiplex Interrupt Specification (AMIS) как улучшение по сравнению с ранее использовавшимися сервисами, предоставляемыми через INT 2Fh. AMIS предоставляет средства для контролируемого совместного использования программных прерываний. Он основан на протоколе совместного использования прерываний (Interrupt Sharing Protocol) от IBM, изначально разработанном для совместного использования аппаратных прерываний процессора x86. Сервисы AMIS доступны через Int 2Dh. В свое время это предложение не получило широкого распространения среди программистов и существовало наряду с несколькими другими конкурирующими спецификациями разной степени сложности.
Неисправности
Хотя TSR очень полезны и даже необходимы для преодоления ограничений DOS, они имеют репутацию источника проблем. Многие перехватывают управление операционной системой различными задокументированными или недокументированными способами, часто вызывая сбои в системе при их активации или деактивации при использовании с определенными приложениями или другими TSR. Как было объяснено выше, некоторые вирусы и другое вредоносное ПО были написаны в виде TSR и намеренно создают проблемы. Кроме того, в DOS все программы, даже те, которые требуют большой объем физической оперативной памяти, должны быть загружены в первые 640 КБ оперативной памяти (обычной памяти). TSR не являются исключением и занимают часть этих 640 КБ, делая их недоступными для других приложений. Это означало, что написание TSR было сложной задачей, требующей достижения минимально возможного размера и проверки совместимости с большим количеством программных продуктов от разных производителей – зачастую очень утомительной задачей. В конце 1980-х и начале 1990-х годов многие видеоигры на платформе PC приближались к этому пределу и оставляли все меньше места для TSR – даже для таких важных, как драйверы CD-ROM – и настройка системы так, чтобы было достаточно свободной оперативной памяти для запуска игр, сохраняя при этом необходимые TSR, превратилась в настоящее искусство. Многие геймеры имели несколько загрузочных дисков с разными конфигурациями для разных игр. В более поздних версиях MS DOS скрипты "загрузочного меню" позволяли выбирать различные конфигурации через единую запись меню. В середине и конце 1990-х годов, хотя многие игры все еще разрабатывались для DOS, ограничение в 640 КБ в конечном итоге было преодолено путем размещения части данных игры выше первого 1 МБ памяти и использования кода ниже 640 КБ для доступа к расширенной памяти (EMS) с помощью техники наложения. Альтернативным подходом, появившимся позже, было переключение процессора в защищенный режим с помощью DOS-расширителей и запуск программы в защищенном режиме. Последнее позволяло размещать код и данные в расширенной области памяти. Поскольку программирование с использованием множества наложений само по себе является сложной задачей, как только программа переставала помещаться в 512 КБ, использование расширенной памяти почти всегда осуществлялось с помощью стороннего DOS-расширителя, реализующего VCPI или DPMI, поскольку доступ к памяти выше границы 1 МБ становился намного проще и быстрее, и возможность запуска кода в этой области, когда процессор x86 переключается из реального режима в защищенный режим. Однако, поскольку DOS и большинство программ DOS работают в реальном режиме (VCPI или DPMI заставляют программу защищенного режима выглядеть как программа реального режима для DOS и остальной системы, переключаясь между двумя режимами), DOS TSR и драйверы устройств также работают в реальном режиме, и поэтому каждый раз, когда один из них получает управление, DOS-расширителю необходимо переключаться обратно в реальный режим, пока он не вернет управление, что приводит к потере времени (если они не используют такие методы, как DPMS или CLOAKING).
Возвращение
С появлением плат расширенной памяти и, особенно, процессоров Intel 80386 во второй половине 1980-х годов, появилась возможность использовать память объемом более 640 КБ для загрузки TSR-программ. Это потребовало разработки сложных программных решений, называемых менеджерами расширенной памяти. Среди таких менеджеров – QRAM и QEMM от Quarterdeck, 386MAX от Qualitas, CEMM от Compaq и, позднее, EMM386 от Microsoft. Области памяти, доступные для загрузки TSR выше 640 КБ, называются "верхними блоками памяти" (UMB), а загрузка программ в них – "высокой загрузкой". В дальнейшем менеджеры памяти стали включать программы, такие как Optimize от Quarterdeck или MEMMAKER от Microsoft, которые стремились максимизировать доступное пространство в первых 640 КБ, определяя оптимальное размещение TSR между низкой и высокой памятью.
Упадок
С развитием игр, использующих DOS-расширители (ранним примером была Doom), которые преодолели барьер в 640 КБ, многие проблемы, связанные с TSR, отпали, а с широким распространением Microsoft Windows и особенно Windows 95 (за которой последовала Windows 98) – сделавшие большинство TSR ненужными и некоторые несовместимыми – TSR постепенно устарели. Однако приложения Win16 по-прежнему могли использовать подобные приёмы TSR, например, изменять таблицу дескрипторов прерываний (IDT), поскольку Windows это допускала. Windows Me не позволяла загрузиться в DOS-ядро при её завершении, что сделало TSR бесполезными в этой системе. Семейство Windows NT (включая Windows 2000, Windows XP и более поздние версии) полностью заменило DOS и постоянно работало в защищённом или длинном режиме (позднее – только в 64-битных версиях), отключая возможность переключения в реальный режим, необходимый для работы TSR. Вместо этого эти операционные системы используют современные драйверы и сервисные фреймворки с защитой памяти и вытесняющей многозадачностью, позволяющие одновременно запускать множество программ и драйверов устройств без необходимости в специальных программных ухищрениях; ответственность за изменение таблицы прерываний была полностью возложена на ядро и его модули.