Program rezident

Un program rezident (sau program TSR , din engleză.  Terminate and Stay Resident  - „complete and stay resident”) - în sistemul de operare MS-DOS , un program care a returnat controlul shell-ului sistemului de operare ( command.com ) sau un add-on la sistemul de operare ( Norton Commander etc.), dar rămânând în memoria RAM a unui computer personal [1] . Un program rezident este activat de fiecare dată când apare o întrerupere , al cărui vector programul a fost schimbat la adresa uneia dintre procedurile sale .

Când lucrați cu MS-DOS, programele rezidente au fost utilizate pe scară largă pentru a atinge diverse obiective (de exemplu, crackere de tastatură , programe de acces LAN , manageri de imprimare întârziate , viruși ).

Prin metoda de inițializare și invocare de către sistemul de operare, programele rezidente trebuie să fie diferențiate de driverele „adevărate” MS-DOS care sunt încorporate de sistemul de operare în nucleul său la momentul pornirii.

În era sistemului de operare multitasking, programele care sunt încărcate și rulează în mod constant în fundal sunt uneori numite programe rezidente. Dar utilizarea acestui termen este incorectă în raport cu sistemul de operare multitasking.

Concepte de bază

Programele rezidente pot prelua gestionarea întreruperilor, de exemplu, cele asociate cu imprimarea sau accesarea tastaturii etc.

Astfel de programe erau de obicei rulate prin fișierul AUTOEXEC.BAT sau direct. Au interceptat întreruperi menite să funcționeze cu tastatura. De îndată ce utilizatorul apasă o combinație de taste predefinită, programul rezident este activat. O casetă de dialog a programului rezident este afișată deasupra imaginii de pe ecran.

Uneori sunt folosite programe rezidente în loc de drivere descărcabile pentru a deservi hardware-ul non-standard. În acest caz, programul rezident își poate încorpora propriul handler, prin care toate programele de aplicație pot accesa hardware-ul.

Modulele rezidente ale unor sisteme de gestionare a bazelor de date ( DBMS ) funcționează în mod similar. Programul de aplicație trimite interogări către baza de date printr-o întrerupere care este setată la pornirea unui astfel de SGBD.

Programelor rezidente sunt impuse numeroase restricții care îngreunează funcționarea unui programator.

De exemplu, TSR-urilor nu li se permite să folosească întreruperi MS-DOS după bunul plac. Acest lucru se datorează faptului că MS-DOS a fost conceput de la început ca un sistem de operare cu o singură sarcină, astfel încât funcțiile de întrerupere MS-DOS nu sunt reintre.

Să ne imaginăm o astfel de situație.

Să presupunem că un program normal numit o funcție de întrerupere MS-DOS care durează relativ mult timp pentru a se finaliza (de exemplu, scrierea pe disc).

Deoarece utilizatorul poate activa oricând programul rezident, cu excepția cazului în care se iau măsuri de precauție speciale, este posibil să apeleze din nou aceeași funcție, a cărei procesare nu a fost încă finalizată. În acest caz, vom primi un apel invers al funcției MS-DOS, care este invalidă datorită faptului că funcțiile MS-DOS nu sunt reintrante.

De asemenea, funcțiile BIOS nu sunt toate reintrante . Un program rezident poate apela în siguranță doar întreruperea INT 16h (care este proiectată să funcționeze cu tastatura). Dacă programul rezident trebuie să afișeze ceva pe ecran, atunci în loc să întrerupeți INT 10h, ar trebui să scrieți caracterele și atributele lor direct în memoria video.

Fără a lua măsuri de precauție speciale, un program rezident nu poate apela multe funcții ale bibliotecii de traducător, deoarece acestea din urmă provoacă întreruperi MS-DOS. De exemplu, funcția malloc determină o întrerupere MS-DOS pentru a determina cantitatea de memorie liberă din sistem.

Un program are două opțiuni pentru a rămâne rezident în memorie - utilizați funcția de întrerupere INT 27h sau funcția de întrerupere INT 21h 31h.

