lekcja20.txt

(14 KB) Pobierz
LEKCJA 20 - JE�LI PROGRAM POWINIEN URUCHOMI� INNY PROGRAM...  
________________________________________________________________ 
W trakcie tej lekcji dowiesz si�, jak w C++ mo�na programowa�  
* procesy potomne  
* pisa� programy rezyduj�ce w pami�ci (TSR)  
________________________________________________________________ 
 
O programach rezydentnych (TSR) i procesach potomnych.  
 
Warunek zewn�trznej zgodno�ci z poprzednimi wersjami DOS  
wyra�nie hamuje ewolucj� systemu MS DOS w kierunku "powa�nych"  
system�w operacyjnych umo�liwjaj�cych prac� wieloprogramow� w  
trybie "multiuser", "multitasking" i "time sharing". Pewn�  
namiastk� pracy wieloprocesowej daj� nam ju� DOS 5/6 i Windows  
3.1. Mo�na ju� otwiera� wiele okien program�w jednocze�nie,  
mo�na np. drukowa� "w tle", mo�na wreszcie pisa� rezyduj�ce  
stale w pami�ci programy klasy TSR (ang. Terminated and Stay  
Resident) uaktywniaj�ce si� "od czasu do czasu".  
 
O bloku PSP. 
 
System DOS przydziela programom blok - "nag��wek" wst�pny  
nazywany PSP (ang. Program Segment Prefix). Blok ten zawiera  
informacje o stanie systemu DOS w momencie uruchamiania programu 
 
(nazywanego tu inaczej procesem). Znajduj� si� tam informacje o  
bie��cym stanie zmiennych otoczenia systemowego (ang.  
environment variables) i parametrach uruchomieniowych. Blok PSP  
zajmuje 256 bajt�w na pocz�tku kodu programu w zakresie adres�w: 
 
 
CS:0000 ... CS:0100  (hex)  
 
W�a�ciwy kod programu zaczyna si� zatem od adresu CS:0100.  
Interpreter rozkaz�w systemu DOS �aduje programy do pami�ci  
pos�uguj�c si� funkcj� systemow� nr 75 (4B hex). Wszystko jest  
proste dop�ki mamy do czynienia z programem "kr�tkim" typu  
*.COM. Je�li jednak�e program uruchamiany jest w wersji  
"d�ugiej" - *.EXE, dowolna mo�e by� nie tylko d�ugo�� pliku, ale 
 
tak�e pocz�tkowa zawarto�� rejestr�w CS, SS, SP i IP. W plikach  
typu *.EXE pocz�tek bloku PSP wskazuj� rejestry DS (DS:0000) i  
ES. W Borland C++ masz do dyspozycji specjaln� funkcj� getpsp()  
przy pomocy kt�rej mo�esz uzyska� dost�p do bloku PSP programu.  
Kr�tki przyk�ad zastosowania tej funkcji poni�ej:  
 
/* Przyk�ad zastosowania funkcji getpsp(): */  
 
# include <stdio.h>  
# include <dos.h>  
  
main()  
{  
   static char TAB[128];  
   char far *ptr;  
   int dlugosc, i;  
  
   printf("Blok PSP: %u \n", getpsp());  
  
   ptr = MK_FP(_psp, 0x80);  
   dlugosc = *ptr;  
  
   for (i = 0; i < dlugosc; i++)  
      TAB[i] = ptr[i+1];  
  
   printf("Parametry uruchomieniowe: %s\n", TAB);  
  
}  
  
W normalnych warunkach po wykonaniu "swojej roboty" program  
zostaje usuni�ty z pami�ci operacyjnej (czym zajmuje si� funkcja 
 
systemowa nr 76 - 4C (hex)). Aby tak si� nie sta�o, program  
mo�e:  
 
* uruchomi� sw�j proces (program) potomny;  
* wyj�� "na chwil�" do systemu DOS - tj. uruchomi� jako sw�j  
proces potomny interpreter COMMAND.COM;  
* przekaza� sterowanie programowi COMMAND.COM pozostaj�c w  
pami�ci w postaci "u�pionej" oczekuj�c na uaktywninie.  
 
Poni�ej kilka prostych przyk�ad�w uruchamiania jednych proces�w  
przez inne w Borland C++:  
 
