Концертная программа
- 1 year ago
- 0
- 0
Резидентная программа (или TSR-программа , от англ. Terminate and Stay Resident — «завершиться и остаться резидентной») — в операционной системе MS-DOS программа , вернувшая управление оболочке операционной системы ( command.com ) либо надстройке над операционной системой ( Norton Commander и т. п.), но оставшаяся в оперативной памяти персонального компьютера . Резидентная программа активизируется каждый раз при возникновении прерывания , вектор которого эта программа изменила на адрес одной из своих процедур .
При работе с MS-DOS резидентные программы широко использовались для достижения различных целей (например, русификаторы клавиатуры , программы доступа к локальной сети , менеджеры отложенной печати , вирусы ).
По способу инициализации и вызова операционной системой резидентные программы необходимо отличать от «настоящих» драйверов MS-DOS, встраиваемых операционной системой в своё ядро во время загрузки.
В эпоху многозадачных ОС резидентными иногда называют программы, загруженные постоянно и работающие в фоновом режиме. Но применение этого термина некорректно по отношению к многозадачным ОС.
Резидентные программы могут переключать на себя обработку прерываний, например, связанных с выводом на печать или с обращением к клавиатуре и т. д.
Такие программы обычно запускались через файл AUTOEXEC.BAT или непосредственно. Они перехватывали прерывания, предназначенные для работы с клавиатурой. Как только пользователь нажимает заранее определённую комбинацию клавиш, резидентная программа активизируется. Поверх имеющегося на экране изображения выводится диалоговое окно резидентной программы.
Иногда резидентные программы используют вместо загружаемых драйверов для обслуживания нестандартной аппаратуры. В этом случае резидентная программа может встроить свой обработчик, через который все прикладные программы смогут обращаться к аппаратуре.
Аналогично работают резидентные модули некоторых систем управления базами данных ( СУБД ). Прикладная программа посылает запросы к базе данных через прерывание, устанавливаемое при запуске такой СУБД.
На резидентные программы накладываются многочисленные ограничения, затрудняющие работу программиста.
Например, резидентным программам не разрешается использовать прерывания MS-DOS, когда вздумается. Это связано с тем, что MS-DOS с самого начала проектировалась как однозадачная операционная система, поэтому функции прерываний MS-DOS не обладают свойством реентерабельности (повторной входимости).
Представим такую ситуацию.
Пусть обычная программа вызвала какую-либо функцию прерывания MS-DOS, на выполнение которой требуется относительно много времени (например, запись на диск).
Так как пользователь может активизировать резидентную программу в любой момент, то, если не принять специальных мер предосторожности, возможен повторный вызов той же самой функции, обработка которой ещё не завершена. В этом случае мы получим повторный вызов функции MS-DOS, который недопустим из-за того, что функции MS-DOS не реентерабельны.
Функции BIOS также далеко не все реентерабельны . Резидентная программа может смело вызывать разве лишь прерывание INT 16h (которое предназначено для работы с клавиатурой). Если резидентной программе нужно вывести что-нибудь на экран, то вместо прерывания INT 10h следует выполнить непосредственную запись символов и их атрибутов в видеопамять.
Без принятия специальных мер предосторожности резидентная программа не может вызывать многие функции библиотеки транслятора, так как последние вызывают прерывания MS-DOS. Например, функция malloc вызывает прерывание MS-DOS для определения размера свободной памяти в системе.
У программы есть две возможности остаться резидентной в памяти — использовать прерывание INT 27h или функцию 31h прерывания INT 21h .
Для использования прерывания INT 27h сегментный регистр CS должен указывать на PSP программы. При этом в регистр DX следует записать смещение последнего байта программы плюс один байт.
Нетрудно заметить, что этот способ больше всего подходит для com-программ, так как с помощью прерывания INT 27h невозможно оставить в памяти резидентной программу длиннее 64 Кбайт.
Другой, более удобный способ, заключается в вызове функции 31h прерывания INT 21h . В регистре AL следует указать код завершения программы, регистр DX должен содержать длину резидентной части программы в параграфах. Здесь уже нет указанного выше ограничения на размер программы.
Для того, чтобы оставить резидентной в памяти программу, размер которой превышает 64 Кбайт, можно использовать только последний метод. Не стоит увлекаться большими резидентными программами, так как занимаемая ими память нужна другим программам.
Сначала в памяти располагаются данные, затем — обработчики прерываний (вектора) и, наконец, секция инициализации (которая имеет точку входа INIT и именно в эту точку передается управление при запуске программы). Основная задача секции инициализации — установить резидент в памяти (она нужна лишь при установке программы, потом её из памяти удаляют). Эту секцию располагают в старших адресах (так как «обрезать» мы можем только старшие адреса).
Для использования прерывания 27h сегментный регистр CS должен указывать на PSP программы, а в регистре DX должно быть записано смещение последнего байта программы плюс один байт. Нетрудно заметить, что этот способ остаться резидентной больше всего подходит для программ в формате COM. Вы не сможете оставить резидентной программу длиннее 64 килобайт.
Другой, более удобный способ — использовать функцию 31h прерывания INT 21h. В регистре AL вы можете указать код завершения программы, регистр DX в этом случае должен содержать длину резидентной части программы в параграфах. Здесь уже нет ограничения 64 килобайта на длину программы. Использование этой функции — единственная возможность оставить резидентной программу длиннее 64 килобайт.
Но не стоит увлекаться длинными TSR-программами, так как обычно освободить память, занимаемую ставшей уже ненужной резидентной программой, можно только с помощью перезагрузки операционной системы.
Библиотека функций Quick C содержит специальную функцию для оставления программы резидентной в памяти. Эта функция использует прерывание INT 21h (функция 31h) и имеет имя _dos_keep(). Первый параметр функции — код завершения (то, что записывается в регистр AL), а второй — длина резидентной части программы в параграфах.
Нужно определить, была уже запущена TSR или нет. Возможно несколько вариантов определения запуска TSR:
MOV AX,2ABCh INT 2Fh CMP AL,0FFh; если равно, то копия есть, иначе копии нет.
Достоинство: Широкое использование. Недостаток: набор сигнатуры достаточно ограничен (сигнатура может случайно совпасть). Надёжность меньше, чем у 2-го метода.
При установке резидентной программы в память осуществляется перехват векторов. При этом между старыми и новыми обработчиками пpерываний возможны следующие схемы взаимодействия:
Возврат осуществляется из старого обработчика. Возникает цепочка между обработчиками пpерываний. Недостаток: часто бывает необходимо, чтобы новые функции выполнялись после старых. По этой схеме это невозможно.
В зависимости от взаимодействия новых ISR выделяют различные уровни сложности.
Если посмотреть на функции BIOS во время их работы, то можно заметить, что они нереентерабельны, это относится к функциям работы с диском INT 13 и экраном INT 10. Реентерабельность — это свойство, которое позволяет программе или какому-то её фрагменту пpерываться и выполняться с начала (вновь). То есть программа может пpерывать сама себя. Т.о. функции BIOS нереентерабильны . Классически нужно будет написать новый обработчик INT 13. Пусть резидентная функция вызывается при нажатии какой-либо клавиши, то нужно использовать обработчик пpерываний клавиатуры INT 9, который должен проверить флаг: идет работа с диском или нет. Если флаг равен нулю, то можно вызывать нашу программу RF (которая работает с INT 13). Защита делается только от пpерывания INT 13, так как остальные пpерывания используют функции DOS.
Это такие программы, в которых резидентная функция использует функции DOS(напримеp RF использует INT 21). INT 21 нереентерабильна . Можно бы было решить эту проблему так же, как и с INT 13. Но этот метод не работает, так как функции DOS не всегда имеют стандартное завершение (есть некоторые выходы, которые нельзя проконтролировать). К таким функциям относятся 4C и 4B. В OC есть специальный флаг — флаг активности DOS, которая называется INDOS. Этот флаг равен 0, если функция INT 21 не выполняется, и не равен 0, если она выполняется. Т.о. в программе необходимо анализировать INDOS. Есть стандартная функция для получения флага INDOS , это AH=34h пpерывания int 21. В результате этой функции ES:BX -> inDOS. Эту функцию 34h надо выполнить в секции инициализации . Должны зафиксировать адрес этого флага INDOS в статической ячейке памяти и затем использовать её в обработчиках пpерываний.
Когда выполняется 1-я группа, то можно выполнять функции другой группы, но не первой, и наоборот. Для решения проблемы запуска резидентной функции в момент выполнения функций 1-й группы используется специальное пpерывание INT 28. Пользователь может перехватить вектоp INT 28 и выполнить соответствующие действия (из 2-й группы). Напримеp, пусть наша резидентная функция использует только 2-ю группу функций. Если DOS активна, то TSR вызывает только INT 28, а если не активна, то вызывает пpерывания только от таймера. Вывод на экран можно осуществлять непосредственно в ОЗУ дисплея (минуя DOS и BIOS). Для работы с клавиатурой используют функции BIOS. Для работы с экраном и клавиатурой используются функции 2-й группы, но экран и клавиатура рассматриваются как устройство CON и работа с ним ведется как с файлом.