Biologie | Chimie | Didactica | Fizica | Geografie | Informatica | |
Istorie | Literatura | Matematica | Psihologie |
Serviciile oferite de S.O. se apeleaza prin intermediul intreruperilor. Pentru DOS nivelul de intrerupere folosit pentru apelul serviciilor sistem este 21h (INT 21h).
Ca regula generala :
registrul AH contine numarul serviciului.
ceilalti registri contin informatii suplimentare necesare apelului respectiv.
in urma executiei, rezultatele se vor gasi in diferite registre.
cele mai multe servicii, in urma apelului, daca a aparut o eroare, pozitioneaza CARRY, iar in AX se intoarce un cod de eroare.
Exemplificare : pentru functia 36h, care furnizeaza spatiul liber disponibil pe disc avem:
AH <- 36h - codul serviciului
DL <- id. disc - numarul discului (0 - disc implicit, 1 - A, 2 - B etc.)
La intoarcerea din apel :
AX - contine numarul de sectoare/cluster sau FFFFh pentru eroare.
BX - numarul de clustere disponibile.
CX - numarul de octeti/sector.
DX - numarul total de clustere.
Ca si secventa de cod in limbaj de asamblare :
mov AH,36h
mov DL,1 ; discul A
int 21h
cmp AX,0FFFFh
je err_rtn ; salt la rutina de tratare a erorii
mov sec_du,AX ; nr. sectoare/cluster
mov avl_du,BX ; nr. clustere disponibile
mov byt_sec,CX ; nr. octeti/sector
Pentru ca functiile DOS sa poata fi apelate din limbajul C, exista cateva functii de biblioteca : bdos, bdosptr, int86, int86x, intdos, intdosx, intr, geninterrupt. Prototipul acestor functii se gaseste in dos.h.
Functiile intdos, intdosx apeleaza servicii DOS prin intermediul lui INT 21h. Mai generale sunt functiile int86, int86x (ofera accesul la registrii DS si ES).
Structurile de date care intervin in aceste apeluri (aceste structuri sunt puse in corespondenta cu registrii microprocesorului) :
struct WORDREGS ;
struct BYTEREGS ;
struct SREGS ;
union REGS ;
struct REGPACK ;
Prototipurile functiilor sunt urmatoarele (toate sunt definite ca int) :
int bdos(int dosfun, unsigned dosdx, unsigned dosal);
primeste ca argumente :
numarul serviciului in dosfun
continutul registrului DX in dosdx
continutul registrului AL in dosal
valoarea returnata este continutul registrului AX dupa apelul DOS.
int bdosptr(int dosfun, void *arg, unsigned dosal);
exista unele servicii care solicita o zona de memorie (in care sa se memoreze mai multe informatii decat incap in registri, de aceea se transmite un pointer).
int int86(int intno, union REGS *in, union REGS *out);
primeste numarul intreruperii si doi pointeri. Cade in sarcina programatorului sa completeze registrii (pentru apeluri DOS : intno = 21h, in.h.ah = numarul serviciului).
int int86x(int intno, union REGS *in, union REGS *out, struct SREGS *sregs);
Functiile int86 si int86x copiaza continutul variabilei in in registrii procesorului, iar dupa apel copiaza in out continutul rezultat al registrilor.
Functiile intdos si intdosx nu mai contin numarul de intrerupere.
int intdos(union REGS *in, union REGS *out);
int intdosx(union REGS *in, union REGS *out, struct SREGS *sregs);
In caz de eroare toate returneaza ca valoare continutul registrului AX. Informatii suplimentare se gasesc in variabila "globala" doserrno. Mai exista si variabila errno care este pozitionata in urma unor functii mai evoluate (nu cele care lucreaza direct cu intreruperi).
Exemplu :
Se considera urmatorul program, care determina spatiul disponibil pe disc:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
long free_space(int drive) /* primeste ca argument drive-ul */
void main(int argc, char *argv[])
drive = (int)(toupper(*argv[1]) - 'A' + 1);
if ((space = free_space(drive)) == -1)
printf('Unitate invalida !n');
else
printf('Spatiul liber pe discul %c: este %ld octeti.n',
*argv[1], space);
exit(0);
Programul se mai putea face apeland o functie de biblioteca getdfree.
In functia free_space avem : int86(0x21, &inregs, &outregs), ar fi fost suficienta o singura variabila, astfel : int86(0x21, &inregs, &inregs), asta presupunand ca dupa apel nu ne intereseaza continutul acesteia de dinaintea apelului (folosim aceeasi zona de memorie).
In primele versiuni operatiile asupra fisierelor se efectuau folosind FCB-uri (File Control Block), aceasta fiind preluata de la sistemul CP/M.
In versiunile mai noi functiile cele mai folosite au devenit cele care lucreaza cu indici de fisier (File Handle) - fiecare fisier este identificat printr-un numar, astfel programatorul lucreaza doar cu un numar intreg, restul operatiilor fiind preluate de S.O.
Fisierele standard au urmatorii indici :
stdin = 0
stdout = 1
stderr = 2
prn = 3
aux = 4
In urmatoarele se vor enumera cele mai folosite functii :
3Ch : functia de creare a unui fisier. Creaza un fisier cu numele precizat de utilizator si ii asigneaza un indice (in functie de cati indici erau deja asignati).
5Bh : functia care creaza un fisier numai daca numele specificat este unic (daca fisierul exista atunci returneaza un cod de eroare).
5Ah : functia care creaza un fisier temporar cu nume unic. Numele acestui fisier se formeaza din cifre hexa otinute din data si ora curenta. Acest fisier de obicei va trebui sters la terminarea programului.
41h : functia de stergere a unui fisier.
3Dh : functia de deschidere a unui fisier specificat intr-un mod de asemenea specificat (citire, scriere, citire-scriere etc.).
3Eh : functia de inchidere a unui fisier specificat prin indice. Indicele respectiv este eliberat, astfel incat va putea fi folosit pentru lucrul cu un alt fisier.
3Fh : functia de citire dintr-un fisier. Se furnizeaza indicele si numarul de octeti care se vor citi. Octetii cititi se depun la o adresa, deasemenea specificata de programator. Se intoarce numarul de octeti cititi.
40h : functia de scriere intr-un fisier. Se furnizeaza indicele si numarul de octeti care se vor scrie. Deasemenea se specifica adresa de unde se vor prelua octetii de scris. Se intoarce numarul de octeti scrisi.
42h : functia de pozitionare a pointerului de citire-scriere in fisier. Se furnizeaza indicele, pozitia relativa la care urmeaza sa fie pozitionat pointerul si locul de referinta, fata de care s-a comunicat pozitia relativa, care poate fi : inceputul, pozitia curenta sau sfarsitul fisierului. Pentru ca aceasta functie sa se poata executa corect fisierul trebuie sa fie deschis.
45h : functia care face duplicarea unui indice de fisier. Aceasta functie creaza un nou indice care se refera la acelasi canal de intrare/iesire ca si cel original. Noul indice mosteneste drepturile de acces precizate pentru primul indice.
46h : functia de redirectare. Aceasta functie face ca doi indici de fisier sa se refere la acelasi fisier fizic, se presupune ca ambii indici existau deja si corespundeau unor canale de intrare/iesire diferite.
Diferenta dintre 45h si 46h : functia 45h este utila pentru golirea bufferelor (un fel de flush) cu indicele duplicat se poate forta inchiderea fisierului, astfel golindu-se bufferele DOS. Secventa este mai rapida decat daca am face acelasi lucru cu un singur indice close si apoi open. Versiunile mai noi ale DOS au o functie speciala de golire a bufferelor. Functia 46h se folosese la redirectarea intrarilor si iesirilor.
Exemplu :
Pentru a exemplifica folosirea functiilor pentru gestionarea fisierelor consideram urmatorul exemplu :
/* Programul este conceput pentru modelul de memorie SMALL ! */
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#define SIZE 512 /* numar octeti pe care ii citim sau scriem */
int copiaza(char *srs, char *dst)
while (nbytes == SIZE);
/* cand s-au citit mai putini octeti decat cati s-au precizat */
/* in apel, ciclul se opreste */
/* inchidere fisiere */
regs.h.ah = 0x3E;
regs.x.bx = idsrs;
int86(0x21, ®s, ®s);
regs.h.ah = 0x3E;
regs.x.bx = iddst;
int86(0x21, ®s, ®s);
/* ca valoare de intoarcere dam valoarea indicatorului CARRY */
/* care ne spune cum s-a inchis fisierul destinatie */
return ((int)regs.x.cflag);
/* programul este valabil pentru cazuri pentru care nu avem nume */
/* ambigue de fisiere, adica sa nu contina * sau ? */
int main(int argc, char *argv[])
if (copiaza(argv[1], argv[2]) == 0)
printf('Program terminat normal.n');
else
printf('Eroare la copiere.n');
exit(0);
In urmatoarele se vor enumera functiile folosite pentru gestionarea cataloagelor :
39h : functia de creare a unui catalog. Parametrii (cum ar fi numele catalogului) se comunica in registre.
3Ah : functia de stergere a unui catalog. Se admite stergerea catalogului numai daca acesta este gol.
3Bh : functia de schimbarea catalogului curent.
43h : functia pentru citirea/pozitionarea atributelor unui fisier.
47h : functia de obtinere a numelui catalogului curent.
4Eh : functia pentru gasirea primului fisier care corespunde unui tipar dat. Determina in catalogul curent numele primului fisier care se poate pune in corespondenta cu tiparul dat. Informatii despre fisierul gasit (data, atribute, lungimea fisierului etc.) se furnizeaza in zona de transfer cu discul (DTA).
4Fh : functia pentru gasirea urmatorului fisier care corespunde unui tipar dat. Se utilizeaza dupa un apel la 4Eh. Gaseste urmatorul fisier sau spune ca nu exista sau nu mai exista fisier corespunzator tiparului dat.
56h : functia pentru schimbarea numelui unui fisier. Prin aceasta functie se poate face si mutarea unui fisier intr-un alt catalog, dar doar pe acelasi disc.
57h : functia pentru citirea/pozitionarea datei si orei unui fisier.
Exemplu :
Programul afiseaza numele catalogului curent de pe o unitate logica specificata. Daca nu se specifica, la apelul programului, unitatea logica, se considera unitatea implicita. Se lucreaza cu modelul de memorie SMALL.
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
void main(int argc, char *argv[])
printf('Catalog curent : %c%c%sn',
drive ? ('A'+drive-1) : ' ', drive ? ':' : 'b', nume);
exit(0);
Urmatorul program schimba catalogul curent. In program se va ilustra si lucrul cu pointeri FAR.
#include <stdio.h>
#include <dos.h>
static char buffer[80];
int main(void)
Dispozitivele standard orientate pe caractere sunt : consola (tastatura si monitorul), imprimanta, porturile seriale, porturile paralele. Daca intr-un program se folosesc aceste functii, actunci este permisa redirectionarea intrarii si/sau iesirii standard a acelui program.
Se recomanda utilizarea subserviciilor oferite de functia 44h. In rutinele pentru tratarea erorilor critice, in driverele de periferice trebuiesc folosite functiile vechi (cele cu numere mici).
In urmatoarele se enumera functiile din aceasta categorie :
01h : citire cu ecou de la tastatura. Codul caracterului citit se va gasi in AL.
02h : afisarea unui caracter. Codul caracterului de afisat trebuie incarcat in DL.
03h : citire caracter de la intrarea auxiliara COM1. Codul caracterului citit se va gasi in AL.
04h : trimiterea unui caracter la iesirea auxiliara COM1. Codul caracterului de trimis trebuie incarcat in DL.
05h : tiparirea unui caracter (LPT1). Codul caracterului de tiparit trebuie incarcat in DL.
06h : intrare/iesire directa, fara ecou de la tastatura, respectiv pe ecran. Se preia un caracter de la STDIN daca exista un caracter pregatit si daca in DL se gaseste FFh, sau se trimite un caracter la STDOUT, daca in DL se gaseste altceva decat FFh (adica codul unui caracter).
07h : simpla citire fara ecou de la tastatura. Se asteapta pana cand exista un caracter disponibil.
Obs. : Functiile 06h si 07h nu trateaza caracterele speciale.
08h : citire fara ecou de la tastatura, se deosebeste de 06h si 07h prin faptul ca se recunosc tastele speciale CTRL-Break etc., acestea generand o intrerupere pe nivelul 23h.
09h : afisarea unui sir de caractere. DS:DX trebuie sa indice spre adresa sirului de caractere terminat cu caracterul '$'.
0Ah : intrare prin zona tampon de la tastatura. Citeste un sir de caractere de la STDIN pana la aparitia caracterului CR (Carriage Return), sirul fiind memorat intr-o zona tampon cu urmatorul format :
Fig. 4.2-
0Bh : verificarea starii intrarii. Se determina daca exista sau nu un caracter disponibil la intrare (AL = 00h <=> nu exista, AL = FFh <=> exista ).
0Ch : stergerea zonei tampon de intrare si citire de la tastatura. Se curata zona tampon de intrare dupa care se apeleaza una din functiile de citire caractere (01h, 06h, 07h, 08h, 0Ah) al carui cod este introdus in registrul AL.
Consideram in aceasta grupa functiile care permit obtinerea de informatii sau controlul echipamentelor periferice standard, precum si functia speciala 44h, care permite lucrul cu orice periferic, daca driverele perifericului exista si respecta anumite restrictii :
19h : obtinerea unitatii implicite (curente). Rezultatul se intoarce in AL (0 - A, 1 - B etc. - aceasta este o exceptie, deoarece numerotarea discurilor in acest caz porneste de la 0 si nu de la 1).
0Eh : selectarea unitatii implicite (curente). Ca si parametru in DL se specifica numarul discului. La revenire functia furnizaeaza in AL numarul de unitati logice existente.
2Fh : obtinerea adresei zonei de transfer cu discul (DTA). Functia furnizeaza in ES:BX adresa DTA.
1Ah : pozitionarea adresei DTA. In DS:DX se comunica adresa noului DTA. Zona de transfer cu discul este folosita la toate accesele la fisiere prin FCB-uri si este implicata in functiile de regasirea fisierelor.
1Bh : obtinerea informatiilor despre tabela de alocare a fisierelor FAT, a unitatii curente. Informatiile obtinute sunt : AL - numar sectoare/cluster, CX - numar octeti/sector, DX - numar unitati de alocare.
1Ch : obtinerea informatiilor despre FAT, a unei unitati specificate. Se comporta ca si precedentul dar cere ca parametru de intrare in DL numarul unitatii (0 - implicit, 1 - A, 2 - B etc.).
36h : obtinerea spatiului liber pe disc.
44h : controlul general de intrare/iesire (IOCTL). Realizeaza schimbul de informatii dintre aplicatii si echipamente ne-standard. Este prevazuta cu mai multe subfunctii prin care se realizeaza urmatoarele :
a) Obtinerea informatiilor despre un echipament.
b) Pozitionarea informatiilor de comanda pentru un echipament.
c) Citire in mod caracter.
d) Scriere in mod caracter.
e) Citire in mod bloc.
f) Scriere in mod bloc.
g) alte functii.
Exemplu :
Program care afiseaza numele si lungimea tuturor fisierelor normale din catalogul curent. Deasemenea se mai afiseaza lungimea totala a acestor fisiere. O forma simplificata a comenzii DIR.
In zona DTA se respecta urmatoarea conventie :
00h - 14h - rezervati
15h - atributele fisierului
16h - 17h - ora ultimei modificari
18h - 19h - data ultimei modificari
1Ah - 1Dh - lungimea fisierului
1Eh - 2Bh - numele si extensia fisierului
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <dos.h>
int gata;
char ndta[256];
char *dta;
int find_first(char *tipar);
int find_next(void);
void set_dta(char dta[]);
void get_dta(void);
char *tipar = "*.*";
void main(void)
printf("Lungimea totala fisiere = %ldn", total);
int find_first(char *tipar)
int find_next(void)
void set_dta(char dta[])
void get_dta(void)
Functiile pentru gestionarea memoriei si a proceselor se prezinta impreuna deoarece o utilizare importanta a functiilor de gestionare a memoriei este aceea de a elibera suficienta memorie pentru a putea rula un proces fiu :
48h : alocarea memoriei. Incearca sa aloce dinamic, procesului curent, un numar de paragrafe de memorie specificat in registrul BX, daca in BX se va introduce 0xFFFF se va aloca toata memoria disponibila. In caz ca alocarea reuseste, adresa de segment pentru memoria alocata este returnata in AX, in caz de eroare se va pozitiona indicatorul CARRY.
49h : eliberarea memoriei alocate. Face disponibil un bloc de memorie care a fost alocat anterior cu functia 48h. Adresa blocului va fi data prin ES.
4Ah : modificarea alocarii memoriei. Incearca sa modifice dimensiunea unui bloc de memorie alocat anterior cu 48h. Noua dimensiune dorita se incarca in BX iar adresa de segment a zonei in ES. La lansarea normala in executie a unui program, acestuia i se aloca toata memoria disponibila, deci pentru a putea lansa in executie un proces fiu, trebuie mai intai redusa dimensiunea blocului de memorie a carui adresa de inceput este PSP-ul.
58h : citirea/pozitionarea strategiei de alocare a memoriei. Se poate face alocare de tipul First Fit (ceea ce inseamna prima potrivire), Best Fit (se examineaza toata lista si se aloca blocul cel mai mic care satisface cerintele), Last Fit (se parcurge lista si se aloca ultima potrivire). Prin continutul registrului AL se alege citirea (00h) sau pozitionarea (01h), iar in BX se va gasi/transmite strategia (00h, 01h, 02h).
4Bh : incarcarea si executarea unui program. Permite ca programul apelant sa incarce in memorie un alt program (AL = 03h) si eventual sa-l lanseze in executie (AL = 00h). Numele fisierului executabil care contine programul ce va fi incarcat se precizeaza printr-un sir ASCIIZ a carui adresa se incarca in DS:DX. Tot ca parametru de intrare in registrele ES:BX se introduce un pointer la un bloc de parametri care se vor transmite noului program. Acest bloc de parametri are o structura diferita dupa cum se cere lansarea in executie sau numai incarcare.
Pentru lansarea in executie :
Depl. |
Lung. |
Semnificatie |
00h |
Adresa de segment a ambiantei (pentru 0 se copiaza ambianta parintelui). |
|
02h |
Adresa de segment si deplasamentul pentru o linie de comanda de maximum 128 octeti, transmisa programului. |
|
06h |
Adresa primului FCB. |
|
0Ah |
Adresa celui de-al doilea FCB. |
Tabelul 4.2-
Pentru incarcare :
Depl. |
Lung. |
Semnificatie |
00h |
Adresa de segment la care se incarca programul. |
|
02h |
Factor de relocare al programului. |
Tabelul 4.2-
Obs.: Cea mai simpla metoda de a incarca si executa un alt program consta in lansarea in executie a unei noi copii a procesorului de comenzi command.com careia i se transmite o linie de comanda avand prevazut comutatorul /c. Functia 4Bh cu AL = 03h este folosita pentru incarcarea de segmente ale unui program cu segmente suprapuse si deasemenea pentru incarcarea unor drivere.
4Ch : terminarea executiei unui proces. Un program apeleaza aceasta functie pentru a anunta catre sistem terminarea executiei si predarea controlului catre procesul parinte. In mod uzual procesului parinte i se poate transmite si un cod de intoarcere de un octet. Inainte de terminare se inchid fisierele si se reancarca vectorii de intrerupere pentru nivelele 22h, 23h si 24h. Deasemenea se realizeaza si eliberarea memoriei.
4Dh : obtinerea codului de retur al unui proces fiu. Aceasta functie intoarce codul transmis de un proces fiu care s-a terminat fie prin functia 4Ch fie prin 31h. Valoarea codului de retur este in AX. In AL este codul returnat de proces, iar in AH este un alt cod, care precizeaza conditiile de terminare (AH = 0 - terminare normala, 1 - proces terminat cu CTRL-Break sau CTRL-C, 2 - eroare critica de periferic, 3 - s-a facut terminarea prin 31h - TSR).
62h : obtinerea adresei PSP. Adresa de segment se intoarce in BX.
31h : realizeaza revenirea in procesul parinte in asa fel incat programul care a apelat functia sa-si retina o anumita zona de memorie. Dimensiunea memoriei rezidente trebuie introdusa in registrul DX (in paragrafe). Se poate transmite si un cod de retur prin AL. Fisierele deschise de program nu se inchid implicit. Spre deosebire de intreruperea 27h, prin aceasta functie se pot retine zone de memorie de peste 64K.
Exemplu :
Utilizarea functiilor de gestiune a proceselor si memoriei se ilustreaza printr-un exemplu care consta din doua programe. Primul PARENT.C si al doilea CHILD.C.
Programul PARENT.C va solicita introducerea de la tastatura a numelui unui fisier executabil (forma executabila a lui CHILD.C) pe care il lanseaza in executie prin functia 4Bh. Programul citeste si afiseaza codul de retur furnizat la terminare de programul lansat in executie.
#include <stdio.h>
#include <dos.h>
static char tampon[128], param[14];
char *errmsg[] = ;
void main(void)
else printf('Terminare anormala, %s !n',
(r.x.ax <= 11) ? errmsg[r.x.ax] : errmsg[0]);
Programul CHILD.C va anunta intrarea sa in executie printr-un mesaj, dupa care aloca mai multa memorie, daca poate, prin 48h si se termina prin apelul functiei exit (4Ch).
#include <stdio.h>
#include <dos.h>
void main(void)
In urmatoarele se va mentiona o lista a functiilor sistem care nu au intrat in categoriile mentionate pana acum :
2Ah : obtinerea datei curente a sistemului. Produce ca rezultat in registre data curenta : an, luna, zi. AL = ziua in saptamana (0 - duminica, 1 - luni, ), CX = anul curent, DH = luna curenta (1 12), DL = ziua curenta (1
2Bh : pozitionarea datei curente.
2Ch : obtinerea timpului sistem curent. CH = ora curenta (0 23), CL = minutul curent (0 59), DH = secunda (0 59), DL = sutimea de secunda (0
2Dh : pozitionarea timpului curent. In AH se returneaza 00h daca in registre s-au introdus informatii valide si FFh daca informatiile sunt invalide.
35h : obtinerea valorii curente ale unui vector de intrerupere. Pentru apelul functiei se incarca in AL numarul nivelului de intrerupere dorit iar rezultatul se obtine in ES:BX. Se recomanda ca asupra vectorilor de intrerupere sa se opereze intotdeauna prin functii sistem si nu prin scriere directa in memorie.
25h : pozitionarea valorii unui vector de intrerupere. AL = numarul nivelului de intrerupere dorit, DS:DX = pointer la rutina care va trata intreruperea pe nivelul specificat. Se recomanda ca inainte de utilizarea acestei functii sa se salveze vechea valoare a vectorului de intrerupere astfel ca la sfarsitul programului curent sa se poata reface vectorii de intrerupere asa cum au fost inaintea lansarii acestui program.
5Ch : blocarea si deblocarea accesului la un fisier. Interzice sau autorizeaza accesul la o regiune specificata a unui fisier. Se utilizeaza in special in retelele de calculatoare. In registrul AL se precizeaza daca se doreste blocarea (00h) sau deblocarea (01h). In registrul BX se introduce identificatorul logic al fisierului. In CX:DX se introduce deplasamentul regiunii afectate, pozitia in fisier unde incepe zona blocata sau deblocata, iar in SI:DI lungimea zonei afectate. Aceasta functie are efect numai dupa ce programul SHARE a fost instalat. Se recomanda ca o regiune de fisier sa fie tinuta blocata cat mai putin timp. Un proces fiu nu mosteneste drepturile de acces ale procesului parinte. Functia permite si cererea blocarii la nivel de fisier, in acest caz CX si DX contin valoarea 00h, iar SI si DI contin FFh.
Majoritatea implementarilor pentru sistemul DOS prevad functii de biblioteca. Se recomanda folosirea acestor functii ori de cate ori este nevoie pentru portabilitatea programului. Aceste functii ne depind de proprietatile hardware ale claculatoarelor iar unele dintre acestea nu sunt specifice doar sistemului de operare MS-DOS. Pot apare diferente intre denumirile acestor functii de la o implementare la alta. De multe ori o functie exista in doua variante. Vom intalni o functie _read si o alta functie read. Prima functie este specifica MS-DOS (_read) si in implementarea ei se apeleaza o functie MS-DOS, cealalta este introdusa pentru compatibilitate cu sistemul UNIX.
1. Crearea unui fisier (3Ch)
int _creat(const char *path, int attribute);
Returneaza indicatorul fisierului (file handle) pentru succes, -1 pentru eroare. Ca si atribute pot fi folosite orice combinatii intre urmatoarele : FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_LABEL, FA_DIREC, FA_ARCH. Prototipul fuctiei se gaseste in fisierul antet io.h, iar constantele simbolice pentru atribute se gasesc in dos.h. Prin variabila errno se specifica natura erorii (ENOENT - calea nu este data bine, ENFILE - prea multe fisiere deschise in program, EACCES - acces interzis la fisier).
2. Deschiderea unui fisier (3Dh)
int _open(const char *filename, int mode);
Specificarea modului de deschidere se poate face cu ajutorul unor constante simbolice, care pentru compatibilitate cu UNIX se gasesc in fcntl.h. Returneaza indicatorul fisierului in caz de succes, iar in caz de eroare returneaza -1. Se pot specifica trei elemente prin mode si anume : care este forma de acces (O_RDONLY, O_WRONLY, ORDWR), care este forma de partajare a accesului (O_DENYALL, O_DENYWRITE, O_DENYREAD, O_DENYNONE) sau daca fisierul este mostenit de procesele fiu (O_NOINHERIT).
3. Inchiderea unui fisier (41h)
int unlink(const char *filename);
Returneaza 0 pentru succes, respectiv -1 pentru eroare.
4. Inchiderea unui fisier (3Eh)
int close(int handle);
Pentru inchiderea unui fisier se specifica numai descriptorul fisierului. In caz de incident se returneaza -1 iar prin variabila errno se descrie natura erorii (EBADF - descriptor eronat).
5. Citirea dintr-un fisier cu indice specificat (3Fh)
int _read(int filehandle, void *buffer, unsigned readcount);
Se pot citi pana la 64K printr-o singura operatie. La revenire functia returneaza numarul de octeti cititi. Daca a aparut o eroare se returneaza -1.
6. Scrierea intr-un fisier cu indice specificat (40h)
int _write(int filehandle, void *buffer, unsigned writecount);
Se returneaza numarul de octeti scrisi care trebuie sa corespunda cu valoarea lui writecount. Aceleasi erori ca si la citire.
Pentru fiecare dintre aceste 5 functii exista si functia fara liniuta, compatibile UNIX, diferenta apare ca si comportare la open, care corespunzand UNIX-ului permite o comportare diferita la citire, dupa cum fisierul este deschis in mod text sau in mod binar. Mai exista si functii de biblioteca echivalente cu apeluri sistem DOS care nu contin liniuta :
int creatnew(const char *path, int attribute); (5Bh)
int creattemp(char *path, int attribute); (5Ah)
int dup(int handle); (45h)
int dup2(int handle1, int handle2); (46h)
long lseek(int handle, long offset, int origin); (42h)
Constantele simbolice acceptate ca si origine sunt : SEEK_SET, SEEK_CUR si SEEK_END, acestea fiind definite in fisierul stdio.h.
Aceste functii au prototipurile in fisierul antet dir.h.
1. Crearea unui catalog (39h)
int mkdir(const char *path);
Returneaza 0 pentru succes si -1 pentru eroare. Ca si pentru crearea unui fisier, se presupune ca toate numele de cale exista, altfel in errno se returneaza codul de eroare corespunzator.
2. Stergerea unui catalog (3Ah)
int rmdir(const char *path);
3. Schimbarea catalogului curent (3Bh)
int chdir(const char *path);
Prin aceasta functie nu putem trece de pe o unitate de disc pe alta.
4. Obtinerea numelui complet al catalogului curent
char* getcwd(char *path, int maxchars);
Primul parametru path desemneaza tamponul unde se va primi numele complet al catalogului, maxchars indica lungimea acestui tampon. Functia poate fi apelata si cu valoarea NULL pentru path, caz in care getcwd aloca din memoria dinamica maxchars octeti si valoarea returnata este adresa acestei zone de memorie.
5. Obtinerea numelui catalogului curent de pe o unitate de disc specificata (47h)
int getcurdir(int drive, char *directory);
Unitatea de disc este specificata ca un intreg dupa conventia : 0 - discul implicit, 1 discul A, 2 discul B etc. Rezultatul se obtine in sirul de caractere directory, acesta fiind un tampon.
6. Obtinerea sau pozitionarea atributelor unui fisier (43h)
int _chmod(const char *pathname, int func, );
Este functie specifica DOS. Compilatorul de C accepta prototipuri de aceasta forma (). pathname este numele fisierului care urmeaza sa fie afectat, func este functia dorita (0 - citire atribute, 1 - pozitionare atribute). Daca func = 1 atunci vom avea si al treilea parametru, construit din constante atribut de fisier.
int chmod(char *path, int pmode);
Aceasta este compatibila UNIX.
7. Gasirea primului fisier care corespunde unui tipar dat (4Eh)
int findfirst(const char *pathname, struct ffblk *fileinfo, int attribute);
Returneaza 0 cand este succes. In campul ff_name se gaseste numele fisierului care satisface acest tipar. La eroare returneaza -1, cu semnificatia ENOFILE (nu s-a gasit nici un fisier corespunzator tiparului dat).
8. Gasirea unui fisier care corespunde unui tipar dat (4Fh)
int findnext(struct ffblk *fileinfo);
Exemplu :
Daca folosim functii de biblioteca putem obtine o forma de dir astfel :
#include <stdio.h>
#include <dir.h>
void main(void)
printf('Lungimea totala a fisierelor : %ldn', total);
1. Obtinerea unitatii implicite, curente (19h)
int getdisk(void);
Prototipul functiei se gaseste in dir.h. Functia returneaza 0 pentru A, 1 pentru B etc.
2. Selectarea unitatii implicite (0Eh)
int setdisk(int drive);
Prototipul functiei se gaseste in dir.h. Unitatea se specifica astfel : 0 - A, 1 - B etc.
3. Obtinerea adresei DTA (2Fh)
char* getdta(void);
Prototipul functiei se gaseste in dos.h.
4. Pozitionarea adresei DTA (1Ah)
void setdta(char far* dta);
Prototipul functiei se gaseste in dos.h.
5. Obtinerea informatiilor despre FAT pentru unitatea curenta (1Bh)
void getfatd(struct fatinfo *dtable);
struct fatinfo ;
Prototipul functiei se gaseste in dos.h.
Exemplu :
Programul afiseaza informatii despre FAT.
#include <stdio.h>
#include <dir.h>
#include <dos.h>
int main(void)
6. Obtinerea informatiilor despre FAT pentru o unitate specificata (1Ch)
void getfat(unsigned char drive, struct fatinfo *dtable);
Prototipul functiei se gaseste in dos.h. Unitatea logica se da ca si numar : 0 - unitatea implicita, 1 - A, 2 - B etc.
7. Obtinerea spatiului liber pe disc (36h)
void getdfree(unsigned char drive, struct dfre *dtable);
struct dfree ;
Prototipul functiei se gaseste in dos.h. Unitatea logica se da ca si numar : 0 - unitatea implicita, 1 - A, 2 - B etc. In caz de eroare functia pozitioneaza df_sclus pe 0FFFFh.
Exemplu :
Programul afiseaza spatiul liber pe discul curent.
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <dir.h>
int main(void)
avail = (long)free.df_avail * (long)free.df_sclus * (long)free.df_bsec;
printf('Discul %c: contine %ld octeti disponibili.n', 'A'+drive, avail);
8. Controlul general al intrarii/iesirii (44h)
int ioctl(int handle, int func [,void *argdx, int argcx]);
Prototipul functiei se gaseste in io.h. Functiile sunt specifice pentru o anumita versiune DOS. Portabilitatea este redusa. Aceasta functie se foloseste pentru obtinerea de informatii despre periferice, starea I/O. La eroare se returneaza -1, altfel valoarea returnata este corespunzatoare fiecarei subfunctii. errno va contine informatii despre eroarea respectiva (EINVAL - argument invalid, EBADF - numar de fisier eronat, EINVDAT - date invalide).
Exemplu :
Programul comuta modul de lucru al ecranului din stilul RAM (caracterele de control afisate fara interpretare) in COOKED (se interpreteaza caracterele de control, aceasta fiind modul normal de lucru). In modul RAM creste foarte mult viteza de afisare pe ecran.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <io.h>
#define RAW_BIT 0x20
int main(int argc, char **argv)
if (!stricmp(argv[1], 'RAW'))
rawmode = 1;
else
if (!stricmp(argv[1], 'COOKED'))
rawmode = 0;
else
/* citire informatie */
func = 0;
ioctl(handle, func, &argdx);
if (rawmode)
argdx |= RAW_BIT;
else
argdx &= ~RAW_BIT;
func = 1;
ioctl(handle, func, &argdx);
return 0;
1. Functia de alocare a unei cantitati de memorie (48h)
int allocmem(unsigned size, unsigned *segp);
Prototipul functiei se gaseste in dos.h. Primeste dimensiunea in paragrafe a blocului de memorie solicitat (16 octeti = 1 paragraf). segp este o locatie de memorie unde se va memora adresa de segment a blocului alocat. Returneaza -1 pentru alocare corecta - s-a putut aloca blocul de memorie solicitat. Altfel va returna dimensiunea celui ma mare bloc disponibil.
Deosebirea dintre allocmem si malloc este ca prima cere sistemului de operare o portiune de memorie, pe cand a doua cere alocarea memoriei din heap - spatiul rezervat programului.
2. Functia de eliberarea memoriei alocate (49h)
int freemem(unsigned segadd);
Prototipul functiei se gaseste in dos.h. Codul de retur poate fi 0 pentru succes si -1 pentru eroare. In caz de eroare se pozitioneaza errno pe ENOMEM, precizand ca s-a transmis o adresa de segment eronata.
3. Functia de modificare a alocarii memoriei (4Ah)
int setblock(unsigned segadd, unsigned newsize);
Prototipul functiei se gaseste in dos.h. Incearca modificarea dimensiunii unui bloc deja alocat. Permite doar marirea blocului, nu si micsorarea lui. Intoarce -1 pentru succes, altfel dimensiunea memoriei disponibile.
Exemplu :
Programul demonstreaza folosirea functiilor amintite. In program se mai foloseste functia movedata care copiaza o zona de memorie intr-o alta zona de memorie.
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#define DOS_PRTSTR 9
char str[80] = 'Test allocmem()nr$';
int main(void)
if ((maxsize = setblock(segadd, 5)) != -1)
movedata(FP_SEG(stradd), FP_OFF(stradd), segadd, 0, 80);
sr.ds = segadd;
r.x.dx = 0;
r.h.ah = DOS_PRTSTR;
intdosx(&r, &r, &sr);
freemem(segadd);
return 0;
1. Obtinerea adresei PSP (62h)
unsigned getpsp(void);
Prototipul functiei se gaseste in dos.h. Este util pentru citirea sirurilor de ambianta (de exemplu PATH-ul). Valoarea returnata reprezinta adresa de segment al PSP. Trebuie sa cunoastem deplasamentul pentru a afla datele din PSP.
Exemplu :
Program care afiseaza spatiul ocupat de el insusi.
#include <stdio.h>
#include <dos.h>
int main(void)
2. Functia care determina ramanerea rezidenta a unui program (31h)
void keep(unsigned char status, unsigned memsize);
Prototipul functiei se gaseste in dos.h. Primeste ca parametru un cod de stare care se transmite programului parinte. memsize reprezinta cantitatea de memorie pe care o pastreaza procesul care ramane rezident. Este reprezentata in paragrafe. Este folosita pentru gestionarea vectorilor de intrerupere.
3. Terminarea executiei unui proces (4Ch)
void _exit(int status);
Prototipul functiei se gaseste in stdlib.h sau process.h. Nu inchide fisierele aferente programului, face numai revenirea la procesul parinte si nu goleste tampoanele.
Functia compatibila UNIX este :
void exit(int status);
Prototipul functiei se gaseste in stdlib.h sau process.h. Inchide toate fisierele aferente programului. La ambele functii status este codul de intoarcere pentru procesul parinte.
4. Executia unei comenzi DOS in interiorul unui program
int system(const char *cmd);
Prototipul functiei se gaseste in stdlib.h sau process.h. cmd reprezinta comanda DOS care va fi executata. Se citeste variabila COMSPEC pentru a localiza COMMAND.COM-ul si se transmite argumentul cmd. Pentru executia acestei comenzi, daca este nevoie, se inspecteaza si variabila PATH. COMMAND.COM se lanseaza cu o singura comanda dupa executia careia se revine.
Daca cmd este sirul vid se face doar verificarea faptului ca exista COMMAND.COM. Daca sirul este vid si nu se gaseste COMMAND.COM atunci se returneaza 0, altfel se returneaza o valoare diferita de 0. Daca sirul nu este vid se returneaza 0 pentru executie normala si -1 pentru esec.
Exemplu :
Programul urmator lanseaza in executie o comanda.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
5. Incarcarea si executia unui proce fiu
Prototipul functiilor din aceasta categorie se gasesc in process.h.
int spawnl(int mode, char *path, char *arg0, , NULL);
int spawnle(int mode, char *path, char *arg0, , NULL, char *envp[]);
int spawnlp(int mode, char *path, char *arg0, , NULL);
int spawnlpe(int mode, char *path, char *arg0, , NULL, char *envp[]);
int spawnv(int mode, char *path, char *argv[]);
int spawnve(int mode, char *path, char *argv[], char *envp[]);
int spawnvp(int mode, char *path, char *argv[]);
int spawnvpe(int mode, char *path, char *argv[], char *envp[]);
mode reprezinta modul de executie al lui spawn, modul cum trebuie tratat procesul parinte. Valorile pe care le poate primi acest parametru sunt :
P_WAIT - procesul parinte ramane in asteptare pana la terminarea procesului fiu.
P_OVERLAY - programul procesului fiu se suprapune peste programul procesului parinte in memorie.
P_NOWAIT - procesul parinte isi continua executia in paralel cu procesul fiu (aceasta forma nu este implementata in S.O. MS-DOS).
path reprezinta numele de cale al fisierului de executat.
arg0, arg1, reprezinta argumentele din linia de comanda pentru procesul fiu (arg0 trebuie sa fie identic cu path).
argv[] reprezinta argumentele din linia de comanda pentru procesul fiu.
envp[] reprezinta tabloul cu parametri de mediu.
Semnificatia literelor din numele functiilor spawn este urmatoarea :
l - se transmit argumentele ca o lista.
v - se transmit argumentele ca un tablou, ca vector de pointeri.
p - indica faptul ca pentru localizarea fisierului executabil se va consulta si variabila de mediu PATH.
e - precizeaza faptul ca se transmit variabile de mediu. In absenta lui e procesul fiu mosteneste variabilele de mediu ale parintelui.
Obs
Este obligatoriu ca functiile spawn sa transmita cel putin un argument procesului fiu, adica cel putin numele fisierului care contine codul procesului.
Lungimea combinata a tuturor sirurilor folosite ca argumente in linia de comanda, daca este vorba de lista |arg0| + |arg1| + + |argn| sau daca este tablou |arg[0]| + |arg[1]| + + |arg[n]| nu poate depasi 128 octeti.
Fisierele care au fost deschise in procesul parinte raman deschise si pentru procesul fiu.
Valoarea de revenire din procesul fiu are semnificatie numai daca mode este P_WAIT, daca este P_OVERLAY atunci starea de revenire din procesul fiu va lua locul starii de revenire a procesului parinte.
In caz ca nu se poate lansa in executie procesul fiu, atunci se returneaza -1, iar pentru variabila globala errno pot exista urmatoarele situatii :
E2BIG, aceasta insemnand ca lungimea totala a argumentelor depaseste 128 octeti, sau ca memoria necesara pentru variabilele de mediu ar depasi 32K.
EINVAL, aceasta inseamna ca pentru mode s-a folosit o valoare invalida (de exemplu P_NOWAIT).
ENOENT, arata ca nu se poate gasi fisierul cu cod executabil. Fie ca nu exista acel fisier, fie ca numele de cale este invalid.
ENOEXEC, arata ca fisierul zis de cod nu este de fapt executabil.
ENOMEM, arata ca nu exista memorie suficienta pentru incarcarea si executia procesului fiu (programul este prea mare).
Aceste functii sunt utile daca vrem sa lansam in executie, din cadrul unui program, un alt program, care a fost compilat si linkeditat separat. Intre cele doua programe (parinte si fiu) se pot folosi in comun zone de memorie, rezultand o functionare asemanatoare cu a programelor rezidente (TSR).
Exemplu:
Se ilustreaza utilizarea acestor functii prin doua programe : PARENT.C si CHILD.C. Programul PARENT.C lanseaza in executie programul CHILD.C intreband utilizatorul care din variantele de spawn doreste sa le foloseasca. Inainte de lansarea in executie a fiului se pregateste in PARENT.C o structura de date care se va transmite procesului fiu prin codificarea adresei acestei structuri ca sir de caractere ce va figura ca unul dintre argumentele din linia de comanda. In procesul fiu se vor tipari argumentele din linia de comanda si ambianta transmisa. Se converteste apoi adresa transmisa ca sir de caractere si se face acces la structura. Se modifica in continuare diverse campuri ale structurii si se termina programul fiu. La revenirea in programul parinte se tiparesc din nou valorile din structura de date comuna pentru a verifica daca s-au produs modificarile executate in procesul fiu. Cele doua programe vor fi in fisiere separate care se compileaza si se linkediteaza separat.
/* Fisierul PARENT.C */
#include <process.h>
#include <string.h>
#include <stdio.h>
#include <alloc.h>
typedef struct TEST_DATA TEST_DATA;
/* Construim o ambianta */
char *envp[] = ;
void main(void)
/* Fisierul CHILD.C */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>
typedef struct TEST_DATA TEST_DATA;
static char far *myname = 'CHILD';
void main(int argc, char **argv, char **envp)
printf('CHILD a fost apelat prin %s.n', argv[1]);
printf('CHILD : ambianta contine :n');
/* se tiparesc sirurile de ambianta */
for(p_table = envp; *p_table != NULL; p_table++)
printf('%sn', *p_table);
/* urmeaza conversia inversa, a sirului de caractere */
sscanf(argv[2], '%Fp', (void far*)&pdata);
printf('In CHILD : name = %Fs, n = %d, x = %f.n',
pdata->name, pdata->n, pdata->x);
p_s1 = (void far*)myname;
p_s2 = (void far*)pdata->name;
/* folosind p_s1, p_s2 putem copia ceva in structura respectiva */
movedata(FP_SEG(p_s1),FP_OFF(p_s1),FP_SEG(p_s2),FP_OFF(p_s2),6);
pdata->n = 101;
pdata->x = 999.99;
/* se termina procesul fiu si se transmite 0 ca si valoare de iesire */
exit(0);
7. Incarcarea si lansarea in executie a unui proces fiu fara revenire
int execl(char *path, char *arg0, .., NULL);
int execle(char *path, char *arg0, .., NULL, char **env);
int execlp(char *path, char *arg0, ..);
int execlpe(char *path, char *arg0, .., NULL, char **env);
int execv(char *path, char *argv[]);
int execve(char *path, char *argv[], char **env);
int execvp(char *path, char *argv[]);
int execvpe(char *path, char *argv[], char **env);
Prototipurile acestor functii se gasesc in fisierul antet process.h. Intr-un anumit sens acestea sunt asemanatoare cu familia de functii spawn la care mode este pe P_OVERLAY.
In MS-DOS utilizarea functiilor exec este recomandabila in aplicatii care presupun inlantuirea unor programe. In caz de esec de lansare in executie si functiile exec returneaza -1, iar in variabila globala errno se obtin detalii despre natura erorii. Pot aparea aceleasi erori ca si la spawn, mai putin EINVAL, care era legat de argumentul mode. In plus mai pote aparea ENFILE, daca sunt prea multe fisiere deschise, respectiv EACCESS, daca un fisier specificat in PATH este blocat, sau nu este protejabil (la MS-DOS versiunile mai mari decat 3.3).
8. Terminarea anormala a executiei unui program
void abort(void);
Prototipul acestei functii se gaseste in fisierul antet stdlib.h sau process.h. Aceasta functie determina afisarea unui mesaj de eroare : 'Abnormal program termination', dupa care in functia respectiva este prevazut un apel la functia exit() si se da codul de retur 3.
Prototipurile acestor functii sunt in fisierul antet dos.h.
1. Functii pentru obtinerea datei curente
void getdate(struct date *datep);
struct date ;
2. Pozitionarea datei curente
void setdate(struct date *datep);
3. Obtinerea timpului curent al sistemului
void gettime(struct time *timep);
struct time ;
4. Pozitionarea timpului curent al sistemului
void settime(struct time *timep);
5. Obtinerea valorii curente a unui vector de intrerupere
void interrupt (*getvect(int interruptno))();
Functia de biblioteca este getvect. interruptno este numarul de intrerupere. Valoarea returnata de functie este o adresa, valoarea curenta a vectorului de intrerupere pe nivelul de intrerupere (dat de interruptno), acea adresa este adresa rutinei de tratare.
Functia se foloseste in mod uzual pentru a putea salva valoarea vectorului de intrerupere inainte de pozitionarea sa.
6. Pozitionarea unui vector de intrerupere
void setvect(int intno, void interrupt (*handler)());
handler este adresa noii functii de tratare a intreruperii de nivel intno.
Exemplu :
In continuare se prezinta un program in care se folosesc functiile getvect setvect si de asemenea functia keep (folosita pentru a realiza programe rezidente). Programul instaleaza o rutina de tratare a intreruperii pe nivelul 1Ch, aceasta va incrementa un contor modulo 10 si va afisa la fiecare intrerupere de timp valoarea contorului respectiv.
#include <dos.h>
#define INTR 0x1C
#define SAFETY 64
#define ATTR 0x7900
/* _heaplen - este variabila globala care specifica */
/* dimensiunea zonei de alocare dinamica */
extern unsigned _heaplen = 1024;
/* _stklen - este variabila globala care specifica */
/* dimensiunea zonei de stiva */
extern unsigned _stklen = 512;
void interrupt (*oldhandler)();
void interrupt handler()
int main(void)
Copyright © 2024 - Toate drepturile rezervate