/* Funkcja execv(): uruchomienie programu "potomnego"*/  
 
# include <process.h>  
# include <stdio.h>  
# include <errno.h>  
  
void main(int argc, char *argv[])  
{  
   int i;  
  
   printf("Parametry uruchomieniowe:");  
   for (i=0; i<argc; i++)  
      printf("\n%d)  %s", i, argv[i]);  
  
printf("Przekazuje parametry do procesu 2 par_1, par_2...\n");  
   execv("CHILD.EXE", argv);  
.... 
exit (2);  
}  
 
[P074.CPP] 
 
/* Funkcja system() - na chwil� do DOS */  
 
# include <stdlib.h>  
# include <stdio.h>  
  
void main()  
{  
   printf("Wyjscie do DOS i wykonanie jednego rozkazu:\n");  
   system("dir > c:\plik.dir");  
}  
  
 
/* Funkcje grupy spawn...() : spawnl() */  
  
# include <process.h>  
# include <stdio.h>  
# include <conio.h>  
  
void main()  
{  
   int rezultat;  
   rezultat = spawnl(P_WAIT, "program.exe", NULL);  
   if (rezultat == -1)  
   {  
      perror(" Fiasko !");  
      exit(1);  
   }  
}  
  
  
/* Funkcja spawnle() */  
  
# include <process.h>  
# include <stdio.h>  
# include <conio.h>  
  
void main()  
{  
   int rezultat;  
  
   rezultat = spawnle(P_WAIT, "program.exe", NULL, NULL);  
   if (rezultat == -1)  
   {  
      perror("Fiasko !");  
      exit(1);  
   }  
}  
  
Zagadnienie uruchamiania program�w potomnych (ang. child  
process) przez programy macie�yste (ang. parent process) jest  
rozpracowane w C++ do�� dok�adnie i zarazem obszernie. Istnieje  
wiele gotowych funkcji bibliotecznych, z us�ug kt�rych mo�esz tu 
 
skorzysta�. Wszystko to nie jest jednak "prawdziwym" programem  
TSR. Przyjrzyjmy si� zatem dok�adniej dopuszcalnym przez system  
DOS sposobom zako�czenia programu nie powoduj�cym usuni�cia  
programu z pami�ci.  
 
Je�li program rezydentny jest niewielki (kod < 64 K), mo�emy  
zako�czy� program pos�uguj�c si� przerywaniem INT 39 (27 hex).  
Je�li natomiast zamierzamy pos�ugiwa� si� d�u�szymi programami,  
mamy do dyspozycji funkcj� systemow� nr 49 (31 hex). Nale�y tu  
zwr�ci� uwag�, �e zako�czenie programu w taki spos�b (z  
pozostawieniem w pami�ci) nie spowoduje automatycznego  
zamkni�cia plik�w, a jedynie opr�nienie bufor�w. Programy  
rezydentne dzieli si� umownie na trzy kategorie:  
 
[BP] - background process - procesy dzia�aj�ce "w tle";  
[SV] - services - programy us�ugowe - np. PRINT;  
[PP] - pop up programs - uaktywniane przez okre�lon� kombinacj�  
       klawiszy;  
 
System DOS dysponuje tzw. przerywaniem multipleksowym  
(naprzemiennym) wykorzystywanym cz�sto przez programy  
rezydentne. Jest to przerywanie nr INT 47 (2F hex). MS DOS  
za�atwia takie problemy funkcjami nr 37 (25 hex) - zapisanie  
wektora przerywania i 53 (35 hex) - odczytanie wektora  
przerywania. 
 
Z jakich funkcji C++ mo�na skorzysta�? 
 
W C++ masz do dyspozycji par� funkcji getvect() i setvect()  
(ang. GET/SET VECTor - pobierz/ustaw wektor przerywania).  
Poni�ej kr�tkie przyk�ady zastosowa� tych funkcji.  
 
/* Opcja:  Options | Compiler | Code generation | Test Stack  
Overflow  powinna zosta� wy��czona [ ] (off)  */  
 
# include "stdio.h"  
# include "dos.h"  
# include "conio.h"  
  
/* INT 28 (1C hex) - Przerywanie zegarowe */  
  
void interrupt ( *oldhandler)(void);  
int licznik = 0;  
  