Pentru a utiliza întreruperea INT 27h, registrul de segment CS trebuie să indice către PSP-ul programului. În acest caz, offset-ul ultimului octet al programului plus un octet ar trebui să fie scris în registrul DX.

Este ușor de observat că această metodă este cea mai potrivită pentru programele comune, deoarece folosind întreruperea INT 27h este imposibil să lăsați un program rezident mai lung de 64 KB în memorie.

O altă modalitate, mai convenabilă, este să apelați funcția de întrerupere 31h INT 21h. Registrul AL ar trebui să conțină codul de terminare a programului, registrul DX ar trebui să conțină lungimea părții rezidente a programului în paragrafe. Nu mai există restricția de mai sus cu privire la dimensiunea programului.

Pentru a lăsa un program rezident în memorie, a cărui dimensiune depășește 64 KB, puteți utiliza doar ultima metodă. Nu ar trebui să vă lăsați duși de programe rezidente mari, deoarece memoria pe care o ocupă este nevoie de alte programe.

Structura programului rezident

Mai întâi, datele sunt stocate în memorie, apoi manipulatorii de întreruperi (vectori) și, în final, secțiunea de inițializare (care are un punct de intrare INIT și în acest moment este transferat controlul la pornirea programului). Sarcina principală a secțiunii de inițializare este de a stabili un rezident în memorie (este necesar doar la instalarea programului, apoi este eliminat din memorie). Această secțiune este situată în adresele superioare (deoarece nu putem decât să „tăiem” adresele superioare).

Funcțiile secțiunii de inițializare sunt următoarele

  1. Vectorii de întrerupere sunt interceptați (setarea operatorilor lor).
  2. Programul se termină în așa fel încât doar partea rezidentă să rămână în memorie.
  3. Transmiterea parametrilor către manipulatorii de întreruperi - ISR. Valorile acestor parametri sunt plasate în zona de date rezidenți (parametrul poate fi o tastă „fierbinte” pentru a apela rezidentul).
  4. Soluția la problema repornirii TSR-ului (a nu se înmulți copii ale TSR-ului în memorie), adică secțiunea de inițializare trebuie să determine dacă există sau nu un program în memorie.
  5. Eliminarea unui rezident din memorie. În primul rând, restaurați vechii vectori de întrerupere (din secțiunea de date) și, în al doilea rând, eliminați mediul TSR și PSP TSR.
  6. Funcție de minimizare a memoriei ocupate de rezident.

Inițializarea programului rezident

Pentru a utiliza întreruperea 27h, registrul de segment CS trebuie să indice către PSP-ul programului, iar offset-ul ultimului octet al programului plus un octet trebuie să fie scris în registrul DX. Este ușor de observat că acest mod de a rămâne rezident este cel mai potrivit pentru programele în format COM. Nu puteți părăsi un program rezident mai lung de 64 de kiloocteți.

O altă modalitate, mai convenabilă, este să utilizați funcția de întrerupere INT 21h 31h. În registrul AL puteți specifica codul de terminare a programului, registrul DX în acest caz ar trebui să conțină lungimea părții rezidente a programului în paragrafe. Nu mai există o limită de 64 de kilobyți pentru lungimea programului. Utilizarea acestei funcții este singura modalitate de a lăsa un program rezident mai lung de 64 de kiloocteți.

Dar nu ar trebui să vă lăsați purtat de programele TSR lungi, deoarece de obicei puteți elibera memoria ocupată de un program rezident deja inutil doar repornind sistemul de operare.

Biblioteca de funcții Quick C conține o funcție specială pentru a lăsa un program rezident în memorie. Această funcție folosește INT 21h (funcția 31h) și este numită _dos_keep(). Primul parametru al funcției este codul de ieșire (ce este scris în registrul AL), iar al doilea este lungimea părții rezidente a programului în paragrafe.

Rezolvarea problemei de repornire

Este necesar să se determine dacă TSR a început deja sau nu. Există mai multe opțiuni pentru a determina începutul TSR:

MOVAX,2ABch INT2Fh CMP AL,0FFh; dacă este egal, atunci există o copie, în caz contrar nu există nicio copie.

Pro: Utilizare largă. Dezavantaj: setul de semnături este destul de limitat (semnătura se poate potrivi accidental). Fiabilitatea este mai mică decât cea a metodei a 2-a.

Interacțiunea dintre noi și vechii manevre de întrerupere (ISR)

Când un program rezident este instalat în memorie, vectorii sunt interceptați. În acest caz, sunt posibile următoarele scheme de interacțiune între vechii și noii gestionari de întreruperi:

Returul este de la vechiul handler. Există un lanț între manipulatorii de întreruperi. Dezavantaj: Este adesea necesar ca funcțiile noi să fie executate după cele vechi. Această schemă nu este posibilă.

Nivelurile de complexitate TSR și modul în care noile ISR interacționează între ele

În funcție de interacțiunea noilor ISR, se disting diferite niveluri de complexitate.

Dacă te uiți la funcțiile BIOS în timp ce rulează, vei observa că nu sunt reintrante, aceasta se referă la funcțiile de lucru cu discul INT 13 și ecranul INT 10. Reintrarea este o proprietate care permite unui program sau un fragment. din acesta să fie întrerupt și executat cu început (din nou). Adică programul se poate întrerupe singur. Acea. Funcțiile BIOS nu sunt reintrante. În mod clasic, va trebui să scrieți un nou handler INT 13. Lăsați funcția rezidentă să fie apelată atunci când este apăsată o tastă, apoi trebuie să utilizați manipulatorul de întrerupere a tastaturii INT 9, care ar trebui să verifice steag: discul este sau nu procesat . Dacă indicatorul este zero, atunci programul nostru RF (care funcționează cu INT 13) poate fi apelat. Protecția se face numai împotriva întreruperii INT 13, deoarece restul întreruperilor utilizează funcții DOS.

Acestea sunt programe în care funcția rezidentă folosește funcții DOS (de ex. RF folosește INT 21). INT 21 nu este reintre. Ar fi posibil să se rezolve această problemă în același mod ca și cu INT 13. Dar această metodă nu funcționează, deoarece funcțiile DOS nu au întotdeauna terminație standard (există unele ieșiri care nu pot fi controlate). Aceste caracteristici includ 4C și 4B. OC are un steag special numit steag de activitate DOS, care se numește INDOS. Acest flag este 0 dacă INT 21 nu este executat și nu 0 dacă este. Acea. în program este necesar să se analizeze INDOS. Există o funcție standard pentru a obține indicatorul INDOS, acesta este AH=34h de întrerupere int 21. Această funcție are ca rezultat ES:BX -> inDOS. Această funcție 34h trebuie executată în secțiunea de inițializare. Trebuie să repare adresa acestui flag INDOS într-o locație de memorie statică și apoi să o folosească în handlere de întreruperi.

Când se execută primul grup, este posibil să se îndeplinească funcțiile unui alt grup, dar nu și primul și invers. Pentru a rezolva problema pornirii unei funcții rezidente în momentul execuției funcțiilor din primul grup, se folosește o întrerupere specială INT 28. Utilizatorul poate intercepta vectorul INT 28 și poate efectua acțiuni corespunzătoare (din al 2-lea grup). De exemplu, lăsați funcția noastră rezidentă să folosească doar al 2-lea grup de funcții. Dacă DOS este activ, atunci TSR apelează doar INT 28, iar dacă nu este activ, provoacă întreruperi numai de la cronometru. Ieșirea ecranului se poate face direct pe RAM-ul afișajului (ocolind DOS și BIOS). Pentru a lucra cu tastatura, utilizați funcțiile BIOS. Pentru a lucra cu ecranul și tastatura, sunt utilizate funcțiile celui de-al doilea grup, dar ecranul și tastatura sunt considerate ca un dispozitiv CON și lucrul cu acesta se efectuează ca și cu un fișier.

Vezi și

Note

  1. © Alexander Frolov, Grigory Frolov. MS-DOS pentru programator . frolov-lib . Preluat la 9 mai 2022. Arhivat din original la 1 decembrie 2020.