void interrupt handler(void)  
{  
/* Inkrementacja globalnej zmiennej licznik */  
   licznik++;  
  
/* Wywolujemy stary "handler" zegara */  
   oldhandler();  
}  
  
void main()  
{  
/* Zapami�taj poprzedni wektor przerywania 28 */  
   oldhandler = getvect(28);  
  
/* Zainstaluj now� funkcje obslugi przerywania */  
   setvect(28, handler);  
  
/* Inkrementuj licznik */  
   for (; licznik < 10; ) printf("licznik: %d\n",licznik);  
  
//odtworz stara funkcje obslugi przerywania: interrupt handler  
 
   setvect(28, oldhandler);  
}  
 
 
# include <stdio.h>  
# include <dos.h>  
  
void interrupt nowa_funkcja(); // prototyp funkcji - handlera 
  
void interrupt (*oldfunc)(); /* interrupt function pointer */  
 
int warunek = 1;  
  
main()  
{  
  printf("\n [Shift]+[Print Screen] = Quit \n");  
  printf("Zapamietaj, i nacisnij cosik....");  
  while(!kbhit()); 
 
  /* zapamietaj stary wektor */  
  oldfunc  = getvect(5);  
  /* INT 5 to przerywanie Sys Rq, albo Print Screen */ 
 
  /* zainstaluj nowa funkcje obslugi: interrupt handler */  
  setvect(5, nowa_funkcja);  
  
  while (warunek) printf(".");  
  
   /* Odtworz stary wektor przerywania */  
   setvect(5, oldfunc);  
  
  printf("\n Udalo sie... nacisnij cosik...");  
  while(!kbhit()); 
}  
 
/* Definicja nowego handlera */ 
void interrupt nowa_funkcja()  
{  
  warunek = 0;    
/* jesli warunek == 0, petla zostanie przerwana*/  
}  
  
Je�li nasz program zamierza korzysta� z przerywania  
multipleksowego INT 47 (2F hex), nale�y pami�ta�, �e przerywanie 
 
to wykorzystuj� tak�e inne programy systemowe. Rozr�nia� te  
programy mo�na przy pomocy identyfikator�w (podaj� dziesi�tnie): 
 
01  - PRINT.EXE  
06  - ASSIGN.COM  
16  - SHARE.EXE  (10 hex)  
26  - ANSI.SYS  
67  - HIMEM.SYS  
72  - DOSKEY.COM  
75  - TASK SWITCHER  
173 - KEYB.COM  
174 - APPEND.EXE  
176 - GRAFTABL.COM  
183 - APPEND.EXE  
 
Identyfikator programu TSR jest przekazywany za po�rednictwem  
rejestru AH.  
 
System DOS jest na razie systemem w zasadzie jednozadaniowym i  
jednou�ytkownikowym, w kt�rym zasoby s� przydzielane procesom  
kolejno (ang. serially reusable resources). Aby uchroni� si�  
przed potencjalnym konfliktem, powinni�my upewni� si�, czy DOS  
"nic nie robi". Cz�sto stosowan� "sztuczk� techniczn�" jest  
zastosowanie flag ErrorMode i InDos systemu oraz wykorzystanie  
mechanizm�w przerywa� nr 36 i 40 (24 i 28 hex). Przydatn�  
informacj� jest tak�e identyfikator programu - PID. Na tak�  
ewntualno�� Borland C++ dysponuje makrem getpid zdefiniowanym w  
pliku nag��wkowym <PROCESS.H>:  
 
# define  getpid()   (_psp)  
 
Inn� przydatn� funkcj� mo�e okaza� si� keep() (ang. keep  
resident - pozosta� rezydentny). Oto kr�tki przyk�ad  
zastosowania tej funkcji - zn�w z wykorzystaniem przerywa�  
zegarowych.  
 
# include <dos.h>  
 
# define INTR 0x1C       /* przerywanie INT 28 */ 
# define ATTR 0x7900  
 
/* ograniczenie wielko�ci sterty (heap length) i stosu (stack  
length):                                                      */ 
extern unsigned _heaplen = 1024;  
extern unsigned _stklen  = 512;  
  
void interrupt ( *oldhandler)(void);  
  
void interrupt handler(void)  
{  
   unsigned int (far *ekran)[80]; ...
Zgłoś jeśli naruszono regulamin