Sunteți pe pagina 1din 379

Sisteme de operare: Mecanisme interne și principii de proiectare

Operating systems: Internals and Design Principless

Universitatea Tehnică a Moldovei


Catedra Automatică şi Tehnologii Informaţionale

Victor Beşliu
Ciclu de prelegeri pentru studenţii programelor TI, SI, IS

01.09.2020
1 12:47:14
Literatura (principală)

В.Е.Карпов, К.А.Коньков
Основы операционных систем
Literatura (suplimentară)

Эндрю Таннебаум
Современные операционные
системы, 2-е издание
Literatura (suplimentară)

Вильям Столлингс
Операционные системы
4-е издание
1. INTRODUCERE
1.1. NOŢIUNI DE BAZĂ ŞI CLASIFICĂRI
1.2. SISTEMUL DE OPERARE ŞI PROCESELE
1.3. MAŞINĂ IERARHICĂ ŞI MAŞINĂ EXTINSĂ
1.4. ALTE PUNCTE DE VEDERE ASUPRA SISTEMELOR DE OPERARE
1.5. EVOLUŢIA SISTEMELOR DE OPERARE
1.6. EXEMPLE DE SO: MS DOS, WINDOWS, UNIX ŞI ALTE SISTEME
Scopul lucrării: expunerea bazelor contemporane ale metodelor şi mijloacelor de
elaborare a resurselor program de sistem (inclusiv operaţii asincrone, tratarea
întreruperilor, compromisele dintre dispozitivele tehnice şi resursele program,
interfeţele sistemelor de operare) şi pregătirea cititorului pentru analiza şi
proiectarea sistemelor de operare (SO).

Un sistem de calcul nu poate să prelucreze date fără să fie programat, un program


constând dintr-o succesiune de instrucţiuni ce converg către soluţia problemei
care se rezolvă. Există două categorii de programe:
1. programe aplicative sau simplu aplicaţii, care sunt destinate să rezolve probleme
specifice; acestea efectuează prelucrări ale datelor în concordanţă cu cerinţele
problemei;
2. programe de sistem, destinate coordonării procesului de operare a circuitelor
sistemului, asistând aplicaţiile, utilizatorul, alte calculatoare. Ele sunt create să
faciliteze utilizarea eficientă a resurselor fizice şi logice ale sistemului de calcul, să
ajute la dezvoltarea şi execuţia programelor aplicaţii.

Programele de sistem sunt scrise pentru anumite categorii de sisteme de calcul şi nu


pot fi folosite pe orice calculator; sunt furnizate de către producătorii sistemelor
de calcul sau alte firme specializate, fiind astfel proiectate încât să corespundă
unei game variate de solicitări.

01.09.20
20 6
12:47:14
Structura sistemului de calcul
și locul disciplinei în ciclul general al cursurilor
de tehnologia informației

Utilizatorul Algoritmi și limbaje de programare

Programe
aplicative

Alte programe
Programe de sistem
de sistem
Sisteme de operare: Meanisme
Sistemul de operare interne și principii de proiectare
Resurse Arhitectura calculatorului
tehnice și limbajul de asamblare
Prin noţiunea de sistem de operare înţelegem modulele program ale unui SC, care
administrează resursele tehnice. Modulele în cauză soluționează situațiile de conflict,
optimizează productivitatea sistemului, sporesc eficiența utilizării lui. Ele joacă rol de
intermediar (interfață) între programele utilizatorului și componentele tehnice ale
calculatorului. Alte denumiri istorice ale SO: program de administrare, monitor, supervizor.

01.09.20
20 8
Fig.1.1. Relaţia dintre un sistem de operare şi componentele
12:47:14 unui calculator.
Fig. 1.2. Sistemul de operare-interfaţă între hardware şi utilizator

01.09.20
20 9
12:47:14
Software de sistem Aplicaţii

Sisteme de Drivere de Programe Limbaje de


operare dispozitiv utilitare programare

• Constau din unul • Sunt programe • Majoritatea • Sunt utilizate


sau mai multe ce oferă utilitarelor pentru a scrie
programe calculatorului tratează programe, ce
• Controlează informaţii operaţiile de pot fi executate
echipamentele specifice stocare şi apoi de către
hardware privind un gestionare a calculator
• Gestionează anumit fişierelor • Permit
toate celelalte echipament • Unele utilitare utilizatorilor să
aplicaţii hardware sunt incluse ca introducă
• Sunt concepute • Sunt utilizate părţi ale SO instrucţiuni mai
pentru a lucra cu de SO pentru inteligibile decât
o anumită comunicarea cu 01.09.20 limbajul maşină
arhitectura echipamentele 20 10
12:47:14
hardware periferice
Ce este un SO?
Extensie a maşinii fizice (vedere top-down)
abstractizează operațiile mașinii fizice în operații mai
simple pentru ușurința utilizării
ex: accesul la fișiere
Gestionar al resurselor mașinii fizice (vedere bottom-up)
utilizatorii accesează resursele comune ale sistemului
SO are rolul de multiplexare a accesului
ex: gestiunea procesorului, a memoriei

01.09.20
20 11
12:47:14
Scurt istoric din dezvoltarea
sistemelor de calcul
Prima generație (1945 – 1955)

 Calculatoare cu tuburi electronice


 Nu există nici o separare a personalului
 Nu există sisteme de operare
 Introducerea manuală a programului (panou de comandă)
sau de pe cartele perforate
 Depanarea programului de la panoul de comandă
 Doar o singură operație executată la un moment de timp
 Apariția prototipurilor primelor compilatoare

Activitatea de cercetare în domeniul tehnicii de calcul


Istoria sistemelor de operare
On 09.09.1945 Grace Hopper
recorded the first actual computer
"bug„ — a moth (molie) stuck
between the relays and logged at
15:45 hours on the Harvard Mark II.
Hopper, a rear admiral in the U.S.
Navy, enjoyed successful careers in
academia, business, and the
military while making history in the
computer field.
She helped program the Harvard
Mark I and II and developed the first
compiler, A-0. Her subsequent work
on programming languages led to
COBOL, a language specified to
operate on machines of different
01.09.2020 12:47:14 13
manufacturers.
Scurt istoric din dezvoltarea
sistemelor de calcul
Generația a doua (1955 – începutul anilor 1960)

 Calculatoare pe tranzistori
 Începe separarea personalului
 Dezvoltarea rapidă a limbajelor de programare
 Introducerea sarcinilor folosind cartelele perforate
 Depanarea programului folosind listingul
 Pachete de sarcini și sistemele de tratare pe loturi

Începe utilizarea calculatoarelor


în scopuri științifice și comerciale
UNIX

01.09.20
20 15
12:47:14
Istorie

Generația a treia (1965 – 1980)


 Circuitele integrate
 Utilizarea spooling-ului
 Planificarea sarcinilor
 Tratarea pe loturi cu multiprogramare
Influența ideii de multiprogramare
asupra evoluției sistemelor de calcul
Software Hardware
 Planificarea sarcinilor  Protecția memoriei
 Administrarea memoriei  Salvarea contextului
 Salvarea contextului  Mecanismul întreruperilor
 Planificarea utilizării procesorului  Instrucțiuni privilegiate
 Apelurile de sistem
 Mijloace de comunicații
 Mijloace de sincronizarea
Scurt istoric

Generația a treia (1965 – 1980)


 Circuitele integrate
 Utilizarea spooling-ului
 Planificarea sarcinilor
 Tratarea pe loturi cu multiprogramare
 Sisteme cu partajarea timpului (time-sharing)
 Memorie virtuală
 Depanarea interactivă a programului
 Sistemele de gestiune a fișierelor
 Familii de calculatoare

Utilizarea pe scară largă a calculatoarelor în


scopuri științifice și comerciale
Generația a treia (1965 - 1980) (multitasking)
CTSS (Compatible Time Sharing System)
MULTICS (Multiplexed Information and Computing Service)
• MIT, Bell Labs, General Electric
• lansat în 1960 are un succes comercial scăzut
• influență masivă asupra dezvoltării ulterioare ale SO

UNIX
• o versiune mult redusă a MULTICS
• implementat de Ken Thompson
• portabil (scris în C)
• System V, BSD

01.09.2020 12:47:14 19
Scurt istoric din dezvoltarea
sistemelor de calcul
Generația a patra (1980 – ???)

 Circuite integrate mari și foarte mari (LSI și VLSI)


 Calculatoare personale
 Resurse program prietenoase
 Sisteme de operare distribuite și de rețea

Utilizarea pe scară largă a calculatoarelor în


casă, în educație, producție
Generația a patra (1980 - prezent)
• microcalculatoare şi calculatoarele personale
• CP/M
• dezvoltat de Kidall pentru Intel 8080
• MS-DOS
• cumpărat de Microsoft de la Seattle Computer ($50,000)
• oferit împreună cu BASIC pentru IBM PC
• Mac OS
• Steve Jobs “fură” ideea de GUI de la Xerox
• MS Windows: 3.11, 95
• influențat de Mac OS
01.09.20
20 21
12:47:14
Generația a patra (1980 - prezent)
• MS Windows NT, 2000, XP, Vista, 7
• Scris de la zero, 32/64 biți
• David Cutler (VAX VMS)

• Solaris, IRIX, HP-UX, ULTRIX


• Tru64
• primul SO pe 64 biți (procesoare Alpha)
• Linux
• clonă UNIX
• scris de la zero de Linus Torvalds

• FreeBSD, OpenBSD, NetBSD


01.09.20
20
01.09.20 22
12:47:14 20 22
12:47:14
Principalele funcții
îndeplinite de un SO clasic (evoluție)

 Planificarea sarcinilor și utilizării procesorului


 Asigurarea programelor cu mijloace de comunicare și
sincronizare
 Administrarea memoriei
 Gestiunea fișierelor
 Administrarea operațiilor de intrare/ieșire (I/O)
 Asigurarea securității

Sistemele de operare există pentru că pentru


moment ele reprezintă un mod rezonabil de
exploatare a sistemelor informatice
Structura internă
a sistemelor de operare
Nucleu monolitic
 Procedurile se pot apela reciproc (fiecare!)
 Toate procedurile sunt executate în regim privilegiat
 Nucleul coincide cu întreg sistemul de operare
 Programele de utilizator interacționează cu nucleul folosind
apelurile de sistem
Program de utilizator

- Punct de intrare în Program de utilizator


nucleu – apel de SO = kernel
Regim privilegiat
sistem
Program de utilizator
Structura internă
a sistemelor de operare
Sisteme multinivel (Layered systems)
 Procedura nivelului N poate apela doar proceduri ale nivelului N -1
 Toate (sau aproape toate) nivelurile funcționează în regim privilegiat
 Nucleul coiincide (sau aproape coiincide) cu întreg sistemul de operare
 Programele de utilizator interacționează cu SO prin interfața uzerului
Sistemul THE
5 Interfața utilizatorului
4 Gestiunea operațiilor de I/O
3 Driver-ul de legătură cu consola
2 Administrarea memoriei
1 Planificarea sarcinilor și a proceselor
0 Hardware
Structura internă
a sistemelor de operare
Arhitectura micronucleu (microkernel)
Funcțiile micronucleului:
 interacțiunea programelor
 planificarea utilizării procesorului
 tratarea primară a întreruperilor și a operațiilor I/O
 gestiunea de bază a memoriei

Managerul SO
rețelei
Aplicația 1
Micronucleu
Managerul
memoriei
Regim privilegiat
Aplicația 2 Managerul
fișierelor
Structura internă
a sistemelor de operare
Arhitectura micronucleu (microkernel)

 Interacțiunea componentelor SO între ele și cu aplicațiile


(folosing mesaje) prin intermediul micronucleului
 În modul privilegiat “lucrează” numai micronucleul
 Micronucleul este doar o mică parte a SO
Structura internă
a sistemelor de operare
Sisteme mixte – de ce?
 Nucleu monolitic - necesitatea de a recompila la fiecare
modificare, depanare complicată, viteză mare de procesare.
 Sisteme multinivel - necesitatea de a recompila la fiecare
modificare, depanarea numai a nivelului modificat, viteză mai
mică de procesare.
 Micronucleu - simplitatea depanării, posibilitatea de a înlocui
componentele fără recompilarea și oprirea sistemului, foarte lent.
Structura internă
a sistemelor de operare
Sisteme mixte – exemple
 Linux – sistem monolitic cu elemente de arhitectură microkernel
(module încărcate dinamic)
 4.4 BSD – lansarea sistemului monolitic sub controlul micronucleului
 Windows NT – micronucleu (aproape!) cu elemente monolitice

Abordarea multinivel stă la baza aproape tuturor SO în componentele


separate ale SO
Structura internă a SO

Mașini virtuale
SO pune la dispoziția fiecărui utilizator o copie a resurselor tehnice virtuale
proprii (virtual hardware)

Utilizator Utilizator Utilizator

Linux Windows-XP MS-DOS

Hardware virtual Hardware virtual Hardware virtual

Sistemul de operare real

Hardware real
Ce înțelegem prin Sistem de Operare?

Principalele puncte de vedere

 Gestionarul resurselor
 Protectorul utilizatorilor și programelor
 Mașină virtuală
 Кот в мешке
 Nucleu care funcționează fără întrerupere

Este mai simplu de spus la ce servește un


sistem de operare și ce face el
NOŢIUNI DE BAZĂ ŞI CLASIFICĂRI
Calculator - ansamblu de componente fizice şi logice, care cooperează
pentru a satisface cerinţele utilizatorilor privind introducerea,
stocarea, prelucrarea, căutarea şi transmiterea informaţiilor.

Funcţiile de bază ale unui calculator:


• iniţializarea - testarea, rularea fişierelor de pornire şi încărcarea altor
fişiere necesare,
• introducerea - transferul datelor dintr-o sursă externă în calculator,
• procesarea - manipularea datelor în scopul producerii unui rezultat,
• stocarea - salvarea informaţiilor într-un dispozitiv de păstrare,
• extragerea rezultatelor -

01.09.20
20 32
12:47:14
Magistrale

01.09.20
20 34
12:47:14
Magistrale
Linii de
• adresă (determină spațiul de adresă)
• date (împreună cu frecvența magistralei
determină lățimea de bandă)
• Control

Lățimea de bandă
• numărul de linii de date x frecvența magistralei

35
01.09.2020 12:47:14
Concepte hardware de bază
• SO interacționează cu hardware-ul la un nivel destul de scăzut
• sunt necesare cunoștințe despre hardware pentru a înțelege modul de
funcționare a sistemului de operare

01.09.20
20 36
12:47:14
Procesoarele

Arhitecturi
• bandă asamblare (a)
• superscalar (b)
• VLIW/EPIC
• RISC
• CISC
01.09.2020 12:47:14 37
Memoria

01.09.2020 12:47:14 38
Dispozitive de intrare/ieșire
în general sunt compuse din două părți
• un controller
• dispozitivul efectiv

părțile din SO care controlează dispozitivele de I/E se numesc drivere


lente: mouse, tastatura
• comunicația între dispozitivele de I/E lente și procesor se poate face
prin polling
rapide: discuri, placa de rețea, placa video
• pentru controlul acestor dispozitive se folosesc întreruperi și
controllere DMA

39
01.09.2020 12:47:14
Concepte de bază
procese, fire de execuție
deadlock
memorie virtuală
sisteme de fișiere
interpretorul de comenzi
nucleul sistemului de operare
kernel mode vs user mode
kernel space vs user space
apeluri de sistem
40
01.09.2020 12:47:14
Procese
un program în execuție
are asociate mai multe resurse:
• un spațiu de adrese
• fișierele deschise
• alte resurse (memorie partajată, socketi, etc)
în general procesele sunt ierarhizate după relația
părinte-copil
SO oferă protecție dar şi comunicație interprocese

41

01.09.2020 12:47:14
Fire de execuție
un proces poate avea mai multe fire de execuție
firele de execuție dintr-un proces partajează resursele
acestuia (memorie, fișiere deschise etc.)
fiecare fir de execuție are un context
• context = informații despre starea thread-ului (stivă,
registre generale, registre speciale)
avantaje / dezavantaje
• paralelism cu o comunicație extrem de facilă și rapidă
• se pierde mai puțin timp pentru o schimbare de context
• nu există protecție între firele de execuție

42

01.09.2020 12:47:14
Blocare reciprocă (impas, deadlock

43
01.09.2020 12:47:14
Memorie virtuală
Adrese
• virtuale
• Fizice
MMU și SO fac
translatarea din
adrese virtuale
în adrese fizice

44
01.09.2020 12:47:14
Fișiere
cale, director rădăcină, director de lucru
descriptor de fișier / handle
fișiere speciale
• bloc
• caracter
• pipe-uri
• link-uri

sistem de fișiere, operații de


montare/demontare
(a) înainte de montare
(b) după montare
45
01.09.2020 12:47:14
Intrepretorul de comenzi
Programul de interfață între utilizator şi sistem
Mod linie de comandă
• avantaje: flexibilitate, puține resurse
consummate
• ex: sh , bash, korn
Mod grafic
• avantaje: mai ușor de utilizat
• ex: explorer.exe în Windows

01.09.20
20 46
12:47:14
Nucleul sistemului de operare
Nucleul SO are acces direct la hardware
Părți din nucleu sunt permanent rezidente în memorie
Imaginea nucleului
• Linux: /vmlinuz, /boot/vmlinuz
• Windows: %SystemRoot%\system32\ntoskrnl.exe
• Mac OS X: Mach 3.0 + *BSD
module / drivere

01.09.2020 12:47:14 47
Nucleul space vs user space
Nucleul rulează în mod privilegiat
• kernel mode
• kernel space

Orice proces are un spațiu de adrese diferit


Nucleul lucrează cu un spațiu de adrese diferit de cel al
proceselor
• user mode
• user space

01.09.2020 12:47:14 48
Apeluri de sistem
Accesul la resursele sistemului se face prin apelarea
serviciilor puse la dispoziție de nucleu

01.09.2020 12:47:14 49
Componente ale SO
• gestiunea proceselor
• gestiunea memoriei
• gestiunea fișierelor
• gestiunea operațiilor de I/E
• gestiunea rețelei

01.09.2020 12:47:14 50
Gestiunea proceselor
• crearea și terminarea proceselor
• suspendarea și repornirea proceselor
• planificatorul de procese (scheduler)
• mecanisme de sincronizare
• mecanisme pentru comunicație inter-procese
• detectare/rezolvare deadlock-uri
• protecție

01.09.2020 12:47:14 51
Gestiunea memoriei
• gestiunea memoriei fizice și virtuale
• memorie virtuală, segmentare, paginare
• swaping
• gestiunea memoriei folosite de nucleu
• memorie rezidentă permanentă
• memorie rezidentă temporară
• gestiunea spațiilor de adrese
• malloc/free, mmap
• Protecție

01.09.2020 12:47:14 52
Gestiunea fișierelor
• translatarea operațiilor de acces asupra fișierelor
(open, close, read, write, seek) în operații de citire și
scriere pe disc
• caching și read-ahead
• compresie și criptare
• Protecție

01.09.2020 12:47:14 53
Gestiunea operațiilor de I/E
• interfață comună pentru drivere
• caching, buffering
• întreruperi, DMA
• I/O scheduling

01.09.2020 12:47:14 54
Gestiunea rețelei

• implementarea unor stive de protocol eficiente și


sigure (secure)
• implementare în kernel
• legături cu alte subsisteme ale SO: memorie,
procese, scheduling, sisteme de fișiere

01.09.2020 12:47:14 55
Noţiuni şi termeni din domeniul SO
SO - ansamblu de programe de control şi de serviciu care
ghidează un calculator în execuţia sarcinilor sale, asistă
programele de aplicaţie şi interacţionează cu utilizatorul prin
intermediul anumitor funcţiuni.
Natura funcţiilor şi modul în care acestea sunt realizate
determină atributele care caracterizează un sistem de operare:
• timpul de răspuns,
• simultaneitatea utilizării,
• eficienţa,
• partajarea resurselor şi protecţia informaţiei în calculator,
generalitatea,
• flexibilitatea,
• extensibilitatea,
• fiabilitatea şi disponibilitatea, 01.09.20

• transparenţa şi vizibilitatea. 20
12:47:14
56
Atribute
Timpul de răspuns exprimă durata intervalului delimitat de lansarea unei
cereri de serviciu şi achitarea acesteia de către sistem. Are două
componente: timpul de aşteptare pentru ca cererea respectivă să fie luată
în consideraţie şi timpul de execuţie a acestei cereri.
Simultaneitatea utilizării măsoară gradul în care un sistem poate să execute
în acelaşi timp mai multe lucrări.
Eficienţa măsoară proprietatea unui sistem de a folosi în mod optim
resursele de care dispune.
Partajarea resurselor şi protecţia informaţiei caracterizează nivelul la care
utilizatorii au posibilitatea să utilizeze în comun informaţia prezentă în
sistem şi nivelul la care pot să comunice între ei, în deplină siguranţă.

01.09.20
20 57
12:47:14
Atribute
Generalitatea, flexibilitatea şi extensibilitatea măsoară gradul în care un sistem
poate fi folositor şi adaptabil unui context specific, precum şi gradul în care se pot
include în sistem noi componente hardware şi software fără eforturi de proiectare
şi programare suplimentare.
Fiabilitatea şi disponibilitatea exprimă proprietatea unui sistem de a cădea foarte
rar în pană şi de a evita goluri în funcţionare din cauza defectării uneia sau mai
multor componente ale sale.
Transparenţa şi vizibilitatea exprimă pe de o parte proprietatea unui sistem de a
face invizibil utilizatorului ceea ce se află sub interfaţa care i se oferă şi, pe de altă
parte, capacitatea de a permite utilizatorilor săi să obţină anumite informaţii
despre modul cum el funcţionează.

01.09.20
20 58
12:47:14
Alte noțiuni
Resursele program (logice) reprezintă seturi de programe şi date
utilizate pentru soluţionarea anumitor probleme.
Programul este transcrierea într-un limbaj de programare a unui
algoritm, altfel – programul este o secvenţă de instrucţiuni sau
simplu, cod.
Utilizatorul (Userul) este oricare doritor să îndeplinească anumite
lucrări la calculator.
Lucrare - set de acţiuni, necesare pentru îndeplinirea unui lucru
anume. Sarcina poate conţine mai mulţi paşi. Paşi de task sunt
unităţi de lucru, care vor fi îndeplinite consecutiv, de exemplu, trei
paşi – compilare, încărcare şi execuţie.
Proces primind o lucrare de la utilizator, SO poate crea câteva
procese: secvenţe de calcul care pot fi efectuate paralel cu alte
secvenţe de calcul. Procesul se află în spațiul01.09.20
de20 adrese.
59
12:47:14
Tipuri de sisteme de operare
Valorile concrete ale atributelor sistemelor de operare şi combinaţii ale
acestora determină diverse tipuri de SO:
• secvenţiale,
• cu multiprogramare,
• cu prelucrare multiplă,
• în timp real, etc.
Un sistem secvenţial (tratare pe loturi, engl. batch processing, fr. traitement par
lots) execută la un moment dat un singur program, care trebuie terminat înainte
de a lua începe execuţia unui alt program.
Sistemele cu multiprogramare acceptă la un moment dat mai multe programe
în memoria centrală, acestea aflându-se în diferite stadii de execuţie.
Un sistem de calcul cu prelucrare multiplă dispune de mai multe procesoare,
care pot să execute simultan unul sau mai multe programe.
Sistemele de timp real funcţionează în cadrul unor sisteme de comandă şi este necesar ca
valorile anumitor atribute să se încadreze în limite destul de restrictive, dictate de dinamica
proceselor comandate. 01.09.2020 12:47:14
60
Clasificare SO
• SO pentru servere
• SO pentru sisteme multiprocesor
• SO pentru calculatoare personale
• SO pentru sisteme embedded
• RTOS

01.09.20
20 61
12:47:14
Obiective:
• maximizarea eficienţei sistemului de calcul şi a satisfacţiei utilizatorilor,
• minimizarea probabilităţii apariţiei unor erori
• maximizarea transparenţei sistemului de operare,
• garantarea securităţii datelor,
• optimizarea controlului comunicaţiilor în cazul unei reţele de calculatoare,
• minimizarea efortului concepţie - realizare.
Obiectivele - consecinţă ale dezideratului principal - un SO este destinat să
administreze resursele fizice şi logice ale sistemului de calcul
• memoria,
• procesorul (procesoarele),
• dispozitivele periferice
• informaţia.
Un sistem de operare este obligat:
• să păstreze informaţia despre starea fiecărei resurse,
• să ia decizia cărui proces să i se aloce resursa, în ce cantitate, când, cum şi unde,
• să aloce resursa şi, la momentul oportun, să o retragă.
01.09.2020 12:47:14 62
1.1.4. Exemple de sisteme de operare

1.1.4.1. Cazul calculatoarelor personale

Cea mai simplă configuraţie a unui calculator personal (PC) include o unitate centrală, o
memorie principală, un display, o tastatură şi un mouse. Această configuraţie, de
regulă, este completată de o memorie secundară şi o imprimantă.

Utilizatorul unui astfel de sistem va cere minimum următoarele două tipuri de servicii:
• identificarea şi crearea unor fişiere sau mulţimi structurate de informaţii;
stocarea acestor fişiere în memoria secundară; transferarea informaţiilor între
fişiere şi dispozitivele de intrare/ieşire;
• execuţia unor programe existente sau introduse sub formă de fişiere în PC;
introducerea datelor necesare pentru execuţia programului (de la tastatură, dintr-
un fişier sau de la alte surse periferice); listarea rezultatelor la display, imprimantă
sau copierea lor într-un fişier.

Sistemul de operare va acorda aceste servicii prin intermediul unui limbaj special,
numit limbaj de comandă, introducându-se de la tastatură instrucţiuni de forma
<acţiune> <parametri> sau utilizând mouse-ul şi o interfaţă grafică a utilizatorului,
acţionările mouse-lui fiind imediat interpretate de sistem.

01.09.2020 12:47:14
63
Exemple de secvenţe tipice de activităţi în cazul unui PC:

• elaborarea unui program;


• introducerea programului cu ajutorul tastaturii şi a unui editor de texte;
• execuţia programului introducându-se datele necesare de la tastatură şi extrăgând
rezultatele la display sau imprimantă;
• modificarea programului, dacă rezultatele nu sunt satisfăcătoare şi repetarea
execuţiei;
• perfectarea versiunii finale a programului, inclusiv documentarea la necesitate a
acestuia;
• exploatarea unui program;
• cererea de execuţie a unui program deja existent. Vor fi pregătite în prealabil
datele de intrare sau acestea vor fi introduse în mod interactiv la cerere cu ajutorul
tastaturii; dintr-un fişier sau de la alte surse periferice;
• afişarea rezultatelor pe ecran, listarea la imprimantă sau copierea lor într-un fişier
pentru o utilizare ulterioară.

Pentru acest tip de sisteme cele mai importante caracteristici sunt:


• fiabilitatea;
• eficacitatea;
• simplitatea utilizării;
• facilitatea extensibilităţii.
64
01.09.2020 12:47:14
1.1.4.2. Gestionarea unor procese industriale

Reactor

Robinete
A Captoare
C

Semnale de
măsură

Înregistrări
Semnale de comandă
Calculator

Fig.1.6. Schema unui proces. chimic


Procesul tehnologic este comandat de un calculator care îndeplineşte următoarele funcţii:
Reglare. Pentru o derulare mai bună a procesului de producere parametrii de funcţionare (temperatura, presiunea,
concentraţia, etc.) trebuie să se afle într-o plajă (într-un diapazon) de valori predefinite. Pentru aceasta va fi acţionat
debitul de intrare a materiilor prime A sau B. Valorile parametrilor de funcţionare a procesului sunt măsuraţi cu
ajutorul unor captoare. Calculatorul preia aceste măsurări şi, în dependenţă de algoritmul de gestionare, acţionează
robinetele de intrare.
Înregistrare. Rezultatele măsurărilor sunt periodic înregistrate; valorile lor sunt afişate pe un tablou (panou) de bord
01.09.20
şi recopiate într-un fişier (“jurnal de bord”) în scopul unor prelucrări
20 ulterioare65
(date statistice).
Securitate. În cazul în care unul dintre parametrii măsuraţi depăşeşte o valoare critică predefinită reactorul trebuie oprit
12:47:14
Acest mod de funcţionare introduce unele restricţii, descrise mai jos.
Măsurările sunt efectuate periodic; fie T valoarea intervalului de timp dintre două
măsurări consecutive (perioada de eşantionare), iar t - timpul total de prelucrare a
datelor de către calculator,. Sistemul va funcţiona doar în cazul respectării relaţiei de
restricţionare t mai mic T.

Securitatea sistemului are prioritate maximă. Depăşirea unor valori critice trebuie să fie
detectată în orice moment şi tratarea acestor accidente va întrerupe toate operaţiile în
curs de execuţie.

Funcţiile principale ale sistemului de operare sunt:


• acţionarea dispozitivelor externe;
• evidenţa timpului real;
• reacţia la evenimentele exterioare (oprire de urgenţă);
• gestiunea informaţiilor (păstrarea şi întreţinerea fişierului jurnalului de bord).

Existenţa unor restricţii (cerinţe) stricte a duratei de prelucrare a informaţiilor,


noţiunea de tratare prioritară, conectarea la nişte dispozitive exterioare de măsurare şi
acţionare sunt caracteristice aplicaţiilor informatice “în timp real”. Pot fi menţionate şi
alte domenii cu comandă în timp real: centralele telefonice, comanda aparatelor de
zbor, robotica, monitoringul medical, etc.

În cazul acestor sisteme caracteristica principală este fiabilitatea: rezultatele unei


funcţionări neadecvate pot fi catastrofale. Sistemul trebuie
01.09.20 să garanteze un serviciu
minim în cazul unor căderi în pană a dispozitivelor tehnice,20
12:47:14
unor evenimente
66
accidentale sau erori umane.
1.1.4.3. Sisteme de operare în timp real

Pentru o lungă perioadă de timp sistemele de operare de timp real au fost utilizate, de
regulă, în aplicaţii specializate cu constrângeri din punctul de vedere al vitezei de
răspuns şi al predictibilităţii. Dezvoltarea excepţională a reţelelor de calculatoare, a
Internetului şi necesitatea tot mai stringentă de asistare a aplicaţiilor în timp real (în
special multimedia) pe calculatoare de tip desktop au impus apariţia sistemelor de
operare de timp real.

Proiectarea sistemelor de operare de timp real este mult mai complicată decât
proiectarea sistemelor de operare clasice datorită numeroaselor condiţionări ce trebuie
rezolvate în timpul execuţiei (engl., runtime) şi care impun schimbarea în mod dinamic
a comportării unui element de execuţie (proces, task, thread).

Prin definiţie, toate aplicaţiile de tip Internet includ aspecte de timp real. Menţionăm
câteva dintre sistemele de operare de timp real comerciale mai cunoscute: QNX,
VxWorks, pSOS, Vrtx, OS/9, Lynx. Majoritatea acestor sisteme de operare sunt
portabile, fiind implementate pe numeroase procesoare.

O definiţie simplistă a software-ului de timp real ar fi: este acel software care trebuie să
opereze în cadrul unor constrângeri specifice de timp.

01.09.20
20 67
12:47:14
1.1.4.4. Sisteme tranzacţionale

Caracteristicile principale:
• sistemul gestionează un set de informaţii sau baze de date, care pot atinge volume
importante de informaţie;
• asupra acestor informaţii pot fi executate un anumit număr de operaţii predefinite
sau tranzacţii, adesea interactive;
• sistemul este dotat cu un mare număr de puncte de acces şi un mare număr de
tranzacţii se pot derula simultan.

Ca exemplu pot fi menţionate sistemele de rezervare a biletelor de tren sau avion, de


gestionare a conturilor bancare, de arhivare şi consultare a documentelor.

Restricţiile sunt în primul rând legate de integritatea şi coerenţa internă a informaţiilor,


care formează bazele de date. Aceste restricţii depind, evident, de aplicaţie.

De exemplu, numărul de locuri rezervate într-un avion nu poate depăşi numărul


locurilor disponibile, un loc distinct poate fi atribuit unei singure persoane, etc.

Caracteristicile obligatorii ale unui astfel de sistem tranzacţional sunt disponibilitatea şi


fiabilitatea; pentru unele sisteme poate fi importantă şi toleranţa la defecţiuni. O
caracteristică importantă ale sistemelor tranzacţionale este multitudinea activităţilor
paralele, iar în multe cazuri şi repartizarea geografică a componentelor.
01.09.20
20 68
12:47:14
1.1.4.5. Sisteme în timp partajat

Destinaţia principală a unor astfel de sisteme este furnizarea serviciilor necesare unei
mulţimi de utilizatori, fiecare dintre ei beneficiind de servicii:
• echivalente serviciilor unui calculator individual;
• legate de existenţa unei comunităţi de utilizatori: partajarea informaţiilor,
comunicaţii între utilizatori.

Problemele care apar datorită conceptului de partajare a timpului sunt o combinaţie a


problemelor existente în cazul unui calculator individual cu cele din sistemele
tranzacţionale şi pot fi clasificate după cum urmează:
• definirea maşinii virtuale oferite fiecărui utilizator;
• partajarea şi alocarea resurselor fizice comune: procesoare, memorii, dispozitive
de comunicaţie;
• gestionarea informaţiilor partajate şi a comunicaţiilor.

Caracteristicile obligatorii ale unui astfel de sistem îmbină, în egală măsură, calităţile
unui sistem de operare al unui calculator individual şi al unui sistem tranzacţional, cum
ar fi: disponibilitatea, fiabilitatea, securitatea, exploatarea optimă a caracteristicilor
resurselor fizice, calitatea interfeţei şi serviciilor utilizatorului, facilitatea adaptării şi
extensibilităţii.

01.09.20
20 69
12:47:14
1.2. Sistemul de operare şi procesele
Noţiunea de proces este asociată conceptului de lucrare şi poate fi definită ca o suită
temporală de execuţii de instrucţiuni, considerată ca fiind o entitate de bază în
descrierea sau analiza funcţionării unui sistem. Evoluţia în timp a unui proces
presupune un consum de resurse, dictat de natura şi complexitatea instrucţiunilor de
execuţie. Orice utilizare a unei resurse este asociată, la un moment dat, unui proces şi
procesul respectiv îşi asumă răspunderea de utilizare a acestei resurse. În particular,
rezultă că ori de câte ori se execută procedurile de sistem, resursele, pe care le
utilizează acesta, intră în administrarea procesului, care a cerut serviciul. Resursele
alocate unui proces variază în timp.

Anterior un sistem de operare a fost definit ca un set de programe destinat să


administreze resursele. Care sunt relaţiile dintre componentele sistemului de operare?
Atunci când un proces este creat, care este ordinea de utilizare a unui program anume?

Procesul 1
Procesul 2
Procesul 3
Sistemul de
operare

Fig.1.7. Trei procese într-un sistem cu multiprogramare.


01.09.20
20 70
12:47:14
Ciclul de viaţă a unui proces poate fi reprezentat printr-un set de stări ale procesului şi
trecerea de la o stare la alta. Vom evidenţia trei stări elementare ale unui proces:
proces ales (sau exe) – procesului i s-a alocat un procesor, este în curs de execuţie,
proces blocat – procesul aşteaptă să se producă un anumit eveniment, al cărui apariţie
este indispensabilă, proces eligibil – procesul are la dispoziţie toate resursele necesare,
lipsă fiind doar procesorul, adică procesul este pregătit să se execute din momentul
alocării unităţii centrale (fig.1.8).

Procesului i s-a
alocat
procesorul Procesul
aşteaptă
Ales (Exe) terminarea
operaţiei I/O

Operaţia de
I/O s-a
terminat

Eligibil Blocat
(Ready) (Wait)

Fig. 1.8. Ciclul de viaţă a unui proces


01.09.20
20 71
12:47:14
Administrarea
memoriei
Administrarea
Expirarea dispozitivelor Administrarea
intervalului Eliberarea procesoarelor
de timp memoriei
Starea Eliberarea Eliberarea
procesorului dispozitivelor procesorului
Administrarea
procesoarelor
Ales Terminare
Administrarea
procesoarelor
Cerere de citire
informaţii

Prezentare Păstrare Eligibil Blocat


Gestiunea
informaţiei

Administrarea Iniţiere I/O


Administrarea procesoarelor
resurselor
Administrarea
Toate procesoarelor Administrarea
MO este accesibilă? dispozitivele sunt dispozitivelor
alocate?

Creare proces I/O


Gestiunea Semnal
informaţiei Administrarea Administrarea
memoriei dispozitivelor
Administrarea
01.09.20 procesoarelor
72 20
12:47:14
Fig.1.9. Schimbarea stărilor unui proces şi componentele SO responsabile de aceste
schimbări
Setul de instrucţiuni realizat hardware împreună cu instrucţiunile suplimentare ale
sistemului de operare formează sistemul de comenzi al maşinii extinse. În fig.1.10. este
reprezentat (în mod grafic) conceptul de maşină extinsă.

Procesul 1 Procesul 2
Maşina extinsă

Maşina “goală” Programele


utilizatorului
(procese)

Sistemul de operare
Procesul 4
Procesul 3

Fig.1.10. Maşina extinsă.

Nucleul sistemului de operare va fi executat pe maşina “goală”, iar programele


utilizatorului – pe maşina extinsă. Să facem cunoştinţă acum
01.09.20
20
cu modul în care sunt
73
organizate într-un tot întreg componentele sistemelor de operare.
12:47:14
Componente ale S.O.

Sistemul de operare Sistemul de operare


Procesul A Procesul B

Procesul 1 Procesul 2
Maşina extinsă externă

Maşina extinsă
internă

Maşina Programele
“goală” utilizatorului
(procese)

Funcţii cheie ale


S.O.

Procesul 4 Alte funcţii Procesul 3


ale S.O.

Fig.1.11. Ilustrarea conceptului de maşină ierarhică,

01.09.20
20 74
12:47:14
Taskuri

Planificator de taskuri

Procesul 2
Procesul 1 Procesul 3 Procese I/O care
I/O de sistem deservesc procesul 3
al utilizatorului
Proces creat Stratul 2
de utilizator

Proces I/O
Nivelul 5
Stratul 1
Nivelul 4

Nivelul 3

Nivelul 2 Stratul 0
Nivelul 1

Maşina
“goală”
Administrare
procesoare (P,V),
planificare procese
Administrare memorie
Administrare procesoare (nivel superior,
mesaje, creare şi distrugere procese)

Administrare dispozitive
01.09.20
Administrare informaţie 20 75
12:47:14

Fig.1.12. Structura ierarhică a sistemului de


2. Tehnici de execuție și comunicație
2.1. Modul secvenţial de execuţie a unui program
2.1.1. Noţiuni fundamentale
2.1.2. Starea şi contextul procesorului
2.2. Întreruperi, devieri (excepții), apelarea supervizorului
2.2.1. Activităţi asincrone
2.2.2. Mecanisme de comutare a contextului
2.2.3. Întreruperi
2.2.4. Devieri şi apelarea supervizorului
2.2.5. Exemple de sisteme de întreruperi
2.3. Implementarea mecanismelor de comutare a contextului
2.3.1. Utilizarea devierilor şi apelării supervizorului
2.3.2. Exemple de utilizare a întreruperilor
2.3.3. Concluzii
2.4. Programarea operaţiilor de intrare-ieşire
2.4.1. Organizarea generală
2.4.2. Metode de comandă a perifericelor
2.4.3. Intrări-ieşiri buferizate în memorie
2.4.4. Încărcarea iniţială
Exerciţii
Mecanismele, care dau posibilitatea unui calculator să interacţioneze cu mediul exterior, pe de o
parte, şi să manipuleze mai multe sarcini, pe de alta, formează baza oricărui SO.
Modul secvenţial de execuţie a unui program
Nucleul: memoria + procesorul. Instrucţiunile şi datele se află în segmente distincte.
Execuţia instrucţiunilor conduce la evoluţia stării calculatorului. Evoluţia stării calculatorului poartă caracter
discret, starea este observabilă doar în momente de timp - puncte de observare.
Starea calculatorului: starea procesorului şi starea memoriei.
Starea memoriei: conţinutul locaţiunilor segmentelor încărcate în memorie.
Starea procesorului: conţinutul setului de regiștri, ataşate procesorului.
Program secvenţial = mulţime de proceduri, care se pot apela reciproc. Fiecărei proceduri îi este asociat un
segment distinct de procedură. Datele sunt reprezentate prin segmente, pot fi proprii unei proceduri sau
partajate între mai multe proceduri.
Activitate - fenomenul care rezultă din execuţia neîntreruptă a unei proceduri unice. !!Execuţia unui
program secvenţial constă dintr-un lanţ de activităţi!!!!
Context al unei activităţi: mulţimea informaţiilor accesibile procesorului în cursul acestei
activităţi. Contextul activităţii este compus din contextul procesorului și contextul memoriei.
Trecerea de la o activitate la alta este realizată de instrucţiuni speciale: apelarea şi returul din
procedură, care realizează comutarea contextului.

01.09.2020 12:47:14
77
Exemplul 2.1. O procedură p (apelantă) provoacă execuţia unei proceduri q
(apelate) cu ajutorul unei secvenţe de apel care conţine următoarele etape:
1. Pregătirea parametrilor, transmişi de către procedura p procedurii q,
2. Salvarea parţială a contextului lui p, necesar la retur,
3. Înlocuirea contextului procedurii p prin contextul lui q.

La revenire din q avem o schemă simetrică, doar contextul lui q fiind pierdut:
1. Pregătirea rezultatelor, transmise de către procedura q procedurii p,
2. Restabilirea contextului procedurii p, salvat înainte de apel.◄

2.1.1.1. Mecanisme de execuţie secvenţială


Vom descrie un mecanism general pentru execuţia programelor secvenţiale,
formate dintr-o suită de activităţi, rezultate din execuţia unei
proceduri. Acest mecanism realizează funcţiile următoare:
1. Salvarea şi restabilirea contextului la apelare şi retur,
2. Transmiterea parametrilor între procedurile apelantă şi apelată,
3. Administrarea unei zone de lucru proprii fiecărei proceduri, cu
permisiunea apelurilor recursive.

01.09.2020 12:47:14 78
Structura de date - stiva de execuţie. Respectare ipoteze:
1. Parametrii unei proceduri sunt transmişi prin valori; la retur un singur rezultat este returnat,
2. Procedurile pot fi apelate recursiv (direct sau indirect).

La fiecare apelare a procedurii o structură de date numită regiune a mediului (sau


simplu mediul procedurii) este creată în vârful stivei de execuţie, care va dispare la
returul respectiv. O procedură apelată recursiv are în stivă atâtea medii câte execuţii
neterminate există pentru această procedură. La un moment concret de timp mediul din
top-ul stivei corespunde procedurii q în curs de execuţie (procedura activă), mediul
imediat următor este al procedurii p, care a apelat procedura q, etc. Stiva este
administrată prin intermediul a doi pointeri (fig.2.1.):
baza pointerul care indică baza mediului procedurii active,
top pointerul care indică primul amplasament liber pentru a crea un nou mediu.
top
q
top
baza
p
p
baza
Stivă Mediul procedurii
Stivă
Înainte de apelarea procedurii q
de către procedura p După apelarea procedurii q

Fig.2.1. Stiva de execuţie


79
01.09.2020 12:47:14
Mediul procedurii conţine următoarele informaţii:
informaţii de salvare şi legăturile de retur
un pointer la baza contextului procedurii apelante
adresa returului
un amplasament pentru rezultat
parametri
n+1 amplasamente, primul conţinând numărul de parametri,
variabilele locale şi spaţiul de lucru al procedurii.

Operaţiile executate la apelarea şi returul procedurii sunt următoarele:


Apelare
alocarea unei zone în stiva de execuţie pentru mediul procedurii apelate
temp:=baza
baza:=top
top:=top+dimensiunea mediului
salvarea informaţiilor de retur Rezumat: contextul memoriei unei
baza_veche:=temp activităţi la un moment curent de timp
memorizarea adresei de retur conţine, în afara segmentului
procedurii în curs de execuţie şi
ordonarea parametrilor
segmentele de date, zona mediului
executarea unei ramificaţii la procedura apelată. curent din stiva de execuţie.
Retur
salvarea rezultatului într-un amplasament stabilit
restabilirea informaţiilor de retur şi eliberarea mediului
temp:=adresa de retur
top:=baza
baza:=baza_veche 01.09.20
returul 20
12:47:14
80
ramificare *temp ramificare indirectă
Starea şi contextul procesorului
Starea procesorului este determinată de conţinutul registrelor acestuia. Registrele pot fi:
adresabile, numite registre generale, manipulate de programe,
registre speciale - cuvânt de stare program (program status word, PSW).
PSW conţine informaţii:
Referitoare la starea procesorului:
Starea de execuţie. Procesorul se poate afla în starea activ în care îndeplineşte instrucţii, sau în
starea de aşteptare, când execuţia este suspendată.
Modul de funcţionare:
Protecţie - se permite doar programelor SO executarea unor instrucţiuni anumite (speciale),
programele utilizatorilor neavând acces la aceste instrucţiuni. Aceasta poate fi realizat definind
două moduri de funcţionare a procesorului, care se deosebesc printr-un bit indicator în cuvântul
de stare: modul supervizor şi modul program.

Masca întreruperilor.

Referitoare la contextul accesibil al memoriei şi drepturile de acces asociate: tabele de


segmente, indicatori de protecţie a memoriei, etc.

Referitoare la derularea activităţii curente: codul condiţiei, contorul operaţiei următoare


(contor ordinal). Pentru unele calculatoare contorul, care conţine adresa operaţiei următoare, poate fi
un registru distinct al cuvântului de stare, pentru altele el este un câmp al acestui cuvânt.

01.09.20
20 81
12:47:14
Întreruperi, excepții, apelarea supervizorului

Activităţi asincrone

Modelul descris mai sus poate fi folosit doar pentru un singur program, reprezentat printr-o
secvenţă de activităţi, executate pe un singur procesor. Unicele mecanisme necesare pentru
organizarea comunicărilor între activităţi sunt operaţiile de apelare şi retur.

Pentru cazuri mai generale sunt necesare noțiuni suplimentare, cum ar fi conceptele de
asincronism sau de protecţie reciprocă între activităţi.

Asincronism - efectul care îl pot avea asupra unei activităţi anumite evenimente exterioare.

Protecţie reciprocă între activităţi - modificarea mai profundă a contextului, atunci când se
trece de la o activitate la alta, în comparaţie cu un simplu apel de procedură.

Un caz tipic de asincronism este executarea intrărilor-ieşirilor simultan cu execuţia unui


program. Trebuie să fie asigurată posibilitatea informării programului despre terminarea
unui transfer de informaţii. O primă posibilitate, care nu necesită utilizarea unor dispozitive
speciale este cea a aşteptării active.

82
01.09.2020 12:47:14
CDC Cyber 170: un PC şi 10 PP. Programele sistemului de operare erau executate pe
PP: unul dintre acestea, numit PS, are "grijă" de înlănţuirea lucrărilor şi alocarea
resurselor, celelalte, notate PES(i), erau specializate în operaţii de I/E. PC şi PP
comunicau prin intermediul unei memorii comune:

programul utilizatorului programul supervizor programul pentru I/E


<cerere de I/E> ciclu ciclu
D:=1; if D=1 then if DEX(i)=1 then
F:=0; caută PES(i); execută I/E;
…… DEX(i):=1; <sincron>
FEX(i):=0; FEX(i):=1;
endif endif
<test terminare I/E> …… endciclu
if F=1 then <test terminare execuţie>
…… if FEX(i)=1 then
F:=1;
endif
endciclu
Comentarii:
1. relaţiile între PC şi PS, pe de o parte, şi PS şi PES, pe de alta, au aceeaşi schemă.
2. procesorul central este în totalitate eliberat de operaţiile de I/E.
3. operaţiile de I/E sunt ele însăşi separate în două părţi: supervizarea (alegerea procesorului de
intrare-ieşire în funcţie de starea lui PES şi urgenţa operaţiei) şi transferul propriu-zis.

83
01.09.2020 12:47:14
Mecanisme de comutare a contextului

Comutarea contextului unui procesor permite executarea într-o manieră indivizibilă


(atomară) a următoarelor două operaţii:
1. trecerea cuvântului de stare într-un amplasament specificat al memoriei,
2. încărcarea în cuvântul de stare a conţinutului unui alt amplasament specificat al memoriei.

Comutarea contextului poate fi necesară din mai multe cauze distincte. Presupunem că
fiecărei cauze i-a fost asociat un număr de ordine. Pot fi întâlnite două scheme de
comutare a contextului.
1. Salvare în amplasamente fixe. Fiecărei cauze (numărul unei cauze fiind i) îi sunt ataşate în
mod constant două amplasamente de memorie adresele cărora le vom nota prin
csp_vechi[i] şi csp_nou[i] (csp semnificând cuvânt de stare program). Comutarea se
produce după cum urmează:
Mp[csp_vechi[i]]:=<cuvânt de stare program>
<cuvânt de stare program>:= Mp[csp_nou[i]]
În setul de instrucţiuni există o instrucţiune privilegiată schimbă_csp(adr) cu următorul efect:
<cuvânt de stare program>:= Mp[adr].
2. Salvare într-o stivă. Acelaşi procedeu în ceea ce constă cuvântul de stare nou. Însă
cuvântul de stare vechi nu este salvat într-un amplasament fix, ci într-o stivă specială:
ptr :=ptr+1
stiva[ptr] :=<cuvânt de stare program>
<cuvânt de stare program> := Mp[csp_nou[i]]
Instrucţiunea schimbă_csp(adr) este identică celei din 1); există însă şi o instrucţiune
restabileşte_csp, care restabileşte PSW folosind pentru acesta top-ul stivei:
<cuvânt de stare program> :=stiva[ptr]
ptr :=ptr-1 01.09.20
20 84
12:47:14
Comutarea contextului, descrisă mai sus, este declanşată sub influenţa stării unor
indicatori interni (din PSW) pe care procesorul îi consultă la interpretarea fiecărei
instrucţiuni. Conform semnificaţiei acestor indicatori şi maniera în care ei sunt
modificaţi, pot fi evidenţiate trei mecanisme de comutare, descrise în tabelul de mai
jos:
Tabelul 2.1. Mecanisme de comutare a contextului
Denumirea Cauza Utilizarea
mecanismului

Întrerupere Exterioară derulării Reacţionare la un eveniment


instrucţiunii curente asincron extern

Excepții (devieri, Legată de derularea Tratarea unei erori sau situaţii


întreruperi programate) instrucţiunii curente excepţionale

Apelarea supervizorului Comutare explicită Apelarea unei funcţii a S.O.

Adesea toate aceste trei denumiri sunt înlocuite cu una singură - întrerupere.

01.09.2020 12:47:14 85
Întreruperi
Întreruperea - comutarea contextului procesorului declanşată de o cauză externă derulării
instrucţiunii curente. Fizic = trimiterea unui semnal procesorului, acest semnal provocând
schimbarea stării unuia dintre indicatorii, consultaţi în cursul executării fiecărei
instrucţiuni. Semnalul poate proveni de la alt procesor, de la un organ de I/E, de la un
dispozitiv extern, şi în genere, de la orice proces fizic, extern procesorului întrerupt.
O întrerupere permite să cerem procesorului să suspende executarea programului curent,
din primul punct întreruptibil, şi să treacă la execuţia unui program predefinit. Acesta din
urmă este numit program de tratare a întreruperii (interrupt handler, eng., traitant de
l'interruption, fr.). Programul de tratare a întreruperii este executat într-un context diferit
de cel al programului întrerupt, diferenţa fiind legată de modul de tratare, protecţie,
informaţiile accesibile, etc.
Nivele de prioritate. Cauzele care duc la necesitatea întreruperii unui procesor sunt diferite,
drept rezultat şi programele predefinite, care tratează întreruperile diferă. Mecanismul
întreruperilor trebuie să poată deosebi aceste cauze. Două scheme de bază sunt utilizate în
acest scop:
1. Există un indicator unic pentru toate întreruperile. Acestui indicator îi este asociat un
program de tratare a întreruperilor. Codul întreruperii, care se conţine în PSW sau într-un
amplasament de memorie, dă posibilitatea deosebirii cauzelor. Programul de tratare a
întreruperilor consultă mai întâi codul întreruperii pentru a stabili originea acesteia, apoi se
va trece la tratarea propriu-zisă.

2. Fiecărei cauze este ataşat un indicator, se mai spune că fiecare cauză este ataşată unui nivel
de întrerupere. Fiecărui nivel îi corespunde un program distinct de tratare a întreruperii,
activat în mod automat de către mecanismul de comutare a contextului.
86
01.09.2020 12:47:14
Întreruperi

87
01.09.2020 12:47:14
Armare Dezarmat

Întrerupere Dezarmare

Declanşare
programată Armat

[ Punct de întrerupere ]
Aşteptare

[ Nivel cu masca eliminată ]


[Nu există nivel activ cu o prioritate mai mare]

Activ
Achitare

88
01.09.2020 12:47:14 Fig.2.3. Stările unui nivel de întrerupere
Priorităţi şi mascarea întreruperilor. Atunci când există mai multe nivele de întrerupere este
posibilă necesitatea modificării simultane a doi indicatori, legaţi de două cauze diferite. Conflictul
poate fi reglat stabilind o ordine de prioritate în cadrul nivelelor de întrerupere.

Protejarea contra unor întreruperi anume a execuţiei unei suite de instrucţiuni.


Aceasta ar însemna întârzierea comutării contextului. Se zice atunci, că nivelul este
mascat sau dezactivat. Activarea ("demascarea") va autoriza schimbarea ulterioară a
contextului.

Pentru unele nivele de întrerupere efectul sosirii semnalului de întrerupere poate fi


suprimat de parcă însăşi cauza întreruperii a fost suprimată: nivelul întreruperii este
dezarmat. Un nivel dezarmat poate fi rearmat, adică repus în serviciu.

Declanşare programată. Pentru unele calculatoare există o instrucţiune de declanşare programată care
permite modificarea indicatorului, asociat unui nivel de întrerupere, din interiorul unui program.

Atunci când toate condiţiile necesare pentru ca o întrerupere să fie luată în consideraţie
sunt prezente, nivelul se numeşte activ. Această stare corespunde executării
programului de tratare a întreruperii.

Ieşirea din starea activă se face prin achitarea întreruperii. Achitarea este realizată
folosind instrucţiunea schimbă_csp, care termină tratarea schimbând contextul.
Operaţiile de armare-dezarmare, mascare-demascare şi declanşare a întreruperilor sunt
totdeauna realizate prin intermediul unor instrucţiuni privilegiate.
89
01.09.2020 12:47:14
Schema unui program de întrerupere.
O întrerupere forţează procesorul să reacţioneze la un eveniment. Executarea
programului curent este suspendată, comanda fiind transmisă programului de tratare a
întreruperii. Programul reluat de către procesor după tratarea întreruperii nu este în
mod obligator programul întrerupt (întreruperea putea avea drept scop realocarea
procesorului). Schema generală de tratare a unei întreruperi este prezentată în fig.2.4.
Programul întrerupt P
Tratarea întreruperii

Comutarea cuvântului de stare


Salvarea contextului
programului P

Tratarea specifică întreruperii, care presupune


determinarea programului Q pentru lansare (poate fi
chiar P sau altul)

Restabilirea contextului programului Q încărcarea


cuvântului de stare a lui Q

Instrucţiunea schimbă_csp (achitare)


01.09.20
Programul nou Q 20 90
12:47:14
Fig.2.4. Schema generală a tratării unei întreruperi
Excepții şi apelarea supervizorului

Spre deosebire de o întrerupere, o excepție (trap) ca și apelul supervizorului sunt


provocate de o cauză legată direct de derularea instrucţiunii curente.

O excepție (trap, eng., dèroutement, fr.) semnalizează o anomalie în derularea unei


instrucţiuni, care prohibitează executarea instrucţiunii. Originile pot fi diverse:
date incorecte, care conduc la imposibilitatea execuţiei instrucţiunii (împărţirea la zero,
de exemplu), tentativa executării unei operaţii interzise de mecanismul de protecţie
(violarea protecţiei memoriei, executarea unei instrucţiuni privilegiate în modul
program ...), instrucţiune neexecutabilă.

Excepțiile pot fi clasificate, ca şi întreruperile, conform cauzelor care le generează.


Efectul unor cauze poate fi suprimat (de exemplu devierile legate de operaţiile
aritmetice, erorile fiind semnalate doar de valoarea codului condiţiei, sau erorile legate
de lipsa unei pagini virtuale în memoria fizică).

Important! Natura unei devieri nu permite aplicarea noţiunii de mască. O deviere poate
fi suprimată, dar nici intr-un caz retardată.

01.09.20
20 91
12:47:14
Un apel al supervizorului (supervisor call, SVC, appel au superviseur, fr.) este o
instrucţiune chemată să provoace o comutare explicită a contextului procesorului.

Acest efect este analogic apelării unei proceduri, însă modificarea contextului este mai
profundă, fiindcă ea afectează întreg cuvântul de stare, nu numai contorul ordinal.

Destinaţia unui apel al supervizorului este de a permite apelarea unei proceduri a


sistemului de operare, pretinzând la drepturi mai mari (modul master, mascare
întreruperi, drepturi de acces, etc.), direct din programul utilizatorului. Mecanismul
comutării contextului permite asigurarea protecţiei.
Ca rezultat: contextul nou (modul, masca,...) este specificat în noul cuvânt de stare,
amplasat intr-o zonă de memorie inaccesibilă utilizatorilor, programul de tratare a
apelului supervizorului începe cu o secvenţă de verificare a drepturilor utilizatorului de
a executa acest apel şi stabilirea validităţii parametrilor transmişi.

Parametrii sunt transmişi ca şi în cazul apelului unei proceduri obişnuite. Returul în


programul apelant se face prin restabilirea cuvântului de stare salvat la apelare.

Alegerea procedurii accesibile în cazul unui apel al supervizorului este determinată de


un parametru suplimentar. Putem considera, că mulţimea procedurilor accesibile
utilizatorului în acest mod constituie o extensie a setului de instrucţiuni, formând astfel
o "maşină" nouă.
Operaţiile de accesare a fişierelor şi de intrare-ieşire sunt disponibile utilizatorilor sub
forma SVC. 01.09.20
20 92
12:47:14
Exemple de sisteme de întreruperi

Exemplul 2.6. IBM 370.


Cuvântul de stare (64 biţi) conţine următoarele câmpuri:
<0-7> masca întreruperii <16-31> codul întreruperii
<8-11> cheie de protecţie <32-33> lungimea instrucţiunii
<12> codul caracterelor <34-35> codul condiţiei
<13> masca întreruperii <36-39> suprimarea devierii
<14> 1 - aşteptare, 0 - activ <40-63> contor ordinal
<15> 0 - stăpân, 1 - sclav.

Sistemul de întreruperi are 5 nivele (în ordinea de descreştere a priorităţilor): eroare


hardware, deviere, apelare supervizor, extern şi intrare-ieşire. Fiecărui nivel îi
corespunde în memoria operativă un cuplu de amplasamente rezervate cuvintelor de
stare vechi şi nou. Fiecare nivel conţine mai multe cauze de întrerupere. Pentru a face o
deosebire a acestor cauze este utilizat un cod al întreruperii format din biţii 16 - 31 ai
PSW. Acest cod este în mod automat pus la zi în cazul unei întreruperi. De exemplu,
pentru o întrerupere de intrare-ieşire el va conţine adresa canalului şi a perifericului
care au provocat întreruperea; pentru o întrerupere externă acest cod permite să se
stabilească originea - ceasul, apel al operatorului, adresare a unui organ extern, etc.

Biţii 0 - 7 şi 13 ai PSW - masca întreruperii. Permit mascarea nivelelor de întrerupere


externă, eroare hardware şi, selectiv, întreruperile de intrare-ieşire, care provin de la
diferite canale. Biţii 36 - 39 permit inhibarea a 4 cauze de deviere.
Devierile şi apelările supervizorului sunt tratate ca şi01.09.20
întreruperi particulare.◄
20 93
12:47:14
Exemplul 2.7. IBM PC. Este propus ca exerciţiu.
Implementarea mecanismelor de comutare a contextului

Implementarea mecanismelor este ilustrată prin exemple, legate de utilizarea lor.

Vom preciza notaţia utilizată în schemele programelor:


1. conţinutul unui cuvânt de stare este reprezentat prin notaţia <activitate, mod, mascare,
contor ordinal>. Primele trei câmpuri pot lua, respectiv, valorile: aşteptare/activ,
master/slave, mascat/demascat. Dacă csp desemnează un cuvânt de stare, câmpurile sale
vor fi desemnate de csp.act, csp.mod, csp.masc şi csp.co.
2. operatorul adr aplicat unui identificator de variabilă sau de procedură, desemnează adresa
amplasamentului unde se află variabila sau prima instrucţiune a procedurii,
3. notaţia Mp[adr] desemnează conţinutul amplasamentului cu adresa adr.
4. notaţiile svc_vechi, dev_vechi, intr_x_vechi, svc_nou, dev_nou, intr_x_nou desemnează
amplasamentele unde sunt plasate şi de unde sunt încărcate cuvintele de stare.

Vom mai presupune că


1. apelarea supervizorului este de forma SVC <cod>, unde <cod> reprezintă un
număr care permite identificarea funcţiei cerute,
2. un indicator <cauză> permite stabilirea cauzei care provoacă o deviere.

Schemele prezentate conţin un program de iniţializare, executat la prima încărcare a


sistemului. Funcţia acestui program este de a iniţializa cuvântul de stare asociat
tratării întreruperilor, devierilor şi apelurilor supervizorului.
01.09.20
20 94
12:47:14
Simularea instrucţiunilor lipsă. Tentativa executării unei instrucţiuni opţionale lipsă
generează o drivere de tipul instrucţiune inexistentă. Realizarea prin program:
procedura iniţializare;
dev_nou:=<activ,master,mascat, adr tratare_deviere>;
csp[ADD_FL]:= <activ,slave,demascat, adr ADD_FL>;
……
csp [DIV_FL]:= <activ,slave,demascat, adr DIV_FL>;
procedura tratare deviere;
begin
save(zonă);
case cauză of
……
instrucţiune inexistentă:
cod_op:=Mp[dev_vechi.co].cod_operaţie;
case cod_op of
……
ADD_FL: determinarea operanzilor;
introdu_în_stivă(stivă_utilizator,dev_vechi.co+1);
încarcă_csp(csp[ADD_FL])
……
else -- caz de eroare
<tratarea erorii>
end;
end;
01.09.20
restabilire(zonă); 20 95
încarcă_csp(dev_vechi) 12:47:14

end
Măsurarea capacităţii memoriei. SO trebuie să se adapteze configuraţiei concrete, ca şi
condiţiilor particulare de utilizare (număr de utilizatori, priorităţi, etc.). Crearea unei
asemenea versiuni specifice se numeşte generarea sistemului de operare. Pentru a
reduce frecvenţa generărilor S.O. unii parametri de configurare pot fi determinaţi în
mod automat la iniţializare.
Astfel, poate fi determinată capacitatea memoriei operative utilizând o deviere pentru
adresa amplasamentului de memorie inexistent.
Realizarea prin program:
program principal:
begin
dev_nou:= <activ,master,mascat, adr măsurare>;
i:=1;
ciclu
<accesare cuvânt cu adresa i.p>;
i:=i+1;
endciclu;
ieşire ciclu: nbloc:=i;
dev_nou := <activ,master,mascat, adr tratare_deviere>;
end
procedura măsurare; -- apelare prin deviere
if cauză = adresă în afara memoriei then
csplucrare:= <activ,master,mascat, adr ieşire ciclu>;
încarcă_csp(csplucrare)
endif
01.09.20
La ieşirea din programul de măsurare a capacităţii memoriei
20 se va96restabili tratarea
normală a devierilor (procedura tratare_deviere). 12:47:14
Limitarea timpului de execuţie a unei proceduri. Realizarea prin program:
procedura iniţializare;
intr_ceas_nou:=<activ,master,mascat,adr intr_ceas>;
svc_nou :=<activ,master,mascat,adr tratare_svc >;
dezarmare(intr_ceas);
procedura tratare_svc;
save(zonă);
case cod of

apel_lim_timp_ex: -- parametrii p, q, tratare_eroare
ceas:=q;
cspretur:=svc_vechi; -- salvare pentru retur
csplucrare:= <activ,slave,demascat,adr p>;
csperoare:= <activ,slave,demascat,adr tratare_eroare>;
armare(intr_ceas);
restabileşte(zonă);
încarcă_csp(csplucrare);

retur: -- datorat terminării procedurii p
dezarmare(intr_ceas);
încarcă_csp(cspretur);

endcase
procedura intr_ceas; -- expirarea timpului limită
dezarmare(intr_ceas);
încarcă_csp(csperoare); 01.09.20
20 97
12:47:14
Culegerea unor date de măsurare. Perioada ceasului este de 5 μs. Datele trebuie culese
fiecare 100 ms. Deoarece timpul necesar culegerii datelor este cu mult inferior
perioadei de eşantionare, calculatorul poate executa alte lucrări în regim de fond.
Măsurare Măsurare Măsurare Măsurare

Realizarea prin program: Fond Fond Fond Fond

const q = 20000 -- 100ms/5μs Iniţializare


procedura iniţializare; 100 ms 100 ms 100 ms 100 ms 100 ms
begin
intr_ceas_nou:=<activ,master,mascat,adr intr_ceas>;
csplucrare:= <activ,slave,demascat,adr fond>;
cspmăsurare:= <activ,slave,demascat,adr măsurare>;
ceas:=q;
încarcă_csp(cspdev)
end
procedura intr_ceas;
begin
save(zonă); salvarea contextului de fond
cspsave:=intr_ceas_vechi; salvarea cuvântului de stare pentru fundal
ceas:=q;
încarcă_csp(cspmăsurare) programul de culegere a datelor
end

Programul de măsurare trebuie să se termine printr-o apelare a supervizorului SVC


retur efectul căreia este de a restabili contextul lucrului în fond. Acest apel execută
secvenţa:
restabileşte (zonă);
încarcă_csp(cspsave); 01.09.20
20 98
12:47:14
Concluzii

Exemplele precedente ilustrează modurile elementare de comunicare dintre programele


unui sistem de operare şi mediul exterior. Programele sistemului sunt activate:
1. de un program al utilizatorului, care semnalează o anomalie sau cere achitarea unui
serviciu,
2. de un dispozitiv extern (ceas, proces comandat, organ periferic sau linie de comunicaţii),
care semnalează producerea unui eveniment şi care cere o reacţie imediată a sistemului.

Ca şi rezultat putem afirma că un sistem de operare este pilotat de evenimente (event-


driven).

Important! Comunicaţia internă între programele unui sistem foloseşte apelarea


supervizorului dacă un anumit tip de protecţie trebuie să fie activat (program
executat în modul slave, de exemplu) şi apelarea unei proceduri obişnuite în caz
contrar.

O secvenţă de execuţie a unui program de sistem se termină prin încărcarea unui


cuvânt de stare a procesorului care permite controlul total al contextului restabilit.

01.09.20
20 99
12:47:14
Programarea operaţiilor de intrare-ieşire

Intrare-ieşire numim orice transfer de informaţii din sau spre nucleul calculatorului.

Operaţiile de I/E semnifică:


1. transferurile de informaţii dintre diferite nivele ierarhice ale memoriei,
2. transferurile de informaţii din sau spre mediul exterior (organe periferice
locale sau la distanţă, captoare sau dispozitive de acţionare, alte
calculatoare, etc.).
2.4.1. Organizarea generală
2.4.1.1. Periferice, controlere, canale
Un organ de intrare-ieşire este un dispozitiv capabil să transfere informaţii între procesorul sau
memoria calculatorului şi un suport extern de informaţie. Acest transfer este comandat de către
procesorul central. În cel mai simplu caz, o instrucţiune specială a procesorului permite
transferarea informaţiei între suportul extern şi un registru al procesorului, care va fi deci ocupat
pe toată perioadă transferului informaţiei.

Odată cu evoluţia calculatoarelor, în scopul unei mai bune utilizări a procesorului s-a ajuns la
necesitatea acordării unei autonomii organelor de intrare-ieşire încredinţându-le funcţii tot mai
complicate de înlănţuire şi comandă, procesorului central lăsându-i-se doar iniţiativa de lansare
şi de control a operaţiilor.

Din considerente economice mai apoi s-a trecut la separarea dispozitivelor de comandă a perifericelor
de perifericele propriu-zise, pentru ca dispozitivele de comandă să poată fi partajate între mai
multe periferice. 01.09.20
20 100
12:47:14
Câteva scheme de organizare a perifericelor sunt prezentate în fig.2.5. Schema (c) este
proprie unui calculator de putere mare, (a) şi (b) corespund configuraţiilor
calculatoarelor de putere mai mică.
Magistrală Magistrală
UC UC

Cp Cp ADM
M M

p p Cp Cp

p p
(a) (b)

UC UC

Magistrală

C C
M
UC : unitate centrală
M : memorie
Cp Cp Cp
C : canal
ADM : acces direct la
01.09.20
memorie
(c) p p p p 20 101
Cp 12:47:14 : controler
p : dispozitiv periferic
Fig. 2.5. Organizarea intrărilor-ieşirilor
Un canal (sau unitate de schimb) este un procesor specializat în operaţiile de intrare-ieşire. El
poate fi lansat doar de un procesor central, nu posedă întreruperi, dar poate întrerupe un
procesor central. Setul de instrucţiuni ale canalului îi permite să acţioneze controlerele şi
perifericele, care-i sunt conectate. Mini- şi microcalculatoarele pot poseda organe, numite Unităţi
de acces direct la memorie (ADM), care sunt nişte canale simplificate.

Un contróler este un dispozitiv de comandă adaptat la un tip concret de echipament periferic.


Autonomia sa este limitată de operaţii foarte elementare. Destinaţia principală a unui controler
este de a permite conectarea a mai multor periferice de acelaşi tip la un singur controler. Un
singur dispozitiv periferic poate transmite informaţii prin intermediul controlerului la un moment
de timp dat. În acelaşi timp, este posibilă executarea simultană a unor operaţii pe alte periferice,
operaţii care nu implică transferul de informaţii (rebobinarea unei bande magnetice, deplasarea
braţului unui disc, etc.). Partajarea funcţiilor între periferic şi controler depinde de tipul
perifericului. De obicei, funcţiile logice (înlănţuirea şi sincronizarea operaţiilor, emiterea unor
semnale în caz de accident sau terminarea normală a execuţiei) sunt încredinţate controlerului,
iar funcţiile fizice (transferul propriu-zis) - perifericului. În programarea intrărilor-ieşirilor nu
este necesar, de obicei, să se facă o deosebire între un controler şi un periferic.

Un periferic este un organ capabil să transfere informaţii din sau spre un suport extern. Controlerul
este legat de periferic printr-o interfaţă, care conţine un set de funcţii (intrare, ieşire,
semnalizări de comandă şi de accident) şi o linie de comunicaţie, care serveşte la transferul
informaţiilor.

Un canal poate comanda un singur dispozitiv periferic cu debit ridicat (disc, de ex.) sau poate fi
multiplexat pentru mai multe periferice cu debitul mai mic.
01.09.20
20 102
12:47:14
Diferite organe sunt desemnate, la fiecare nivel, printr-o adresă care permite să evidenţiem:
canale legate de memorie,
controlere ataşate fiecărui canal,
dispozitive periferice ataşate fiecărui controler.

Adresa este un simplu număr de ordine. Un periferic este desemnat printr-o adresă compusă din
<numărul canalului, numărul controlerului, numărul dispozitivului periferic>.

p
000
0
Controler
p
Canal 0 1 001
0 00

1 0 p 010
Controler
100

Canal 0 1
1 01, 10 p 011
101
110
1 0
Controler
p
111
Această organizare permite ameliorarea 1
11
performanţelor şi disponibilităţii sistemului.
Existenţa mai multor căi de acces la un
periferic diminuează riscul unor 01.09.20
Fig.2.6. Adresarea perifericelor
indisponibilităţi din cauza saturaţiei sau 20 103
12:47:14
ieşirii din funcţiune a unui canal sau
controler.
Metode de comandă a perifericelor
Programul, care controlează funcţionarea elementară a unui dispozitiv periferic se numeşte driver. Driverul
gestionează în mod direct controlerul perifericului, tratează întreruperile generate de acesta, detectează şi
tratează cazurile de eroare.
Vom prezenta mai jos modurile principale de control ale perifericelor şi primitivele elementare de intrare-ieşire.

Intrări-ieşiri sincrone
În acest caz nu există nici un fel de paralelism între procesare şi transferul informaţiilor. Procesorul este ocupat
pentru toată durata transferului.

Specificarea mecanismului

Operaţia de bază constă în transferarea unor informaţii elementare de volum fix între un amplasament de
memorie şi un dispozitiv periferic. Presupunem că volumul informaţiei transmise, care depinde de perifericul
considerat, este un octet. Starea ansamblului controler-periferic este definită printr-un cuvânt de stare, aflat în
controler. Acest cuvânt de stare conţine o mulţime de indicatori booleeni, dintre care 3 ne vor interesa aici:
preg : perifericul este pregătit (gata) de funcţionare,
term : transferul este terminat; perifericul poate să transfere un nou caracter,
err : în cursul transferului a avut loc o eroare.

Controlerul este comandat de UC cu ajutorul a 3 instrucţiuni de intrare-ieşire, efectul cărora este descris mai jos:
IN(adr_mem, adr_perif) : cerere de transfer tip intoducere a unui octet,
OUT(adr_mem, adr_perif) : cerere de transfer tip extragere a unui octet,
TEST(adr_perif) : copie cs într-un registru cu scopul de a consulta indicatorii.

01.09.2020 12:47:14 104


Programul driver-ului

Fie că vrem să extragem o secvenţă de n caractere care se află într-un masiv T[0..n-1].
Caracterul T[i], dacă i>0, poate fi extras doar dacă a fost transferat T[i-1]. Pentru a
verifica această condiţie se testează iterativ (aşteptare activă) indicatorul term.

iniţializare : term:=false;
TEST(adr_perif);
if nonpreg then
<tratare eroare>
endif;
for i:=0 to n-1 do
OUT(adr T[i],adr_perif);
ciclu: TEST(adr_perif);
if err then
<tratare eroare>
endif;
if nonterm then goto ciclu
endif;
endfor

Intrările-ieşirile sincrone sunt folosite la microprocesoarele cele mai simple sau atunci
când procesorul nu poate fi exploatat în mod util în timpul transferului.

105
01.09.2020 12:47:14
Intrări-ieşiri asincrone cu întreruperi

Specificarea mecanismului
Terminarea procesului de transferare a caracterului T[i] este semnalizată printr-o întrerupere.
Dacă acest caracter nu este ultimul (i<n-1), următorul caracter poate fi transmis. Procesul este
declanşat de transferul primului caracter. Acest transfer este cerut de către programul
principal prin intermediul unui apel a supervizorului (SVC intrare sau ieşire), care are drept
parametri: adresa perifericului, numărul de caractere care vor fi transferate, adresa de origine
sau de destinaţie a primului caracter, booleanul term, valoarea TRUE a căruia semnalizează
sfârşitul transferului.
Programul principal programul de tratare a întreruperii
term:=FALSE (la părăsirea lui T[i])
SVC i:=0;
ieşire OUT(adr T[i], adr_perif);
save context;
TEST(adr_perif);
… if err then
<tratare eroare>
else
if i<n-1 then
<tratare paralelă> i:=i+1;
OUT(adr T[i], adr_perif)
… else
term:=TRUE
if term then endif
… endif; 106
<restabilire context>
01.09.2020 12:47:14
Intrări-ieşiri buferizate în memorie
Diferenţa considerabilă dintre viteza de lucru a unităţii centrale şi cea a organelor periferice
impune "buferizarea" intrărilor-ieşirilor, adică introducerea unei zone-tampon de memorie
între periferic şi programul utilizatorului. Scopul este de a reduce timpul de inactivitate a
unităţii centrale, dezlegând funcţionarea acesteia de periferice.
Programul utilizatorului va transfera informaţiile din sau spre bufer, iar buferul va servi, în
mod paralel, drept sursă sau destinaţie la schimbul de date cu perifericul. Pentru a nu
supraîncărca memoria principală, buferul poate fi situat pe discul rigid.

Specificaţii:
• schimburile de informaţii cu perifericele se va face prin înregistrări de lungime fixă,
• zona-tampon este de volum fix egal cu N înregistrări,
• pentru un program utilizator, schimbul de informaţii cu zona-tampon trebuie să
simuleze schimbul cu perifericul - ordinea de depozitare sau de extragere a informaţiilor
trebuie să fie bine stabilită şi nici o înregistrare să nu fie pierdută,
• aşteptările inutile trebuie reduse la minimum,
• capacitatea suporturilor nu este limitată,
• transferul se va efectua fără eroare.

107
01.09.2020 12:47:14
Descrierea algoritmilor
Citire
Procedura citire(înreg) prezintă drept rezultat valoarea înregistrării citite. Realizată printr-o apelare a
supervizorului, are ca efect citirea din bufer a înregistrării următoare. Citirea este posibilă doar dacă
buferul conţine cel puţin o înregistrare, care nu a fost încă citită. În caz contrar, activitatea apelantă trece
în starea de aşteptare. În ambele cazuri, continuitatea alimentării buferului este asigurată de citirea unei
înregistrări de la perifericul de intrare, dacă un transfer nu are deja loc.
Terminarea transferului unei înregistrări în bufer provoacă o întrerupere. Pentru a menţine perifericul în
stare activă, programul de tratare asociat acestei întreruperi trebuie să relanseze transferul următor,
dacă mai există loc în bufer. Dacă activitatea apelantă era în aşteptarea sosirii unei înregistrări, ea
trebuie relansată. programul utilizator
periferic de
intrare citire (înreg)

Zonă-tampon cu N locaţiuni
procedura citire(înreg) tratare întrerupere
(apelare supervizor)
if buferul_nu este_vid then if buferul_nu este_plin then
extragere(înreg, tampon); lansare_transfer;
lansare_transfer în caz de necesitate; if aşteptare then // aşteptare pentru citire
else reluare citire
lansare_transfer în caz de necesitate; endif
108
aşteptare
01.09.2020 12:47:14
endif
Scriere
Schema care corespunde unei scrieri se obţine din precedenta, înlocuind după cum urmează:
citire prin scriere
extragere prin introducere
tampon_vid prin tampon_plin
tampon_plin prin tampon_vid
programul utilizator
periferic de
ieşire scriere (înreg)

Zonă-tampon cu N locaţiuni

procedura scriere(înreg) tratare întrerupere


(apelare supervizor)
if tamponul_nu este_plin then if tamponul_nu este_vid then
introducere(înreg, tampon); lansare_transfer;
lansare_transfer în caz de necesitate; if aşteptare then
else reluare scriere
lansare_transfer în caz de necesitate; endif
aşteptare
endif
01.09.20
20 109
12:47:14
Programe
Zona-tampon: fir de aşteptare, gestionat circular cu ajutorul a doi pointeri:
• tcitire (top-ul FA) - indică următoarea înregistrare care urmează a fi preluată,
• qcitire (coada FA) - indică amplasamentul unde se va introduce următoarea înregistrare.
Funcţia suc realizează înlănţuirea amplasamentelor;

Realizare pentru o zonă-tampon secvenţială cu N înregistrări a câte L amplasamente:


suc(ptr) = (ptr + L) mod (L*N)
Procedurile lansare_citire şi lansare_imprimare realizează pregătirea programului canalului şi
lansarea transferului.
programul utilizator (SVC)
periferic de
citire (înreg)
intrare

Zonă-tampon

qcitire tcitire

Variabile Semnificaţie Valoare iniţială


L lungimea unei casete (înregistrări) const.
Ncitire numărul de casete a zonei-tampon const
nvcitire numărul de casete vide Ncitire
citire_activ indicator al activităţii perifericului de intrare false
tcitire, qcitire pointeri top şi coadă 0, 0
suc() pointer spre caseta următoare …

110
01.09.2020 12:47:14
citire(înreg) tratare_întrerupere_perif_de_intrare
save(zonă_svc); save(zonă_întrerupere);
început: qcitire:=suc(qcitire);
if nvcitire<Ncitire then nvcitire:=nvcitire-1;
înreg:=bufer[tcitire]; if nvcitire>0 then
tcitire:=suc(tcitire); lansare_perif_de_intrare(qcitire)
nvcitire:=nvcitire+1; else
if citire_activ=false then citire_activ:=false
citire_activ:=true; endif;
lansare_perif_de_intrare(qcitire) if aşteptare_citire then
endif întrerupere_veche.act:=activ;
else aşteptare_citire:=false
if citire_activ=false then endif;
citire_activ:=true; restabilire(zonă_întrerupere);
lansare_perif_de_intrare(qcitire) încărcare_csp(întrerupere_veche);
endif; lansare_perif_de_intrare(qcitire)
elaborare prog.canal:
csplucrare:=<aşteptare,slave,demascat, adr început>; <sens=citire
aşteptare_citire:=true; adr.memorie=adr bufer[qcitire]
încărcare_csp(csplucrare); contor_octeţi=L>
endif; SIO
restabilire(zonă_svc); <prog=prog.canal
încărcare_csp(svc_vechi); perif= perif_de_intrare>

01.09.2020 12:47:14 111


Excluderea mutuală
Remarcă. Tratarea întreruperii este declanşată de sfârşitul transferului fizic al unei înregistrări, activitate,
care are loc paralel cu executarea programului primitivei citire(înreg) pe procesor. Drept rezultat, este
posibil ca întreruperea să survină într-un punct oarecare (observabil) al executării acestei primitive, ceea ce
va însemna intercalarea executării programului de tratare a întreruperii între două puncte oarecare ale
programului citire(înreg).

Exemplu. Să considerăm instrucţiunea a doua


if non citire_activ then
citire_activ:=true;
lansare_perif_de_intrare(qcitire)
endif
din programul citire(înreg). Ea se descompune în următoarele instrucţiuni elementare:
a) load R, citire_activ
b) jifz R, urm -- ramificare dacă true
c) …
urm: …
<aşteptare>
Presupunem că întreruperea soseşte între instrucţiunile (a) şi (b), valoarea pusă în R de (a) este true;
programul de tratare a întreruperii pune citire_activ în false. După prelucrarea întreruperii, instrucţiunea (b)
este executată cu R având valoarea true şi activitatea apelantă trece în starea de aşteptare în care rămâne un
timp indefinit.
Putem afirma, că validitatea variabilelor comune (de ex. citire_activ, nvcitire etc.,) nu poate fi garantată dacă
autorizăm sosirea întreruperilor de terminare a operaţiilor de intrare-ieşire în orice moment de timp.
Apelarea supervizorului pentru a realiza secvenţa de cod citire_înreg trebuie executată cu întreruperile de
intrare-ieşire mascate.

Situaţia dată este cunoscută sub numele de excludere mutuală şi este o consecinţă
112a execuţiei activităţilor
asincrone.
01.09.2020 12:47:14
3. Gestiunea activităţilor paralele
3.1. Exemple introductive
3.1.1. Administrarea tamponată a intrărilor-ieşirelor
3.1.2. Comanda unui proces industrial
3.2. Noţiune de proces secvenţial
3.2.1. Proces unic. Context
3.2.2. Relaţii între procese
3.3. Sincronizarea proceselor
3.4. Implementarea sincronizării
3.4.1. Probleme-tip
3.4.2. Administrarea unei resurse partajate
3.4.3. Comunicarea între procese
3.4.4. Administrarea intrărilor-ieşirilor
3.4.5. Sincronizare temporală
3.5. Gestiunea dinamică a proceselor
3.6. Sincronizarea în Windows
3.1.1. Administrarea tamponată a intrărilor-ieşirelor

scriere_linie
SL SD CD IF

tm1 tm2

(memorie) (memorie)
td

(disc)

Fig.3.1. Gestionarea buferizată a unei imprimante

1) primitiva scriere_linie SL (unitatea centrală)


2) scriere pe disc SD (canal 1)
3) citire de pe disc CD (canal 2)
4) imprimare fizică IF (canal 3)

Aceste patru activităţi sunt în mare măsură autonome - ele sunt executate pe
procesoare distincte, cu programe diferite.

Ele nu sunt totuși independente, deoarece accesează obiecte comune: două bufere în
memorie, tm1 şi tm2 şi unul pe disc, td.
114
01.09.2020 12:47:14
1) Condiţii, care stabilesc posibilitatea existenţei activităţilor

O înregistrare nu poate fi preluată din bufer înainte de a fi depozitată aici.


Buferele au capacităţi limitate: dacă un bufer este plin, este imposibilă depozitarea fără
a pierde informaţii.

Activitate Acţiune Condiţie


SL scriere în tm1 tm1 nu este plin
SD citire din tm1 tm1 nu este vid
SD scriere în td td nu este plin
CD citire din td td nu este vid
CD scriere în tm2 tm2 nu este plin
IF citire din tm2 tm2 nu este vid

Execuția activităților modifică veridicitatea acestor condiții: astfel, imprimarea unei linii
pune în TRUE condiția “tm2 nu este plin”.

O activitate, care nu poate executa o acţiune, deoarece condiţia asociată are valoarea
FALSE, trebuie să aştepte până când valoarea logică a condiţiei devine TRUE.
SL SD CD IF

tm1 tm2
(memorie) (memorie)
td
115
01.09.2020 12:47:14
(disc)
2) Condiţii de validitate a informaţiilor partajate
Examinăm procesul de accesare a buferelor. Este posibilită accesarea simultană
de către două activităţi a unuia și același amplsament de memorie.
Exemplu: SD citeşte conţinutul unei înregistrări din tm1 pe care SL este în curs de
a o modifica. Rezultatul citirii riscă să fie incoerent, dacă nu vor fi luate măsuri
speciale de precauţie. Problema poate fi rezolvată impunând una din activităţi,
aflate în conflict, să “aştepte” până când cealaltă va termina accesarea.
Concluzii:
Lucrarea “imprimare buferizată” este realizată prin patru activităţi
simultane, în mare măsură autonome, care cooperează pentru atingerea scopului
final. Executarea corectă a lucrării impune restricţii logice în vederea derulării
acestor activităţi. Aceste restricţii pot conduce la întârzierea execuţiei unei
activităţi, care este obligată să aştepte producerea unui eveniment, provocat de o
altă activitate.

01.09.2020 12:47:14 116


Comanda unui proces industrial
R1 şi R2 funcţionează separat și independent. Vom examina două soluţii posibile:
1) utilizarea a două calculatoare (câte unul pentru fiecare reactor),
2) folosirea unui singur calculator pentru comanda ambelor reactoare.
Implementarea variantei doi impune verificarea posibilităţii apariţiei unor condiţii
suplimentare. Fie P1, P2, D1, D2 segmentele procedurilor şi datelor pentru comanda
celor două reactoare R1 şi R2, memoria principală având capacitatea necesară pentru
păstrarea acestor segmente.
Programele P1 şi P2 sunt executate pe rând de procesor. Funcţionarea reactoarelor pentru un
observator extern pare identică pentru ambele soluţii. Doar că soluţia 2 impune restricţii mai
severe în ceea ce priveşte performanţele calculatorului.
Modalităţile de implementare a soluţiei 2:
1. Partajarea procesorului
2. Partajarea programului
Programele P1 şi P2, fiind identice, putem păstra doar o singură copie, să-i zicem P, pentru
economisirea memoriei. Condiţii!

117
01.09.2020 12:47:14
Exemplul 2: rezumat

1. Avem două activităţi logic independente: comanda reactoarelor R1 şi


R2. Aceste două activităţi pot fi puse pe două maşini distincte fără să
existe vre-o legătură între ele.
2. Considerente de economie pot impune ca aceste activităţi să partajeze
resurse fizice şi resurse program comune. Apar restricții dictate de buna
funcţionare a partajării referitoare la execuţia activităţilor şi modul de
utilizare a obiectelor partajate.

Ca şi concluzie pentru ambele exemple putem evidenţia două momente:


• există activităţi evolutive, care pot derula simultan,
• există relaţii între aceste activităţi: cooperare pentru executarea
unor sarcini comune, concurenţă în utilizarea resurselor partajate.

Continuarea acestui capitol are drept scop elaborarea unui suport formal
pentru aceste noţiuni, introducând conceptele de proces şi sincronizare şi
descriind modalităţile lor de utilizare în cadrul unui sistem informatic.

118
01.09.2020 12:47:14
Proces unic
Executarea unui program se traduce într-o suită de
acţiuni/activități
a1, a2,..., ai,...,
cu început(ai)<sfârşit(ai)

O astfel de suită este numită proces secvenţial sau simplu


proces. Un proces poate fi descris cu ajutorul succesiunii
evenimentelor
început(a1), sfârşit(a1), început(a2), sfârşit(a2),...

Suita de stări datate ale maşinii se numeşte traiectorie


temporală (sau istorie) a procesului.

01.09.2020 12:47:14 119


Contextul procesului
Mulţimea informaţiilor pe care acţiunile unui proces le pot consulta sau
modifica se numeşte contextul procesului.
Contextul unui proces rezultant din executarea unui program conţine:
1. Contextul procesorului (cuvântul de stare şi regiștrii),
2. Un context în memorie (segment procedură, segmente date, stiva de execuţie),
3. O mulţime de atribute ataşate procesului şi care specifică diferite proprietăţi:
a) Nume. Serveşte pentru identificarea procesului (un număr intern atribuit la
crearea procesului) şi permite să se ajungă la reprezentarea contextului său.
b) Prioritate. Prioritatea permite ordonarea pentru alocarea procesorului.
c) Drepturi. Specifică operaţiile care îi sunt permise, în scopul asigurării
protecţiei informaţiei.

Traiectoria temporală a unui proces este definită de şirul stărilor


contextului său.
01.09.2020 12:47:14 120
Relaţii între procese
Vom cerceta execuţia unei mulţimi de procese şi interacţiunea lor reciprocă.
Noţiunile, introduse pot fi extinse pentru o mulţime de procese:
1. traiectoria temporală a unei mulţimi de procese este şirul evenimentelor formate de
începuturile şi sfârşiturile activităţilor rezultante din executarea programelor
proceselor.
2. contextele unor procese diferite pot avea părţi comune. Două procese, contextele
cărora sunt disjuncte, se numesc independente; ele nu pot avea interacţiuni
reciproce. Partea contextului, care aparţine unui singur proces, se numeşte context
privat al procesului dat.
Exemplu. Fie două procese care partajează o procedură reentrantă. Segmentul
executabil, care conţine această procedură aparţine contextului comun.
Segmentul de date şi stiva fiecărui proces formează contextul lor privat. ◄

01.09.2020 12:47:14 121


Mulţimi de procese. Paralelism
Să considerăm două programe distincte P şi Q, fiecare având în memorie un segment
cod şi un segment de date. Numim p şi q procesele rezultante din executarea respectivă
a acestor două programe. Executarea setului (p, q) poate să se producă în diferite
moduri, caracterizate de forma particulară a traiectoriei sale temporale (fig. 3.2).

p q
(1)

p q p q p q
(2)

p q
(3)

Fig. 3.2. Executarea unei mulţimi de procese


Comment:
• schema 1: este executat mai întâi tot procesul p, apoi procesul q la fel în întregime,
• schema 2: sunt executate şiruri de instrucţiuni ale procesului p în mod alternativ cu şiruri de
instrucţiuni ale procesului q, şi tot aşa până la terminarea ambelor procese,
• schema 3: executarea proceselor p şi q este simultană; în acest caz sunt necesare două procesoare.

01.09.2020 12:47:14 122


Nivelul de observare cel mai fin (cel al instrucţiunilor) este numit nivel de bază.

Nivelul programelor. Să ne situăm mai întâi la nivelul de observare la care, prin convenţie,
executarea completă a fiecărui dintre programele P şi Q reprezintă o acţiune unică:
a) schema de tip 1 este a unei execuţii secvenţiale a lui p şi q. Ea este caracterizată de relaţiile:
sfârşit(q) < început(p) sau sfârşit(p) < început(q)
b) schemele de tip 2 sau 3 sunt scheme de execuţie paralelă. Ele sunt caracterizate de
sfârşit(p) > început(q) sau sfârşit(q) > început(p).

Nivelul de bază. La acest nivel este posibilă o distincţie între schemele 2 şi 3. Într-adevăr, în
schema 2, din considerente de existenţă a unui singur procesor, la un moment de timp dat
doar o singură activitate poate fi executată, contrar schemei 3. Se va spune că în schema 3
are loc un paralelism real, iar în schema 2 – un pseudo-paralelism. Paralelismul real necesită
două procesoare distincte. Două observaţii importante sunt necesare:
1) Diferenţa acestor scheme de execuţie este legată de alegerea nivelului de observare.
Astfel, la nivelul de bază, diferenţa dintre schemele 1 şi 2 dispare: ambele sunt
secvenţiale.
2) Alegerea nivelului de bază depinde de fineţea fenomenelor, care dorim să le
considerăm elementare. Dacă trebuie să studiem executarea instrucţiunilor în “pipe-
line” pe un procesor microprogramat, în calitate de nivel de bază va fi ales nivelul
microinstrucţiunilor, iar contextul va fi completat cu memoria microprogramelor şi
registrele interne.

01.09.2020 12:47:14 123


Concurenţa proceselor. Resurse virtuale

Situaţia descrisă de schemele 1 şi 2 nu rezultă dintr-o legătură logică între p şi q, ci doar din
existenţa unui singur procesor. Ea poate fi generalizată astfel:
fie o mulţime de procese contextele cărora au un obiect comun, care poate fi utilizat la un moment de
timp dat de un singur proces. Se va spune în acest caz, că obiectul constituie o resursă critică
pentru procesele date sau că procesele sunt în excludere mutuală (excludere reciprocă sau concurenţă)
pentru utilizarea unei resurse.

Excluderea mutuală a unei resurse conduce la “serializarea” execuţiei proceselor concurente,


în cazul unor acţiuni, care cer această resursă. Schemele 1 şi 2 diferă doar prin nivelul de
fineţe la care este executată serializarea.

Funcţionarea corectă a unei mulţimi de procese, care participă la îndeplinirea unei lucrări
comune, implică relaţii logice de cooperare. Este comod să se separe această cooperare de
concurenţa pentru resursele fizice cu scopul de a simplifica înţelegerea şi aplicarea celor
două tipuri de relaţii. Pentru aceasta este folosită noţiunea de resurse virtuale:
fiecărei resurse fizice critice i se asociază tot atâtea copii imaginare (sau virtuale) ale acestei resurse
câte procese concurente solicită utilizarea ei. Trebuie să tratăm două probleme distincte:
1) respectarea relaţiilor de cooperare între procesele, care, fiecare posedă (conceptual)
resursele fizice solicitate şi pentru care paralelismul în execuţie nu este restricţionat de
competiţia pentru resurse,
2) reglarea problemei de concurenţă pentru resursele fizice printr-o serializare convenabilă a
01.09.20
execuţiei proceselor. Se va spune în acest caz, că realizăm 20 o alocare
124 a resurselor fizice.
12:47:14
Conceptual, totul va avea loc ca şi cum procesele s-ar derula paralel, conform unei scheme,
numite logice sau virtuale, analogice schemei 3 din fig.3.2. Cu toate acestea, trebuie de
menţionat, că această schemă logică reprezintă doar o notaţie compactă pentru mulţimea
schemelor reale posibile şi că ele sunt obligatoriu de forma 1 sau 2 din considerentele
unicităţii procesorului. Pentru o schemă reală şi una virtuală a unui proces dat este păstrată
doar ordinea de succesiune a evenimentelor (începutul şi sfârşitul activităţii) şi nu sunt
păstrate valorile absolute ale intervalelor de timp, care le separă.
Timpul folosit la reperarea evenimentelor în schema logică este numit timp logic.
a1 a2
+------+-----------------+------+ procesul p
b1 b2 (timp logic)
+--+-------+---------+ procesul q

a1 a2
+------+---+ +----------+ +----+------+ p (timp real, execuţia 1)
+--+--+ +-----+---------+ q
b1 b2

a1 a2
+---+ +---+-----------------+------+ p (timp real, execuţia 2)
+--+----+ +---+---------+ q
b1 b2
În toate cazurile a1 precede a2, b1 precede b2. 01.09.20
20 125
Fig.3.3. Timpul logic şi timpul12:47:14
real
Excluderea mutuală
Exemplu 3.3. Două procese p şi q trebuie fiecare să actualizeze valoarea unei variabile
comune n (de exemplu, n este starea unui cont bancar pentru care p şi q
efectuează o depozitare) :
procesul p: Ap : n=n+np procesul q: Aq : n=n+nq
Să realizăm decompoziţia acestor acţiuni în instrucţii, notând prin Rp şi Rq registrele
locale ale proceselor p şi q respectiv:
procesul p procesul q
1. load Rp, n 1’. load Rq, n
2. add Rp, np 2’. add Rq, nq
3. sto Rp, n 3’. sto Rq, n
Dacă aceste acţiuni sunt executate în ordinea 1, 1’, 2, 2’, 3, 3’, efectul lor global este de
executat n:=n+nq şi nu n:=n+np+nq: una din actualizări a fost pierdută şi valoarea
finală a variabilei n este incorectă. Pentru evitarea acestei incoerenţe acţiunile Ap şi Aq
trebuie să fie executate în excludere reciprocă; se zice de asemenea că ele constituie
pentru p şi q secţiuni critice.
Este necesar să se respecte condiţia
sfârşit(Ap) < început(Aq) sau sfârşit(Aq) < început(Ap).
Această condiţie de serializare, care are efectul de a face Ap şi Aq să devină atomare,
este identică condiţiei deja întâlnite la accesarea unei resurse fizice critice. ◄
Excluderea mutuală constă în extinderea pentru secvenţa de acţiuni a proprietăţii de
indivizibilitate a acţiunilor nivelului de bază (acţiuni atomare). Posibilitatea executării
unor acţiuni atomare se află la baza mecanismelor care 01.09.20
realizează
20
sincronizarea.
126
12:47:14
Sincronizarea proceselor
Exprimarea şi implementarea restricţiilor de succesiune
Exemplul 3.4. Procesul p transmite informaţii procesului q scriind într-un segment a,
consultat de q (această transmitere are loc o singură dată). Este necesar să se
îndeplinească condiţia: sfârşit(scriere(a)) < început(citire(a))
Această relaţie exprimă restricţia, că citirea lui a de către q nu poate începe înainte de
terminarea scrierii lui a de către p. ◄
Exemplul 3.5. Rendez-vous. Fie N procese p1,..., pN. Definim în programul fiecărui proces un
punct, numit rendez-vous, pe care procesul nu-l poate trece înainte ca alte procese să
ajungă la punctul lor propriu de rendez-vous.
Dacă programul procesului pi are forma
<debut_i>;
<rendez-vous>
<continuare_i>;
atunci restricţiile de sincronizare se vor exprima după cum urmează:
pentru orice i, j din [1..N]: sfârşit(debut_i) < început(continuare_j) ◄
Restricţiile de sincronizare pot fi exprimate prin următoarele două forme echivalente:
1. Se va impune o ordine de succesiune în timp logic pentru unele puncte ale traiectoriei
temporale ale procesului,
2. Se va impune unor procese o condiţie de autorizare a depăşirii acestor puncte ale
traiectoriei lor temporale.
Punctele privilegiate astfel se vor numi puncte de sincronizare. 127
01.09.2020 12:47:14
Vom utiliza noţiunea de aşteptare pentru specificarea sincronizării proceselor. Această
specificare se va produce în două etape:
 definirea punctelor de sincronizare pentru fiecare proces,
 asocierea unei condiţii de depăşire fiecărui punct de sincronizare, condiţie exprimată
prin intermediul variabilelor de stare ale sistemului.
Vom ilustra acest mod de specificare pentru cele două exemple precedente. Notăm un
punct de sincronizare prin ps, iar condiţia de depăşire asociată prin aut(ps). Dacă această
condiţie are valoare TRUE, procesul în cauză este autorizat să execute instrucţiunea
etichetată cu ps.
Exemplul 3.6: var f : boolean init false
procesul p procesul q
scriere(a); <debut_q>;
f:=true;
<continuare_p> ps : citire(a)
aut(ps) : f:=true
A fost introdusă variabila de stare f pentru a exprima condiţia “procesul p a terminat
acţiunea scriere(a)”.◄
Exemplul 3.7: var n : integer init 0;
procesul pi
<debut_i>;
n:=n+1
ps: <continuare_i>
aut(psi): n=N (i=1,...,N);
Variabila de stare n este în acest caz numărul procesului sosit în punctul de rendez-vous.◄
01.09.2020 12:47:14 128
Probleme de realizare a sincronizării
Vom încerca să implementăm sincronizarea specificată de condiţiile de depăşire. Pentru
aceasta trebuie să definim un mecanism de aşteptare şi să introducem noţiunea de
variabilă de blocare (mutex). O variabilă de blocare (e) este o
variabilă, care poate lua două valori: liber sau ocupat, valoarea iniţială este
ocupat. Asupra v.b. sunt posibile două operaţii, care sunt acţiuni indivizibile:
e:=<valoare> -- atribuirea imediată a unei valori
aşteptare(e).
Operaţia aşteptare(e), executată de un proces p, are următoarea specificaţie:
if e = ocupat then
starea(p) := blocat -- p este trecut în “aşteptarea lui e”
endif
Când e ia valoarea liber, toate procesele care aşteptau e trec în starea activ.
Vom încerca acum să realizăm cu ajutorul acestui mecanism sincronizarea pentru cele
două exemple.
Exemplul 3.8. var e : variabilă de blocare;
procesul p procesul q
scriere(a); <debut_q>;
e:=liber; aşteptare(e);
<continuare_p> citire(a) ◄
Analiza acestui sistem (care nu conţine alte variabile de stare, decât v.b. e) poate fi
făcută enumerând traiectoriile temporale posibile. Această analiză arată, că
sincronizarea este corectă atunci când operaţiile asupra v.b. sunt indivizibile.
01.09.2020 12:47:14 129
Exemplul 3.9. var e : v.b.;
n : integer init 0;
procesul pi
<debut i>;
A n:=n+1;
B if n<N then
aşteptare(e)
else
e:=liber
endif
<continuare i> ◄
O analiză mai atentă ne arată că acest program este incorect. Notând un registru local al
procesului i prin Ri, acţiunile (A) şi (B) pot fi descompuse după cum urmează:
load Ri, n
ai Ri, 1 -- adunare imediată
ci Ri, N -- comparare imediată
br () etichetă -- salt dacă Ri  N
<aşteptare (e)>
...
etichetă : ...
Presupunem, că toate procesele sunt în aşteptarea punctelor lor de rendez-vous, cu excepţia
a două, notate prin pj şi pk. Dacă pj şi pk vor fi executate pe traiectoria temporală (1j, 1k,
2j,...), atunci fiecare va atribui lui n valoarea finală N-1 şi se va bloca, drept rezultat toate
procesele se vor bloca pentru un timp indefinit.
01.09.2020 12:47:14 130
Monitorul – mecanism de sincronizare
Un monitor este constituit dintr-o mulţime de variabile de stare şi o mulţime de
proceduri, care utilizează aceste variabile. Unele dintre aceste proceduri, numite
externe, sunt accesibile utilizatorilor monitorului; numele acestor proceduri sunt
numite puncte de intrare ale monitorului. Procesele, care utilizează monitorul
pentru a se sincroniza, nu au acces direct la variabilele de stare.
Monitorul poate fi utilizat doar prin apelarea procedurilor sale externe; acestea
realizează blocarea sau deblocarea proceselor conform specificaţiilor problemei.
Condiţiile de blocare sau deblocare sunt exprimate ca funcţie ale variabilelor de
stare, iar mecanismul de execuţie a monitorului garantează manipularea acestor
variabile în regim de excludere mutuală.
Monitorul conţine un fragment de cod de iniţializare, executat o singură dată la
crearea monitorului.

01.09.20
20 131
12:47:14
Condiții de monitor
Blocarea şi deblocarea proceselor se exprimă, în procedurile monitorului, prin
intermediul unui tip de date numit condiţie.
O condiţie este declarată ca şi o variabilă, dar nu are “valoare”: o condiţie c poate fi
utilizată doar prin intermediul a trei operaţii sau primitive, efectul cărora este descris
mai jos (prin p am notat procesul, care le execută)
c.aşteptare : blochează procesul p şi îl plasează în “aşteptarea lui c”
c.vid : fn bool (true, dacă nu există nici un proces în aşteptarea lui c, altfel false)
c.semnalizare : if non c.vid then <deblocarea proceselor în aşteptarea lui c> endif
Procesele, care sunt în aşteptarea unei condiţii c, sunt grupate într-un fir de aşteptare
asociat lui c. Putem spune, că o condiţie furnizează proceselor un instrument de
desemnare a unui astfel fir de aşteptare.
Un proces deblocat de c.semnalizare îşi reia execuţia de la instrucţiunea, care
urmează imediat primitivei c.aşteptare, care-l blocase.

01.09.20
20 132
12:47:14
Exemplul 3.10. sinc: monitor;
var f: boolean;
term: condiţie;
procedura terminare_scriere;
begin
f:=true;
term.semnalizare
end
procedura debut_citire;
if f=false then
term.aşteptare
endif
begin -- iniţializare
f := false
end
end sinc

Monitorul este utilizat după cum urmează:


procesul p procesul q
scriere(a); <debut_q>
sinc.terminare_scriere; sinc.debut_citire;
<continuare_p> citire(a);
01.09.2020 12:47:14 133
Exemplul 3.11.
rendez-vous : monitor;
var n : integer;
toţi_sosiţi : condiţie;
procedura sosire;
begin
n := n+1;
if n < N then
toţi_sosiţi.aşteptare --nu au sosit toate procesele
else
toţi_sosiţi.semnalizare -- a sosit şi ultimul
endif

begin -- iniţializare
n:=0
end
end rendez_vous

Programul procesului pi va fi de forma:


procesul pi
<debut i>
rendez_vous.sosire;
<continuare i> 01.09.20
20 134
12:47:14
Implementarea sincronizării
Probleme-tip
Problemele de sincronizare logică pot fi reduse la combinaţia unui număr mic de
situaţii elementare, schemele de soluţionare ale cărora sunt cunoscute.
Problemele-tip sunt următoarele:
• accesarea de către o mulţime de procese a unei resurse partajate comune,
• comunicarea între procese,
• gestionarea perifericelor şi intrărilor-ieşirilor buferizate,
• sincronizarea temporală.

01.09.20
20 135
12:47:14
Administrarea unei resurse partajate
Considerăm o resursă (fizică sau logică) partajată de o mulţime de procese. Utilizarea
acestei resurse trebuie să respecte nişte reguli de utilizare, destinaţia cărora constă în
garantarea unor proprietăţi specificate sau restricţii de integritate. Aceste restricţii sunt
specificate pentru fiecare resursă.

O modalitate de garantare a respectării regulilor de utilizare a unei resurse constă în


adoptarea următoarei scheme:
modul de folosire a resursei presupune utilizarea obligatorie a procedurilor de
acces asociate resursei; orice tentativă de utilizare, care nu respectă acest mod
este detectată automat,
procedurile de accesare sunt grupate într-un monitor, sau mai multe, programul
căruia impune respectarea restricţiilor de integritate.

Cel mai simplu caz este acela al unei resurse pentru care singura restricţie de
integritate este de a fi utilizată în excludere reciprocă. Simpla grupare a procedurilor
sale de acces într-un monitor unic garantează respectarea acestor restricţii.

01.09.20
20 136
12:47:14
Alocarea resurselor banalizate
Considerăm o resursă pentru care există un număr fix de N exemplare. Un proces poate
accesa la cerere n unităţi din cele N, le poate utiliza şi apoi elibera. Toate unităţile sunt
echivalente din punctul de vedere al proceselor utilizatoare (banalizate).
Utilizarea resursei are loc conform schemei de mai jos.
ps:resurse.cerere(n); -- cerere pentru n unităţi
-- aşteptare în caz de eşec
<utilizarea unităţilor primite>
resurse.eliberare(n) -- eliberarea resurselor
Condiţia de sincronizare se va scrie pentru orice proces:
aut(ps) : n  nlibere
Monitorul resurse va utiliza direct condiţia de sincronizare:
resurse: monitor;
var nlibere : integer;
disp : condiţie;
procedura cerere(n); procedura eliberare(n);
begin begin
while n>nlibere do nlibere:=nlibere+n;
disp.aşteptare; disp.semnalizare -- deblocare în lanţ
endwhile; end;
nlibere:=nlibere-n
end;
begin -- iniţializare
nlibere:=N 01.09.20
20
end 12:47:14
137
end resurse
resurse : monitor
type element : struct
lungime : integer
proc : proces
end;
var nlibere : integer;
disp : array[proces] of condiţie;
<declaraţia f.de aşt. f şi procedurilor sale de accesare: introducere, extragere, primul>
procedura cerere(n);
begin
var e: element;
if n>nlibere then
e.lungime:=n;
e.proc:=p; -- p este procesul apelant
introducere(e,f); -- în ordinea de creştere a lungimii
disp[p].aşteptare
endif;
nlibere:=nlibere-n
end;
procedura eliberare(n);
var e: element;
begin
nlibere:=nlibere+n;
while primul(f).lungime  nlibere do
extragere(e,f); -- elementul extras = primul (f)
disp[e.proc].semnalizare -- e.proc = procesul deblocat
endwhile;
end;
begin -- iniţializare
01.09.20
nlibere:=N; 20
f:=<vid>
138
12:47:14
end
end resurse
Modelul cititorului şi scriitorului
Să considerăm un fişier manipulat de procese din două clase diferite: cititori, care
consultă fişierul fără a modifica conţinutul lui şi scriitori, care pot modifica acest
conţinut. Fie pentru un moment arbitrar de timp ncit şi nscr numărul de cititori şi de
scriitori, respectiv, care folosesc o procedură de acces la fişier. Cererea de
asigurare a coerenţei fişierului ne impune să respectăm următoarele restricţii:
(nscr=0) şi (ncit0) -- fişier în citire
sau (nscr =1) şi (ncit=0) -- fişier în scriere

Fie fich un monitor care asigură respectarea acestor restricţii. Vom impune următoarea
formă a acceselor la fişier:
proces cititor proces scriitor
fich.debut_citire; fich.debut_scriere;
<acces citire> <acces scriere>
fich.terminare_citire; fich.terminare_scriere;

Procedurile debut_citire, terminare_citire, debut_scriere, terminare_scriere trebuie să


asigure respectarea restricţiilor de mai sus.
Presupunem că cititorii au prioritate în faţa scriitorilor (o scriere nu va fi autorizată,
dacă există cititori în aşteptare). Definim următoarele variabile de stare:
scr = o scriere este în curs (valoare booleană)
nc = numărul de cititori în aşteptare sau în curs de citire

Condiţiile de depăşire se vor exprima după cum urmează:


01.09.20
aut(citire) : scr=false (nu există scrieri curente) 20 139
aut(scriere): scr=false şi nc=0 (nici scrieri nici citiri în curs, nici cititori în aşteptare)
12:47:14
fich : monitor;
var scr : boolean;
nc : integer;
c_scr, c_cit : condiţie;

procedura debut_citire;
begin
nc:=nc+1;
if scr then procedura terminare_scriere;
c_cit.aşteptare; begin
endif scr:=false;
end if nc>0 then -- prioritate
cititorilor care aşteaptă
procedura terminare_citire;
c_cit.semnalizare
begin
nc:=nc-1; else
if nc=0 then -- ultimul cititor a terminat c_scr.semnalizare
c_scr.semnalizare endif
endif end
end
begin -- iniţializare
procedura debut_scriere;
begin scr:=false;
if scr or nc>0 then -- scriere sau citire în curs nc:=0
c_scr.aşteptare end
endif; end fich
scr:=true 01.09.20
20 140
end 12:47:14
Comunicarea între procese
Procesele pot comunica prin accesarea unei mulţimi de variabile comune. Acest mod de
comunicare este slab structurat şi ineficient - cere excluderea reciprocă a variabilelor.
Comunicarea prin mesaje - modelul producătorului şi consumatorului, realizată cu
ajutorul monitoarelor (3.4.3.1). O altă posibilitate, descrisă în 3.4.3.2, constă în a
considera operaţiile de comunicare ca un fel de mecanisme primitive de sincronizare. În
3.4.3.3 prezentăm o aplicaţie frecventă de comunicare – modelul client-server.
3.4.3.1. Modelul producătorului şi consumatorului
Un proces (producătorul) trimite mesaje unui alt proces (consumatorul), utilizând o zonă
tampon în memoria comună. Mesajele sunt de lungime fixă şi capacitatea tamponului
este de N mesaje.
Specificaţiile comunicaţiei:
• un mesaj dat poate fi preluat doar o singură dată după ce a fost depozitat în tampon,
• un mesaj nu poate fi pierdut;
• dacă tamponul conţine N mesaje nepreluate, nu pot fi depozitate alte mesaje,
• o operaţie “imposibilă” blochează procesul, care încearcă să o execute.

Condiţiile de depăşire (n numărul de mesaje din tampon, care nu au fost încă preluate):
aut(depozitare) :n<N -- tamponul nu este plin
aut(preluare) : n > 0 -- tamponul nu este vid

Respectarea acestor restricţii este asigurată de un monitor tampon, utilizat astfel:


proces producător proces consumator
... ... 01.09.20
produce(mesaj); bufer.preluare(mesaj);
20
12:47:14
141
bufer.depozitare(mesaj); consumare(mesaj);
bufer : monitor; Procedurile introducere(m) şi extragere(m) definesc
var n : 0..N; politica de gestionare a buferului şi
non_plin, non_vid : condiţie; reprezentarea internă a mesajelor.
<declaraţii ale procedurilor introducere şi
extragere> type mesaj : <descrierea formatului mesajelor>
procedura depozitare(m:mesaj); pt : 0..N-1;
begin var fa : array[pt] of mesaj;
if n=N then top, coadă: ptr;
non_plin.aşteptare procedura introducere(m:mesaj);
endif; begin
n:=n+1; fa[coadă]:=m;
introducere(m); coadă:=coadă+1 mod N
non_vid.semnalizare end;
end procedura extragere(var m:mesaj);
procedura preluare(var m:mesaj); begin
begin m:= fa[top];
if n=0 then top:=top+1 mod N
non_vid.aşteptare end;
endif; <iniţializarea se va completa cu top:=0; coadă:=0;>
extragere(m);
n:=n-1; Schema poate fi extinsă pentru mai mulţi producători
non_plin.semnalizare şi consumatori.
end;
begin -- iniţializare
n:=0; 01.09.2020 12:47:14 142
end
end bufer
Exemplul 3.12. Sistemul de operare Thoth [8]. Comunicarea foloseşte desemnarea directă şi
sincronizarea prin rendez-vous. Mesajele - lungime constantă. Sunt utilizate patru primitive:
id:=send(message, id_dest)
emite procesului id_dest un mesaj; blochează emiţătorul până la primirea unui răspuns, transmis
în message. Primitiva indică identitatea procesului care a transmis răspunsul (nil, dacă
destinatarul nu există).
id:=receive(message, id_orig)
recepţionează un mesaj; procesul origine poate să nu fie specificat. Valoarea transmisă este
identitatea emiţătorului.
reply(message, id_orig, id_dest)
trimite un răspuns destinatarului specificat (care trebuie să-l aştepte); nu este blocantă; fără
consecinţe, dacă răspunsul nu era aşteptat.
forward(message, id_orig, id_dest)
această operaţie non blocantă este utilizată de un proces după recepţionarea unui mesaj trimis de
către id_orig, pentru ca să impună mesajul să ajungă la id_dest, care are acum obligaţia de a
răspunde lui id_orig. ◄

Exemplul 3.13. Sistemul de operare Unix [9]. În sistemul Unix comunicarea între procese
utilizează zone-tampon, numite pipes (tuburi), administrate conform schemei producător-
consumator. Mesajele transmise sunt caractere. Un pipe (tub) leagă un emiţător şi un
receptor, conexiunea fiind stabilită dinamic. ◄

Exemplul 3.14. Limbajul Ada permite definirea proceselor. Forma sintactică a comunicărilor între
procese este apelarea procedurii, însă transmiterea parametrilor şi a rezultatelor are loc
conform principiului de transmitere a mesajelor cu rendez-vous. Recepţionarea
143 poate fi
condiţionată (un apel este acceptat doar dacă o condiţie specificată este satisfăcută). ◄
01.09.2020 12:47:14
3.4.3.3. Client-server

O aplicaţie curentă a comunicărilor între procese este relaţia client-server. Un proces server
are în şarjă îndeplinirea unor servicii (executarea unor programe predefinite)
proceselor client. Pentru aceasta este utilizată următoarea schemă:

procesul server procesul client


ciclu poartă_serviciu.emitere(cerere)
poartă_serviciu.recepţionare(cerere)
<executare serviciu> ...
[poartă_client.emitere(rezultat)] ...
endciclu [poartă_client.recepţionarere(rezultat)]

Procesul server este asociat unei porţi, unde clienţii îşi depun cererile; el este blocat atâta
timp cât nu există cereri de servicii în aşteptare.

Serviciul cerut poate conţine trimiterea la client a rezultatului. În acest caz clientul trebuie
să trimită serverului în cererea sa numărul unei porţi la care el se va bloca în aşteptarea
rezultatului.

Modelul din 3.4.2.1 (alocarea resurselor banalizate) şi modelul client-server sunt


reprezentative pentru două scheme de obţinere a unui serviciu cu ajutorul proceselor într-un
sistem de operare: apelarea unei procedure de monitor sau activarea unui proces server
ciclic prin emiterea mesajelor. Alegerea între aceste două scheme este dictată de
01.09.20
considerente de eficacitate (schema serverului este preferată, 20 atunci 144
când există paralelism
real între client şi server) sau de uniformitate a structurii.
12:47:14
Administrarea unui periferic Fiecărui periferic îi este asociat un monitor procedurile externe
ale căruia permit executarea intrărilor-ieşirilor la acest periferic. Forma generală:
perif: monitor;
var ..., sfr_schimb_i,...: condiţie;
<declaraţiile variabilelor de stare ale perifericului>
...
procedura schimb_i(<parametri>);
begin
<mascarea întreruperilor>;
if starea ≠ preg then
<tratare eroare(perifericul nu este gata)>
endif;
lansare_transfer_i(parametri);
sfr_schimb_i.aşteptare; -- întrerupere demascată
if starea ≠ ok then -- în timpul aşteptării
<tratare eroare(incident de transfer)>
endif;
<demascare întreruperi>
end;
...
begin
<iniţializare>
end
end perif
Procedura lansare_transfer_i pregăteşte programul pentru schimbul cerut (construirea programului canalului,
ţinând cont de parametrii schimbului) şi lansează execuţia sa (instrucţiunea SIO). Procesele apelante aşteaptă
sfârşitul transferului datorită condiţiei sfr_schimb_i. Sosirea unei întreruperi, care marchează sfârşitul
schimbului de tip i provoacă în mod automat executarea următoarei 01.09.20
secvenţe:
20 145
if sfr_schimb_i.vid then <tratarea eroare întrerupere care nu este aşteptată>
12:47:14
else sfr_schimb_i.semnalizare
endif
Sincronizarea temporală

Sincronizarea temporală face ca timpul să intervină nu numai


ca mijloc de ordonare a evenimentelor, dar şi ca măsură de
durată absolută. Acest mod de sincronizare este utilizat în
aplicaţiile de timp real, care conţin interacţiuni cu organe
externe (comanda proceselor industriale, de exemplu).

Sincronizarea temporală solicită folosirea unui ceas, realizat


prin intermediul generatorului de sincronizare, care emite
impulsuri la intervale regulate. Aceste impulsuri pot fi
utilizate pentru a declanşa o întrerupere
• la fiecare impuls sau
• pentru a decrementa în mod automat conţinutul unui
registru contor, o întrerupere este declanşată atunci
când conţinutul acestui registru atinge valoarea 0.
01.09.20
20 146
12:47:14
Gestionarea dinamică a proceselor

În sistemele cele mai simple procesele sunt în număr constant şi create odată pentru
totdeauna la generarea sistemului de operare. În sistemele performante, mai ales în cele
interactive, procesele sunt comandate dinamic. Astfel, în Multics, un proces nou este creat
odată cu admiterea unui nou utilizator; în Unix, la executarea fiecărei comenzi.
Primitivele de creare şi distrugere a proceselor pot fi puse în şarja sistemului de operare sau
la dispoziţia utilizatorilor. Crearea unui proces presupune alocarea resurselor şi iniţializarea
contextului. Distrugerea unui proces eliberează toate resursele care i-au fost alocate.
Primele primitive, propuse pentru gestionarea dinamică a proceselor, au fost fork şi join.
Istoric şi cronologic, aceste operaţii au fost introduse pentru organizarea executării paralele a
programelor pe un sistem multiprocesoral, noţiunea de proces nefiind încă clară.

Fie P o procedură. Instrucţiunea


id := fork(p),
executată de procesul p (părinte), creează un proces nou q (fiul), care va fi executat paralel cu
p. Primitiva fork prezintă ca rezultat identificatorul lui q (sau nil, dacă imposibilă). Contextul
iniţial al lui q este o copie a lui p, nu și contorul ordinal, care este fixat la prima instrucţiune a
lui p. Procesul fiu se termină cu o primitivă, numită exit sau quit, care provoacă dispariţia sa.
După ce fork crează un proces fiu q, primitiva join q permite procesului părinte să fixeze un
punct de rendez-vous cu acest fiu. Executarea lui join q blochează procesul părinte până când
q nu va executa exit. Primitivele fork şi join au avantajele şi dezavantajele instrucţiunii go to
din programarea secvenţială. 01.09.20
20 147
12:47:14
4. Administrarea proceselor
4.1. Realizarea excluderii mutuale
4.1.1. Specificarea problemei
4.1.2. Excluderea mutuală prin aşteptare activă
4.1.3. Semaforul – instrument elementar pentru excluderea mutuală

4.2. Funcţionarea şi structura unui nucleu de sincronizare


4.2.1. Stările unui proces. Fire de aşteptare
4.2.2. Administrarea contextelor şi schemele primitivelor

4.3. Realizarea unui nucleu de sincronizare


4.3.1. Organizarea generală
4.3.2. Realizarea monitoarelor
4.3.3. Operaţii asupra proceselor
4.3.4. Excluderea mutuală şi alocarea procesorului

4.4. Procese şi fire în Linux


4.4.1. Crearea proceselor
4.4.2. Distrugerea proceselor
4.4.3. Daemoni în Linux
4.4.4. Obţinerea informaţiilor despre procese 148
01.09.2020 12:47:14
Acest capitol este consacrat implementării noţiunilor proces
şi sincronizare în cadrul unui sistem de operare.

Mecanismele utilizate sunt bazate pe realizarea principiul


excluderii mutuale, studiat în 4.1.

Principiile directoare ale reprezentării şi gestiunii proceselor


(contexte, alocarea procesorului) sunt prezentate în 4.2 şi
ilustrate în 4.3 printr-un exemplu schematic de realizare a
unui nucleu de sincronizare.

01.09.20
20 149
12:47:14
4.1. Realizarea excluderii mutuale

Mecanismele care realizează excluderea mutuală pentru un


set de programe sunt bazate pe un principiu comun:
utilizarea mecanismului de excludere mutuală existent
deja la un nivel inferior. Drept rezultat, sunt utilizate
variabile comune ale proceselor concurente, iar coerenţa
acestor variabile trebuie ea însăşi să fie garantată.

La nivelul de bază (cel al resurselor fizice) există două


mecanisme elementare: excluderea mutuală la accesarea
unui amplasament de memorie şi masca întreruperilor.
Aceste două mecanisme sunt, în principiu, suficiente
pentru toate necesităţile. Dar, din considerente de
eficacitate, la nivelul resurselor fizice sau
microprogramelor există dispozitive 01.09.20mai sofisticate, cum
20 150
ar fi instrucţiunea Test and Set sau semafoarele.
12:47:14
4.1.1. Specificarea problemei

Fie {p1, p2,...,pn} o mulţime de procese pe care le vom considera ciclice; programul fiecărui
proces conţine o secţiune critică. Excluderea mutuală este asigurată prin două fragmente de
program (prolog şi epilog), care încadrează secţiunea critică a fiecărui proces. Soluţia
trebuie să posede următoarele proprietăţi:
• excludere mutuală: la fiecare moment de timp cel mult un proces execută secţiunea critică,
• absenţa blocajelor intempestive (care nu sunt la timpul lor): dacă în secţiunea critică nu se
află vreun proces, nici un proces nu trebuie să fie blocat de mecanismul excluderii
mutuale,
• toleranţă la defecte: soluţia trebuie să rămână validă şi în cazul unor defecte în unul sau în
mai multe procese, care se află în afara secţiunii critice,
• absenţa privaţiunilor: un proces, care a cerut intrarea într-o secţiune critică nu trebuie să
aştepte un timp infinit (presupunând, că toate procesele au aceeaşi prioritate),
• simetrie: prologul şi epilogul trebuie să fie identice pentru toate procesele şi independente
de numărul lor.

Vom construi o soluţie de forma:


<iniţializare> -- comună tuturor proceselor
<programul procesului pi>:
ciclu
<prolog> -- intrare în secţiunea critică
<secţiunea critică>
<epilog> -- ieşire din secţiunea critică
01.09.20
<restul programului> 20 151
endciclu 12:47:14

Trebuie să elaborăm fragmentele iniţializare, prolog şi epilog.


4.1.2.2. Aşteptarea activă în sistemele multiprocesorale: Test & Set

Pentru tratarea cu ajutorul aşteptării active a cazului în care mai multe procese
actualizează şi consultă variabile comune, unele maşini au o instrucţiune, care
realizează într-o manieră indivizibilă consultarea şi actualizarea unui amplasament
de memorie. Această instrucţiune, adesea numită Test And Set (tas), este utilizată
în sistemele multiprocesorale (în sistemele monoprocesor mascarea întreruperilor
este suficientă pentru asigurarea excluderii mutuale).

Fie m adresa amplasamentului de memorie considerat, sau lacătul, iar R un registru al


procesorului. Prin convenţie, dacă lacătul este în 0, secţiunea critică este liberă, iar
dacă este 1 – ea este ocupată. Efectul lui Test And Set este descris mai jos (Mp[m]
desemnează amplasamentul de memorie cu adresa m):

tas R, m : <blocare acces la Mp[m]>


R:=Mp[m]
Mp[m]:=1
<eliberare acces la Mp[m]>
Excluderea mutuală prin aşteptare activă poate fi programată cu ajutorul următoarelor
secvenţe:
iniţializare : stz m -- Mp[m]:=0
prolog : tas R, m
br(R≠0) $-1 -- test iterat
01.09.20
epilog : stz m 20 152
12:47:14
4.1.3. Semaforul – instrument elementar pentru excluderea mutuală
4.1.3.1. Definiţii

Un semafor s este constituit prin asocierea unui contor cu valori întregi, notat s.c., şi a unui fir
de aşteptare, notat s.f. La crearea semaforului contorului i se atribuie o valoare iniţială s0
(s0≥0), şi firul de aşteptare s.f. este vid.

Un semafor serveşte la blocarea proceselor aşteptând să se producă un eveniment pentru


deblocarea lor; procesele blocate sunt plasate în s.f. Mai multe procese pot fi sincronizate
prin semafoare, care aparţin părţii comune a contextului lor. Un proces poate fi manipulat
doar cu ajutorul a două operaţii P(s) şi V(s), numite primitive. Valoarea contorului şi
starea firului de aşteptare sunt inaccesibile, chiar şi pentru citire.

Fie p un proces care execută P(s) sau V(s), iar q un proces care se află în firul de aşteptare s.f.
Algoritmul primitivelor este următorul:
P(s): V(s):
s.c.:=s.c.-1; s.c.:=s.c.+1;
if s.c.<0 then if s.c.≤0 then
stare(p):=blocat; extragere(q,s.f.);
introducere(p,s.f.) stare(q):=activ
endif endif

Aceste operaţii sunt executate în excludere mutuală.


01.09.20
20 153
Doar executarea primitivei P poate bloca un proces, acesta12:47:14
va putea
fi deblocat doar de un alt
proces, care a executat primitiva V pe acelaşi semafor. Executarea operaţiei V nu este
blocantă.
4.1.3.2. Proprietăţi

Proprietăţile principale ale sincronizării cu ajutorul semafoarelor pot fi deduse din câteva
relaţii invariante: relaţii verificate iniţial şi care rămân neschimbate după executarea
primitivelor P şi V un număr arbitrar de ori.

Fie, pentru un semafor s:


np(s) – numărul total de execuţii a operaţiei P(s),
nv(s) – numărul total de execuţii a operaţiei V(s).

Are loc relaţia:


s.c. = s0 – np(s) + nv(s) (1)

deoarece valoarea iniţială a lui s.c. este s0, fiecare operaţie P(s) scade din această valoare o
unitate, iar V(s) adaugă 1.

Aceste operaţii, fiind executate în excludere mutuală, nici o modificare nu este pierdută.

Fie nbloc(s) numărul proceselor blocate în s.f. Are loc relaţia:


nbloc(s) = if s.c. ≥ 0 then 0 else –s.c. endif (2)
care poate fi de asemenea scrisă
nbloc(s) = max(0, –s.c.) (21)
01.09.20
20 154
12:47:14
Relaţia (2) poate fi scrisă sub o altă formă, care ne va fi utilă mai departe.

Fie nf(s) numărul de “treceri” de către procese a primitivei P(s), adică suma numărului
de executări a lui P(s) fără blocare şi a numărului de deblocări realizate de către
V(s).

Vom avea în acest caz:


nbloc(s) = np(s) – nf(s).

Introducând această valoare în (21) obţinem:

- nf(s) = max(-np(s), -s.c.-np(s)), sau

nf(s) = min(np(s), s.c.+np(s)).

În fine, utilizând valoarea lui s.c. din (1), avem:

nf(s) = min(np(s), s.c.+nv(s)). (3)

01.09.20
20 155
12:47:14
4.1.3.3. Realizarea excluderii mutuale cu ajutorul semafoarelor

Prezentăm o schemă, care rezolvă problema excluderii mutuale pentru n procese. În


cazul în care nu se fac ipoteze speciale despre gestionarea firului de aşteptare, nu
se garantează lipsa privaţiunilor (blocărilor indefinite).
iniţializare: semafor mutex init 1
prolog : P(mutex)
<secţiunea critică>
epilog : V(mutex)

Să ne convingem, că soluţia prezentată este în conformitate cu specificaţiile din 4.1.1.

Trebuie să verificăm proprietăţile a, b şi c au loc.

Fie nc numărul de procese, care se află în s.c. la un moment concret de timp. Avem:
nc = nf(mutex) – nv(mutex) (4)
Proprietăţile în cauză pot fi verificate aplicând semaforului mutex relaţia (3):
nf(mutex) = min(np(mutex), 1+nv(mutex)) (5)

Excluderea mutuală

Din (5) avem:


nf(mutex) ≤ 1+nv(mutex)
01.09.20
şi, utilizând (4), obţinem nc ≤ 1: excluderea mutuală12:47:14
este 20 asigurată.
156
Absenţa blocajelor

Presupunem, că nici un proces nu se află în secţiunea critică. Vom avea în acest caz nc = 0, sau
nf(mutex) = nv(mutex) sau încă
nf(mutex) ≤ 1+nv(mutex)
Conform relaţiei (5):
nf(mutex) = np(mutex) sau
nbloc(mutex) = 0
Proprietatea b este prezentă, ca şi proprietatea c, deoarece nu s-a făcut nici o ipoteză despre
starea proceselor, dacă ele nu se află în secţiunea lor critică.

1). Secţiuni critice incorporate. Blocaje


Fie două procese p şi q pentru care programul conţine două secţiuni critice, corespunzătoare
utilizării a două resurse critice distincte.
procesul p procesul q
... ...
(1) P(mutex1) (11) P(mutex2)
... ...
(2) P(mutex2) (21) P(mutex1)
... ...
V(mutex2) V(mutex1)
... ...
V(mutex1) V(mutex2) 01.09.20
Dacă traiectoria temporală de execuţie a proceselor p şi q începe20 cu (1, 11, 2, 21), se va ajunge
157
la o situaţie în care ambele procese sunt blocate pentru un timp infinit.
12:47:14
2). Aşteptare infinită în secţiunea critică sau impas

Validitatea soluţiei se bazează pe presupunerea, că toate procesele părăsesc secţiunea critică


în timp finit. Această ipoteză poate fi infirmată dacă secţiunile critice se intersectează.
Alte cauze, care conduc la aşteptare infinită: blocarea, incorectitudini sau ciclări infinite într-
un proces, care se află în secţiunea critică. În cazul unor secţiuni critice globale, realizate
pentru un SO, pot fi propuse următoarele soluţii:
• oricărui proces, care execută o secţiune critică globală, i se atribuie, pe toată durata
acestei execuţii, un statut special, care îi conferă anumite drepturi particulare: prioritate
înaltă, protecţie contra distrugerii, etc.
• un orologiu de gardă este armat la intrarea unui proces în secţiunea critică; dacă procesul
nu părăseşte secţiunea critică după un interval de timp predefinit, sistemul de operare
forţează ieşirea procesului şi eliberează astfel secţiunea critică.

3). Privaţiune
Algoritmul excluderii mutuale garantează intrarea a exact unui proces în secţiunea critică când
secţiunea critică este liberă. Se poate întâmpla ca un proces particular să fie reţinut pentru un
interval de timp nedefinit: acest fenomen se numeşte privaţiune.

Pentru cazul cel mai frecvent, când firele de aşteptare a semafoarelor sunt gestionate conform
ordinii “prim sosit – prim servit” fără prioritate, riscul de privaţiune este eliminat.

01.09.2020 12:47:14 158


4.2. Funcţionarea şi structura unui nucleu de sincronizare

Noţiunea de proces şi operaţiile asociate nu fac, de obicei, parte din setul de bază al
calculatorului. Ele vor fi implementate cu ajutorul unor programe şi/sau microprograme, care
formează nucleul de administrare a proceselor.

În cadrul descrierii unui sistem de operare cu ajutorul maşinilor abstracte ierarhice, nucleul
constituie nivelul cel mai inferior, realizat direct pe maşina fizică. Maşina abstractă, realizată
astfel poate fi numită o maşină a proceselor, care posedă, în afara setului de instrucţiuni de
bază, primitivele care permit crearea, distrugerea şi sincronizarea proceselor. Ca şi orice
maşină abstractă, maşina realizată în acest mod ascunde unele proprietăţi ale maşinii fizice.

Astfel:
• noţiunea de proces ascunde utilizatorilor nucleului mecanismul de alocare a procesoarelor fizice. La un
nivel superior nivelului nucleului chiar şi numărul procesoarelor nu intervine decât doar asupra
performanţelor sistemului şi nici într-un fel asupra structurii sale logice,
• primitivele de sincronizare, realizate de nucleu, ascund mecanismele fizice de comutare a contextului, de
exemplu, cele oferite de întreruperi.

Structura nucleului de sincronizare depinde de specificaţiile maşinii fizice (gestiunea


întreruperilor, structura cuvântului de stare, sistem mono- sau multiprocesoral, etc.) şi de
specificaţiile maşinii abstracte care trebuie realizate, îndeosebi de mecanismul de sincronizare
ales.

Este, totuşi, posibil de evidenţiat câteva caracteristici comune ale acestei structuri, pe care le
vom prezenta înainte de a descrie o realizare concretă. 159
01.09.2020 12:47:14
4.2.1. Stările unui proces
Luarea în consideraţie a alocării fizice a unui procesor ne impune să descompunem starea activă
în două stări noi. Un proces activ se numeşte ales, dacă el este în curs de execuţie pe un
procesor fizic; el se numeşte eligibil dacă nu poate fi executat din cauza lipsei unui
procesor disponibil.

Tranziţiile 3 şi 4 (blocare şi deblocare) sunt tranziţiile “interne”, datorate sincronizării


proceselor. Tranziţiile “tehnologice” 1 şi 2 sunt datorate alocării procesoarelor fizice
proceselor.
Retragere (eng. preemption, fr. réquisition) a procesorului.
Administrarea proceselor face apel la fire de aşteptare. Astfel, fiecărei cauze distincte de blocare
(semafor, condiţie într-un monitor, etc.) i se asociază un fir de aşteptare pentru a stabili o
ordine a proceselor blocate. Mai mult, procesele eligibile sunt menţinute într-un fir special
de aşteptare, gestionarea căruia permite implementarea unei politici de alocare a
procesoarelor fizice. Dacă presupunem, că viitorul proces ales este totdeauna primul din
firul proceselor eligibile, algoritmul de alocare poate fi definit (1)
eligibil ales
(ready) (2) (exe)
cu ajutorul algoritmului de inserare
în firul proceselor eligibile sau

cu ajutorul algoritmului care (4) (3)


determină retragerea procesoarelor fizice.

blocat
01.09.20 (wait)
20 160
12:47:14
Fig.4.1. Stările unui proces
Mulţimea programelor, care realizează aceşti algoritmi se numeşte planificator (eng.
scheduler, fr. ordonnanceur).
Programul, care realizează alegerea propriu-zisă se numeşte dispecer (eng. dispatcher, fr.
distributeur).

Schema generală a firelor de aşteptare ale proceselor este prezentată în fig.4.2.

Deplasarea proceselor între aceste fire corespunde schimbării stării.

planificator

fire de procese blocate

dispecer proces ales


firul proceselor eligibile

Fig.4.2. Fire de aşteptare ale proceselor, administrate de nucleul sistemului de operare

01.09.20
20 161
12:47:15
4.2.2. Administrarea contextelor şi schemele primitivelor
Conţinutul contextului
Operaţia de alocare a procesorului fizic impune păstrarea pentru fiecare proces a unei copii a
contextului. Această copie a contextului descrie starea procesorului pentru procesul
considerat. În acest scop fiecărui proces i se asociază o mulţime de informaţii rezidente în
memorie şi numită vector de stare, bloc de control al procesului sau blocul contextului,
care conţine:
• informaţiile despre starea procesorului, necesare la realocarea lui,
• valorile atributelor procesului (prioritate, drept de acces),
• pointeri la spaţiul de lucru al procesului (segmentele procedură şi date, stiva de execuţie),
• informaţii de gestiune (starea, legăturile de înlănţuire).
Organizarea nucleului
Execuţia programelor nucleului poate fi declanşată în două moduri (fig.4.3):
• prin apelarea unei primitive de administrare a proceselor (creare, distrugere, sincronizare, etc.); aceste
primitive sunt realizate sub formă de apel al supervizorului,
• printr-o întrerupere: programele de tratare a întreruperilor fac parte din nucleu, deoarece întreruperile
sunt traduse în operaţii de sincronizare şi sunt invizibile la nivelurile superioare.

alocare procesor apelare supervizor


proces Programele primitivelor şi cele de tratare a
întreruperilor manipulează blocurile
contextului şi firele proceselor. Pentru
programul
nucleului
asigurarea coerenţei informaţiilor aceste
programe trebuie executate în excludere
mutuală. Executarea unui program al nucleului
periferice,
se termină în toate cazurile prin realocarea
ceasul procesorului sau procesoarelor, adică prin
01.09.20
lansare întreruperi 20
apelarea dispecerului.
162
12:47:15
Fig.4.3. Comunicarea cu un nucleu de sincronizare
Programul unei primitive a nucleului are următoarea schemă generală:

prolog; -- salvarea contextului şi intrarea în secţiunea critică


control; -- verificarea drepturilor şi a parametrilor
<corpul programului> -- manipulează firele proceselor
alocare_procesor; -- programul dispecer şi ieşirea din secţiunea critică

Secvenţa prolog, comună tuturor operaţiilor, salvează contextul procesului, care


execută operaţia, şi asigură intrarea în secţiunea critică. Secvenţa control verifică
drepturile procesului apelant de a executa primitiva şi validitatea parametrilor
transmişi. Detaliile depind de primitivă. Secvenţa alocare_procesor este
programul dispecerului: ea realizează realocarea procesorului şi ieşirea din
secţiunea critică.

Tratarea întreruperilor de către nucleu trebuie să fie coordonată cu mecanismele de


sincronizare alese. De obicei sunt considerate două scheme de bază:

• Asocierea unui concret proces, care tratează o întrerupere. Doar acest proces se va afla în
aşteptarea unei întreruperi anume, existând pentru aceasta o instrucţiune specială.
• Asocierea unei operaţii de deblocare (semnalizare asociată unei condiţii, V la un semafor, etc.)
la o întrerupere.

Problemele de mascare şi de prioritate a întreruperilor sunt tratate asociind priorităţi


proceselor.
01.09.20
20 163
12:47:15
4.3. Realizarea unui nucleu de sincronizare
Vom prezenta în cele ce urmează schema realizării unui nucleu particular de sincronizare.
Descrierea este cu titlu de ilustrare, fiind posibile multe ameliorări atât din punct de vedere
al interfeţei, cât şi în ceea ce priveşte detaliile de realizare.
4.3.1. Organizarea generală
4.3.1.1. Interfeţele
Gestionarea proceselor
Procesele pot fi create şi distruse în mod dinamic şi sunt organizate ierarhic conform relaţiei de
paternitate. Un proces este creat cu ajutorul primitivei:
creare(p, context iniţial, atribute)
Atributele unui proces conţin prioritatea (exprimată printr-un întreg) şi drepturile de a executa
anumite operaţii. Contextul iniţial specifică starea iniţială a cuvântului de stare, a
registrelor procesorului şi a spaţiului de lucru asociat procesului (stiva, date proprii).
Procesul este creat în starea eligibil. Numărul său p (numele) este returnat ca rezultat (valoarea
nil, dacă crearea este imposibilă).

Primitivele care urmează pot fi aplicate unui proces existent şi executate doar de proc-părinte.

Procedura distrugere poate fi utilizată de către un proces pentru a se autodistruge.


distrugere(p) va distruge toate procesele desemnate de procesul p şi toţi descendenţii acestora.

Procedura suspendare(p) întrerupe execuţia unui proces p, plasându-l într-un fir de aşteptare
special. Execuţia lui p poate fi reluată doar cu ajutorul primitivei reluare(p).
01.09.20
Utilizarea primitivelor creare, distrugere, suspendare şi reluare 20este
12:47:15
condiţionată
164 de un drept,
care figurează în atributul drepturi al procesului.
Sincronizarea

Procesele sunt sincronizate cu ajutorul monitoarelor. Gestiunea întreruperilor este


integrată în mecanismul monitoarelor: o întrerupere este asociată unei condiţii.

Monitoarele sunt declarate în programele proceselor; un monitor este creat la


compilarea programului, unde el este declarat, şi este mai apoi utilizat conform
regulilor, definite de limbajul de programare utilizat.

4.3.1.2. Structuri şi algoritmi

Din momentul creării sale unui proces i se asociază un număr fix (nume intern, process
handler), care serveşte la desemnarea lui şi permite accesarea blocului său de
context. Blocul de context conţine următoarele câmpuri:
Csp : zona de salvare a cuvântului de stare a programului,
Reg : zona de salvare a registrelor generale ale procesorului,
Stare : valoarea stării procesului (eligibil, blocat, ...),
Prio : prioritatea procesului,
Drepturi : drepturile procesului,
Fire : legături de înlănţuire în ierarhia proceselor,
Suc : legături de înlănţuire în firele de aşteptare (FA).

01.09.20
20 165
12:47:15
Administrarea proceselor utilizează fire de aşteptare, ordonate în ordinea de descreştere a
priorităţilor şi comandate de un set de proceduri de accesare:

introducere(p, f) Introduce p în f, în elementul lui f care corespunde priorităţii procesului.


primul(f) Întoarce numărul (numele) procesului din vârful lui f (nil dacă f este vid); nu
modifică f.
ieşire(p, f) Extrage din f primul proces, numărul pus în p (nil dacă f este vid).
extragere(p, f) Extrage din firul f procesul cu numărul p specificat, nil dacă pr nu există în f.
vid(f) Funcţie bool cu valoarea adevărat, dacă firul f este vid, fals în caz contrar.

.. legătură de înlănţuire
.

Csp[i]

Reg[i]

Bloc de Stare[i]
context
Drepturi[i]
Prio[i]

.. legături de înlănţuire în FA
.
context în memorie

blocul contextului i
01.09.20
20 166
Fig.4.4. Organizarea unui FA de procese 12:47:15
4.3.2. Realizarea monitoarelor
Monitorul, descris mai jos, în raport cu noţiunea clasică de monitor, prezintă următoarele
diferenţe:
Semantica primitivei semnalizare. Specificarea iniţială a primitivei c.semnalizare precizează că
unul din procesele care sunt în aşteptarea condiţiei c (dacă există) este imediat deblocat,
ceea ce implică trecerea temporară în starea blocat a procesului, care execută
semnalizare. În specificarea prezentă procesul deblocat este simplu trecut în starea
eligibil şi trebuie să intre în monitor; el se află, deci, în competiţie cu alte procese, care
aşteaptă să intre în monitor, şi nu este garantat că va fi imediat ales. Condiţia, care
provocase deblocarea, poate fi modificată înainte ca procesul deblocat să-şi reia execuţia
în monitor. Pentru această nouă interpretare trebuie să fie modificată forma punerii în
aşteptare. O construcţie de forma
if continuare_non_posibilă then
c.aşteptare
endif
devine în acest caz
while continuare_non_posibilă do
c.aşteptare
endwhile
Deşi această construcţie introduce un risc de privaţiune, ea prezintă o serie de avantaje de
ordin practic. Ea evită o comutare a contextului, cu preţul unei evaluări suplimentare a
condiţiei. Dar principalul este că ea permite definirea simplă a unor posibilităţi
suplimentare utile (deblocare multiplă, întârzieri de control sau de gardă).
Verificarea validităţii monitorului este simplificată, deoarece condiţia de depăşire
01.09.20
(continuare_posibilă) este consultată în timpul deblocării: 20 procesul
167care execută
semnalizare poate să se mulţumească cu garantarea unei condiţii mai slabe decât
12:47:15

condiţia de depăşire.
Deblocare multiplă
Problema deblocării multiple poate fi rezolvată uşor introducând o primitivă nouă
c.difuzare_semnal efectul căreia se exprimă astfel:
while c.non_vid do
c.semnalizare
endwhile

Fiind dat, că toate procesele deblocate vor testa din nou condiţia şi cer din nou acces la
monitor, această primitivă va avea evident efectul aşteptat.

Întârziere de gardă.
Din probleme de securitate, în special pentru tratarea blocajelor, poate fi util să se asocieze
o întârziere de gardă condiţiei unui monitor. Această întârziere este egală cu durata
maximă de blocare a unui proces într-un fir de aşteptare asociat condiţiei date. La
expirarea întârzierii de gardă va fi efectuată o tratare specificată. Această tratare poate
consta în simpla deblocare a procesului (care va testa din nou condiţia de depăşire) sau
transferul său într-un fir de aşteptare special.

Fie M.c.întârziere întârzierea de gardă asociată unei condiţii c în monitorul M. Se presupune


disponibil un ceas habs, care pune la dispoziţie timpul absolut. Trebuie să adăugăm în
programul primitivei c.semnalizare instrucţiunea următoare:
hdeblocare[p]:=habs+M.c.întârziere
unde hdeblocare[p] este un câmp nou al blocului de context al procesului p. Un proces, numit
“gardian”, deblocat la intervale regulate de timp parcurge
01.09.20 mulţimea contextelor şi
care20 hdeblocare
efectuează tratamentul specificat proceselor pentru 12:47:15 [p]>habs.
168
4.3.2.1. Algoritmi de bază

Programul monitorului trebuie să asigure două funcţii:


• excluderea mutuală pentru procedurile monitorului,
• blocarea şi deblocarea asociate primitivelor aşteptare şi semnalizare.

Fiecărui monitor M îi sunt asociate următoarele structuri de date:


• un dispozitiv de excludere mutuală M.disp (lacăt), care poate lua două valori liber sau
ocupat,
• un fir de aşteptare M.fir asociat acestui dispozitiv. Iniţial M.disp=liber, M.fir=<vid>.

Fiecărei condiţii c de M îi este asociat un fir M.c.fir, un contor de gardă M.c.întârziere şi,
pentru condiţiile asociate unei întreruperi, un indicator boolean M.c.într_sosită.

Firul proceselor eligibile este determinat de f_eligibil.


Pentru M : intrare, ieşire, c.aşteptare şi c.semnalizare (secvenţele intrare şi ieşire sunt
inserate de compilator şi încadrează execuţia procedurilor externe ale monitorului). Să
definim mai întâi procedurile de gestiune a dispozitivului:
cerere_disp(M, p): eliberare_disp(M):
if M.disp=ocupat then if vid(M.fir) then
intrare(p, M.fir); M.disp:=liber
stare[p]:=blocat else
else ieşire(q, M.fir);
M.disp := ocupat; intrare(q, f_eligibil);
intrare(p, f_eligibil); stare[q]:=eligibil
01.09.20
20 169
stare[p]:=eligibil endif12:47:15
endif
Cele patru secvenţe se vor scrie utilizând următoarele proceduri:
intrare(M): ieşire(M):
prolog; prolog;
p:=<proces apelant>; p:=<proces apelant>;
cerere_disp(M, p); eliberare_disp(M);
alocare_procesor; intrare(p, f_eligibil);
alocare_procesor;

c.aşteptare: c.semnalizare:
prolog; prolog;
p:=<proces apelant>; p:=<proces apelant>;
intrare(p, M.c.fir); if non_vid(M.c.fir) then
stare[p]:=blocat; ieşire(q, M.c.fir);
eliberare_disp(M); cerere_disp(M, p);
alocare_procesor; cerere_disp(M, q);
eliberare_disp(M)
else
intrare(p, f_eligibil)
endif
alocare_procesor;
Să ne amintim, că secvenţa prolog asigură salvarea contextului şi intrarea în secţiunea critică,
iar secvenţa alocare_procesor asigură alocarea procesorului şi părăsirea secţiunii critice.

Notăm, că în primitiva semnalizare, procesul apelant p şi procesul


01.09.20 deblocat q sunt introduse
(cu ajutorul primitivei cerere_disp) în firul de aşteptare pentru a 170
20
12:47:15
intra în monitor.
Procesul activat prin intermediul primitivei este primul proces din acest fir.
4.3.2.2. Tratarea întreruperilor

Pentru asigurarea uniformităţii mecanismelor de sincronizare fiecărei întreruperi i se asociază:


o condiţie într-un monitor, un proces ciclic care realizează tratarea întreruperilor, în stare de
repaus acest proces este în aşteptarea condiţiei.

O condiţie poate fi asociată unui singur nivel de întrerupere. Sosirea unei întreruperi provoacă
executarea funcţiei semnalizare pentru condiţia asociată. Prioritatea relativă a
întreruperilor este tradusă în prioritatea proceselor, care tratează întreruperile.

Acest mecanism are carenţe. De exemplu, excluderea procedurilor monitorului nu poate fi


aplicată întreruperilor. Se poate întâmpla ca o întrerupere să fie cerută atunci când
procesul, care tratează întreruperile, este încă activ, din care cauză întreruperea va fi
pierdută. Evitarea acestui fenomen se va face cu ajutorul unui indicator boolean, care
memorizează sosirea unei întreruperi. Vom avea:
<proces de prelucrare a întreruperii>
ciclu
test if nonM.c.într_sosită then
c.aşteptare; -- evitarea pierderii unei întreruperi
go to test
endif;
<tratarea întreruperii>
endciclu
<sosirea unei întreruperi asociate lui M.c> 01.09.20
M.c.într_sosită := true; 20
12:47:15
171
c.semnalizare;
4.3.2.3. Tratarea erorilor

Principiul de tratare a erorilor constă în blocarea procesului care a provocat eroarea şi


expedierea unui mesaj procesului părinte, care va putea lua măsurile necesare
(corectarea erorii şi relansarea sau distrugerea procesului, care a generat eroare). Pentru
aceasta este folosit un fir special f_eroare (în conformitate cu organizarea sistemului,
poate fi prevăzut un fir unic sau un fir pentru fiecare utilizator, pentru fiecare subsistem,
etc.).
Presupunem că o eroare care are loc în cursul execuţiei unui proces provoacă o deviere,
tratarea căreia se va scrie astfel:
prolog;
p:=<proces apelant>;
intrare(p, f_eroare);
<tratare specifică>;
stare[p]:=suspendat;
alocare_procesor;
Am definit o stare nouă (“suspendat”), care se aplică unui proces activitatea căruia a fost
întreruptă de un eveniment, considerat anormal.

Nu detaliem aici <tratare specifică>, care trebuie să fie specificat de către procesul părinte la
momentul creării procesului descendent. Acest program conţine, evident, codul de
diagnosticare (identitatea procesului generator de eroare, natura erorii), care trebuie
transmis procesului părinte într-un mod special, conform
01.09.20 gradului de urgenţă
20 172
(actualizarea unui indicator, deblocare, etc.). 12:47:15
4.3.3.1. Crearea şi distrugerea proceselor
Pentru alocarea contextelor şi numelor proceselor sunt utilizate două metode principale:
• pentru blocurile contextelor sunt rezervate un număr fix de amplasamente; amplasamentele neutilizate -o valoare
specială (nil) a câmpului stare; blocul este desemnat de un număr, care este numărul utilizat pentru desemnarea
procesului asociat;
• amplasamentele rezervate blocurilor sunt alocate dinamic în memorie; numerele sunt alocate proceselor de asemenea
în mod dinamic şi un tabel de corespondenţă, asociază numărului fiecărui proces adresa în memorie a blocului său de
context.

Disponibilă o procedură alocare_context(p), care realizează alocarea contextului (blocul de


context şi spaţiul de lucru) şi întoarce ca rezultat un număr p al procesului. Numărul
procesului creat este întors drept rezultat al primitivei:
creare(p, context iniţial):
prolog;
control; -- verificarea drepturilor
alocare_context(p);
if p  nil then
iniţializare_context(i);
intrare(p, f_eligibil)
endif;
intrare(proces apelant, f_eligibil);
alocare_procesor; -- este întors p drept rezultat

Contextul iniţial este specificat de către procesul creator: el trebuie să definească valoarea
iniţială a registrelor şi a cuvântului de stare a procesului creat, starea iniţială a spaţiului
de lucru, atributele, cum ar fi prioritatea şi drepturile.01.09.20
Unele câmpuri ale cuvântului de
stare sunt predefinite şi nu pot fi modificate (modul, mascarea 20 întreruperilor,
173 etc.).
12:47:15
Pentru elementele legate de protecţie (drepturile de acces), procesul creat nu poate avea
drepturi superioare drepturilor procesului creator; în caz contrar atributele de protecţie
Distrugerea trebuie să implice eliberarea resurselor. Doar numele şi contextul sunt gestionate
direct de nucleu; celelalte resurse, cum ar fi fişierele, sunt preluate de mecanisme
specifice.

Distrugerea unui proces, care se află în secţiunea critică poate conduce la o blocare. Secţiunile
critice ale monitoarelor sunt gestionate direct de nucleu. Este posibil să se asocieze unui
proces numărul dispozitivului de blocare, care se află în posesia procesului dat (el poate fi
angajat în mai multe apeluri incorporate), şi să diferenţiem distrugerea procesului până
când valoarea acestui număr nu va fi 0. O altă soluţie constă în examinarea periodică a
fiecărui dispozitiv de blocare şi să eliberăm dispozitivul de blocare, dacă procesul care îl
posedă a fost distrus.

Principiul primitivei distrugere este dat în schema de mai jos:


distrugere (p):
prolog;
control; -- verificarea drepturilor
eliberare_context(p);
intrare(proces apelant, f_eligibil);
alocare_procesor;

Procedura eliberare_context trebuie să asigure eliberarea resurselor ocupate de procesul distrus


şi de descendenţii acestuia:
eliberare_context(p):
listă:=<lista firelor procesului p>;
restituire_bloc_context(p);
01.09.20
restituire_memorie(p); 20
for q listă do
174
12:47:15
eliberare_context(q)
endfor;
4.3.3.2. Suspendarea şi reluarea

Efectul primitivei suspendare poate fi ca şi al unei devieri şi programul de tratare poate fi


analogic. Suspendarea unui proces pune o problemă analogică celei de distrugere, dacă
procesul se află în secţiunea critică într-un monitor.
suspendare(p):
prolog;
control;
< tratare secţiune critică>;
f:=<fir care conţine p>;
extragere(p, f);
intrare(p, f_eroare);
stare[p]:=suspendat;
intrare(proces apelant, f_eligibil);
alocare_procesor;
Primitiva reluare permite unui proces să deblocheze un fir suspendat, după modificarea
eventuală a contextului său.
reluare(p):
prolog;
control;
extragere(p, f_eroare);
stare[p]:=eligibil;
intrare(proces apelant, f_eligibil);
intrare(p, f_eligibil); 01.09.20
alocare_procesor; 20
12:47:15
175
4.3.4. Excluderea mutuală şi alocarea procesorului
4.3.4.1. Realizarea pentru cazul monoprocesor

În acest caz excluderea mutuală este realizată prin mascarea întreruperilor. Pentru aceasta trebuie pregătită
masca întreruperii în cuvântul de stare, care ar specifica programele asociate primitivelor de tratare a
întreruperilor. Dacă notăm prin proces_ales o variabilă globală, care conţine numărul procesului ales, iar
prin salv_csp locaţiunea în care a fost salvat cuvântul de stare a procesorului la apelarea supervizorului
sau la întrerupere, prologul va fi de forma:
prolog:
<mascarea întreruperilor> -- masca în cuvântul de stare
csp[proces_ales] := salv_csp;
salv_registre(Reg[proc_al]);

Programul dispecerului, care de asemenea realizează ieşirea din secţiunea critică, are grijă să aloce procesorul
primului proces din firul de procese eligibile. Pentru simplificarea manipulării acestui fir este binevenit
să fie introdus aici un proces special cu prioritate joasă, care rămâne tot timpul în coada firului şi nu
poate fi blocat. Acest proces, care poate fi ales doar atunci când el este unicul eligibil, execută o
activitate de fond, care nu este urgentă sau o simplă buclă de aşteptare. El garantează, deci, că firul
proceselor eligibile nu este niciodată vid.

Programul dispecerului este de forma:


alocare_procesor:
ieşire(proces_ales, f_eligibil);
încărcare_registre(Reg[proc_al]);
încărcare_csp(csp[proces_ales]);
Figura 4.5 ilustrează principiul de funcţionare a nucleului, exemplificând efectul global al unei realocări a
01.09.20
procesorului după blocarea procesului ales. 20 176
12:47:15
f_eligibil

Cuvânt de stare
proc_al Registre

Csp Csp Procesor


Reg Reg
Prio=6 5 3 2
p1 p2 p3 p4

c.fişier
(a) începutul executării c.aşteptare

5 1
p5 p6
Cuvânt de stare
f_eligibil proc_al Registre

Procesor

6 5 3
p1 p2 p3
c.fişier

(b) sfârşitul executării c.aşteptare


01.09.20
20 177
5 2 1 12:47:15
p5 p4 p6
Fig.4.5. Alocarea procesorului
4.4.1. Crearea proceselor în Linux
În Linux procesele „se înmulţesc” prin clonare: apelul de sistem, care crează un proces nou, se
numeşte clone, iar procesul fiu este o copie aproape exactă a procesului părinte, doar că mai
departe va executa codul său, iar procesul părinte – ceea ce este scris după apelarea lui clone.
Dacă dorim să evităm diferenţierea, apelarea lui clone permite să definim următorii indicatori
(flags), care specifică momentele comune ale fiului şi părintelui:
Spaţiul de adrese (Clone_VM);
Informaţiile despre sistemul de fişiere (Clone_FS);
Tabelul fişierelor deschise (Clone_FILES);
Tabelul programelor de tratare a semnalelor (Clone_SIGHAND);
Părintele (Clone_PARENT) – în acest caz, evident, va fi creat un proces – frate.
Firele sunt realizate în biblioteca standard de susţinere a programelor cu mai multe fire ca şi
procesele, generate cu indicatorul Clone_VM, şi, din punctul de vedere al nucleului sistemului,
nu se deosebesc de alte procese. În unele biblioteci de alternativă pot exista diferenţe.
Există fire „handicapate”, generate de funcţia kernel_thread pentru necesităţi interne ale
sistemului. Acestea nu au parametri pentru linia de comandă, de obicei nu au fişiere deschise…
Procesele - funcţiile exec (bibl Linux stand): execl, execlp, execle, execv, execve, execvp.
Înlocuiesc codul din procesul curent cu codul, care se află în fişierul indicat. Fişierul poate fi un
fişier binar executabil Linux, un script al interpretorului limbajului de comandă, un fişier binar
de un alt format (de exemplu, o clasă java, un fişier executabil DOS). În ultimul caz modalitatea
de prelucrare va fi determinată de modulul de adaptare a nucleului binfmt_misc. Din această
cauză, operaţia de lansare a unui program, care în DOS şi Windows formează un tot întreg, în
Linux (şi în Unix, în general) este împărţită în două: mai întâi are loc lansarea propriu-zisă, iar
178
apoi se va determina care program va fi executat.
01.09.2020 12:47:15
4.4.2. Distrugerea proceselor în Linux

La terminarea execuției unui proces (normal, forţat sau accidental), el este distrus
eliberând toate resursele, alocate anterior.

Dacă procesul părinte se termină înaintea procesului descendent, ultimul devine


“orfan” (orphaned process). Toţi “orfanii” sunt “înfiaţi” în mod automat de procesul init
(cu numărul 1), care duce evidenţa terminării execuţiei lor.

Dacă a fost terminată deja execuția procesului descendent, iar procesul părinte nu este
gata să recepționeze de la sistem semnalul despre acest eveniment, descendentul nu
dispare total, ci este transformat în Zombie; în câmpul Stat aceste procese sunt notate
cu litera Z. Procesele Zombi nu cer timp de procesor, dar în tabelul proceselor este
păstrată linia lor şi structurile respective ale nucleului nu sunt eliberate. După
terminarea execuției procesului părinte, procesul Zombi orfan devine pentru o perioadă
scurtă de timp descendentul lui init, ca mai apoi să “moară” definitiv.

Un proces poate să “cadă în hibernare”, fără a putea fi scos din această stare: în câmpul
Stat acest eveniment se va nota prin litera D. Procesele aflate în hibernare nu
reacționează la cererile de sistem şi pot fi distruse doar prin reîncărcarea sistemului.

01.09.2020 12:47:15 179


4.4.3. “Demoni” în Linux

Demon (daemon) în Linux este numit procesul destinat să lucreze în regim de fond fără
terminal şi care execută anumite operații pentru alte procese (nu obligator pe
calculatorul Dumneavoastră). De obicei, demonii își îndeplinesc în liniște lucrul şi ne
amintim de ei doar în cazul unor situații ieşite din comun: spaţiu insuficient – demonul
singur informând utilizatorul despre aceasta, sau refuz să lucreze şi sunteți întrebat de
șef când se vor termina problemele cu imprimantă .

Pentru multe calculatoare demonii, care servesc procesele altor calculatoare, sunt rar
utilizați din care cauză nu trebuie păstrați constant în memorie cu cheltuieli neraționale
ale resurselor sistemului. Pentru coordonarea lucrului acestora a fost creat un super
demon – inetd (Internet daemon).

În fișierul de configurare inetd (/etc/inetd.conf) este indicat care demon accesează un


serviciu anume de Internet. De obicei, cu ajutorul lui inetd sunt apelate programele
pop3d, imap4d, ftpd, telnetd (exercițiu - determinați serviciul pus la dispoziție), etc.
Aceste programe nu sunt în mod constant active, în rezultat, ele nu pot fi considerate
demoni în adevăratul sens al cuvântului, dar, deoarece ele sunt create de un demon
adevărat, sunt numite demoni.

01.09.20
20 180
12:47:15
4.4.4. Obținerea informațiilor despre procese

Pentru obținerea informațiilor despre procese, vizualizate de programele ps şi top,


Linux-ul utilizează un sistem special de fişiere, numit procfs.

În majoritatea distributivelor el este iniţializat la lansarea sistemului de operare cu


titlul de catalog /proc. Datele despre procesul cu numărul 1 (de obicei /sbin/init) se
află în subcatalogul /proc/1, despre procesul cu numărul 182 - în /proc/182, etc. Toate
fişierele, deschise de un proces, sunt reprezentate sub forma unor referinţe simbolice în
catalogul /proc/<pid>/fd, iar referinţa la catalogul rădăcină este păstrată ca
/proc/<pid>/root.

Sistemului de gestiune a fişierelor procfs îi sunt asociate şi alte funcţii. De exemplu, cu


ajutorul comenzii echo 100000>/proc/sys/fs/file-max un superuser poate indica, că se
permite deschiderea unui număr de până la 100000 de fişiere, iar comanda
echo 0>/proc/sys/kernel/cap-bound va retrage proceselor din sistem toate drepturile
suplimentare, adică va priva sistemul de noţiunea superuser.

Informaţii utile pune la dispoziţie programul lsof. Acesta returnează lista tuturor
fişierelor, utilizate la momentul curent de către procese, inclusiv cataloagele folosite de
către unele procese în calitate de catalog curent sau catalog rădăcină, bibliotecile
dinamice, încărcate în memorie, etc.
01.09.20
20 181
12:47:15
5.1. Principiile gestiunii informaţiei
5.1.1. Definiţii generale
5.1.2. Interpretarea numelor
5.1.2.1. Construirea căii de acces
5.1.2.2. Structura reprezentărilor. Descriptori
5.1.2.3. Contexte şi medii
5.1.3. Legarea
5.1.4. Protecţia
5.1.4.1. Domenii şi drepturi de acces
5.1.4.3. Problemele protecţiei
5.2. Desemnarea şi legarea fişierelor şi intrărilor-ieşirilor
5.2.1. Căi de acces la un fişier
5.2.2. Desemnarea externă a fişierelor. Cataloage
5.2.2.1. Introducere
5.2.2.2. Organizarea arborescentă
5.2.3. Legarea fişierelor cu fluxurile de intrare-ieşire
5.3. Legarea programelor şi datelor
5.3.1. Etapele de viaţă a unui program
5.3.2. Funcţionarea unui încărcător
5.3.3. Funcţionarea unui editor de legături
5.3.3.1. Legarea prin substituţie
5.3.3.2. Legarea prin înlănţuire 01.09.20
5.4. Mecanisme de gestiune a obiectelor 20 182
5.4.1. Segmentarea 12:47:15
Acest capitol este consacrat studierii principiilor de gestiune a informaţiei în SO.
Noţiunea de obiect formează suportul director al studiului dat.

Concepte de bază: nume sau identificator, cale de acces, legare, protecţia obiectelor.
Aceste noţiuni vor fi utilizate în două domenii importante: desemnarea şi legarea
fişierelor şi legarea programelor şi a datelor.

Informaţia, care circulă într-un sistem de calcul constă din obiecte; obiectele sunt
entităţile asupra cărora sunt efectuate anumite operaţii. Toate operaţiile pot fi clasificate
în patru categorii:
• de creare,
• de modificare,
• de căutare,
• de distrugere a obiectelor.

Fiecare obiect are o reprezentare externă (în afara calculatorului) şi una internă,
determinată de suportul fizic. Un obiect poate fi accesat cu ajutorul funcţiilor de acces.

Problema centrală a administrării informaţiei constă în conversia reprezentării externe şi


a funcţiilor de acces asociate în reprezentarea internă şi funcţiile de acces
corespunzătoare obiectelor sistemului.

01.09.2020 12:47:15 183


5.1. Principiile gestiunii informaţiei
Noţiunile de identificator, valoare, tip, desemnare, reprezentare sunt utilizate în informatică
în forme diverse. Pentru a fi în acelasi cadru conceptual prezentăm un model simplificat, care
se conturează în cadrul limbajelor de programare şi care permite să ţinem cont de cele mai
frecvente situaţii.
5.1.1. Definiţii generale
Programul unui sistem informatic descrie acest sistem ca o mulţime de obiecte, obiectele
sistemului şi operaţiile asociate sunt cele specificate de limbajul utilizat. La implementarea
sistemului definim pentru fiecare obiect o reprezentare concretă, care are forma unei mulţimi
de informaţii în memorie, pentru unităţile periferice, etc. Implementarea sistemului se
traduce în acţiuni, care modifică starea acestor reprezentări.

Procesul de reprezentare utilizează două scheme de bază:


• schema compilării - obiectele abstracte, specificate de program, sunt înlocuite, în faza
preliminară de translatare, prin reprezentările lor.
• schema interpretării - un sistem logic (interpretorul) este alimentat direct de program; el
asociază (în mod static sau dinamic) o reprezentare internă fiecărui obiect şi stabileşte
corespondenţa între obiectul abstract şi reprezentarea la fiecare accesare.

Schema interpretării este de regulă mai puţin eficace în comparaţie cu schema compilării,
deoarece corespondenţa obiectelor trebuie realizată la fiecare accesare, însă ea convine mai
mult în cazul unei gestionări dinamice a obiectelor.

01.09.20
20 184
12:47:15
Programul unui sistem utilizează nume pentru a desemna obiectele. Numele unui obiect este
o informaţie cu funcţie dublă: pe de o parte permite să se facă distincţia obiectului dat de alte
obiecte; pe de altă parte, el serveşte ca şi cale de acces la obiect.
Numele trebuie să respecte anumite reguli proprii limbajului de programare. Nume sunt
identificatorii, care desemnează variabilele şi procedurile într-un limbaj de programare sau
fişierele într-un limbaj de comandă.
În cazul reprezentării externe un identificator desemnează un anumit obiect, care poate fi o
constantă sau o informaţie ce permite accesul la un alt obiect (obiectul permite referirea unui
alt obiect, fig.5.1).

Program
..
. D obiect/reper Ri
identificator
..
.
obiect

Fig.5.1. Relaţia identificator - obiect

Trecerea de la identificator la obiectul propriu-zis se realizează prin compunerea funcţiilor de


acces D şi Ri, obţinând calea de acces la obiect.
01.09.2020 12:47:15 185
Suportul fizic al informaţiei este memoria - şir de amplasamente caracterizate printr-un
conţinut. Un proces desemnează un amplasament printr-un nume folosit de unitatea centrală
pentru a citi şi la necesitate a modifica conţinutul acestui amplasament. Conţinutul unui
amplasament poate fi un întreg, o instrucţiune sau un nume care desemnează alt amplasament.
Reprezentarea externă este convertită în cuplul (amplasament, conţinut), numele
amplasamentului devenind numele obiectului. De exemplu, o constantă devine un cuplu (ampl.,
conţinut invariabil), iar un obiect care reperează altul - (amplasament, conţinut variabil).
Vom face o deosebire între celulele memoriei fizice şi amplasamente prin utilizarea noţiunii de
adresă pentru celule şi nume pentru amplasamente. Obiectele definite de perechea
(amplasament, conţinut) pot fi deplasate în memoria fizică, schimbarea adresei fizice a unui
amplasament nu afectează, în general, numele lui.
Obiectele constituite din mai multe obiecte de acelaşi tip sau de tip diferit (masive, fişiere,
structuri) se numesc obiecte compuse. Numele obiectului compus se află într-un amplasament
al cărui conţinut este un descriptor. Descriptorul, fiind reprezentarea internă a unui obiect
compus, defineşte tipul, numărul componentelor obiectului, o eventuală ordine a acestora,
precum şi amplasamentele în care se află aceste componente. Funcţia de acces asociată
descriptorului are parametri şi furnizează un conţinut sau un nume de amplasament.

Numim obiect accesibil un obiect căruia i s-a asociat o cale de acces. Numim obiect partajat
orice obiect care este accesibil mai multor utilizatori (eventual cu drepturi de acces
diferenţiate).
01.09.20
20 186
12:47:15
5.1.2. Interpretarea numelor
Obiectele sunt păstrate în amplasamente, iar procesele le pot accesa prin nume. Stabilirea căii
de acces la un obiect prin compunerea funcţiilor de acces ataşate se numeşte legare. Vom spune
că un obiect este legat atunci când pentru el este stabilită calea de acces. În cazul operaţiilor
aritmetice calea de acces asociată unui obiect conduce la o constantă; în cazul listelor sau
parametrilor - la un nume. Legarea se traduce, în ultimă instanţă, prin stabilirea corespondenţei
între identificatori şi adrese.
5.1.2.1. Construirea căii de acces
F1 şi F2 - funcţii de acces, accesul de la o1 la o3 fiind realizat prin compunerea acestor funcţii.
Calea de acces de la o1 la o3 - prin metoda substituţiei sau prin metoda înlănţuirii.
Metoda substituţiei stabileşte o nouă funcţie de acces F3, o3 fiind accesat direct de la o1: o1F3o3.
Avantaj - acces rapid, dar şi dezavantajul că o2 este iremediabil pierdut.
Metoda înlănţuirii cere ca la fiecare accesare a obiectului o3 pornind de la o1 să fie parcursă
calea o1F1o2F2o3. Nu se pierde nici o informaţie, dar accesul este mai lent.
Legare la faza de compilare (obiectele private ale unui program), pentru altele calea de acces
este stabilită într-o fază ulterioară (ob. ext. şi parametrii sunt obiecte libere după compilare).
Operaţia de legare a externilor se numeşte editare de legături. Ea poate fi realizată într-o fază
distinctă, premergătoare fazei de execuţie (static), sau în faza de execuţie (dinamic), când se
face prima referinţă la obiectul extern.
Editarea legăturilor se face prin înlănţuire sau prin metoda substituţiei.

187
01.09.2020 12:47:15
Segment - ansamblu de amplasamente consecutive în care se reprezintă obiecte de
acelaşi tip, cu aceeaşi durată de existenţă şi cu acelaşi grad de protecţie.
Segmentul - cea mai mică unitate care poate fi partajată şi poate conţine obiecte
compuse - un masiv, un fişier, o stivă sau o procedură - accesibile procesului la un
anumit moment.
Obiectului procedură îi sunt asociate mai multe noţiuni: modul sursă, modul obiect
sau modul executabil.
Modulul sursă al unei proceduri este textul acesteia scris de către programator într-
un limbaj de programare şi care va fi tratat de către compilator.
Modulul obiect este obţinut la ieşirea compilatorului: este un produs al
compilatorului. Modulul obiect este reprezentat într-un segment sau într-un fişier,
destinat interpretării (după editarea legăturilor, la necesitate) de către procesor ca
instrucţiuni, valori etc., fiind manipulat în consecinţă.
Pentru a separa gestiunea resurselor de administrarea informaţiei s-a introdus
noţiunea de memorie fictivă: memorie operativă ipotetică suficient de mare pentru a
conţine toate obiectele sistemului.
Memoria fictivă este asociată sistemului, memoria virtuală este proprie procesului.

01.09.2020 12:47:15 188


5.1.2.2. Structura reprezentărilor. Descriptori
Există obiecte elementare, cum ar fi valori întregi, reale sau caractere,
reprezentarea cărora cere un singur amplasament şi pentru care funcţiile de acces
sunt reprezentate direct prin instrucţiunile maşinii fizice. Pot exista obiecte
compuse, structura internă a cărora poate fi complexă, lungimea poate varia pe
perioada timpului de existenţă a obiectului. Poate fi necesar să se realizeze unele
funcţii complexe de accesare a obiectelor compuse.
Numele obiectului compus se află într-un amplasament al cărui conţinut este un
descriptor. Utilizarea unui descriptor pentru a accesa un obiect impune trecerea
printr-un program de accesare care va interpreta acest descriptor şi prezintă
anumite avantaje:
• este mult mai simplu să administrezi informaţii de volum fix şi cunoscut,
• descriptorul constituie un “punct de trecere” impus pentru accesarea reperată a obiectului
şi, ca rezultat, poate servi la implementarea unor controale a accesării, de măsurare, etc.,
• descriptorul asigură un acces indirect la obiectul reperat, ceea ce permite modificarea
dinamică a căii de acces sau deplasarea unui obiect în memorie fără recompilarea
modulului sursă,
• partajarea obiectelor între mai mulţi utilizatori cu drepturi sau proceduri de accesare
diferite poate fi realizată construind tot atâţia descriptori, câţi utilizatori există; aceşti
descriptori reperează acelaşi obiect şi au aceleaşi informaţii de localizare fizică.
01.09.2020 12:47:15
189
5.1.2.3. Contexte şi medii

Considerente din care mulţimea obiectelor accesibile unui proces variază în timp:
• Decompoziţia aplicaţiilor
• Gestiunea dinamică
• Protecţia
• Eficacitatea

Trebuie să luăm în consideraţie atât posibilitatea evoluţiei dinamice a mulţimii obiectelor, cât şi
a căilor de acces la aceste obiecte.

Introducem Lexică - mulţime de identificatori.


Mulţimea obiectelor, desemnate de identificatorii lexicii la un moment de timp dat, se numeşte
context asociat la această lexică.
Starea de execuţie a unui context este starea mulţimii obiectelor, care formează acest context.
Fiind dată doar lexica nu putem defini un context: mai trebuie să fie specificate regulile de
interpretare, care vor fi aplicate identificatorilor din cadrul lexicii.

Mediul de execuție - mulţimea formată din lexică şi informaţiile (programe, date, reguli de
interpretare) necesare la utilizarea acestei lexici. Aceste informaţii pot lua diferite forme în
dependenţă de limbajul utilizat (limbaj de comandă, limbaj de programare).

01.09.2020 12:47:15 190


Accesibilitate a identificatorului într-un program - regiunea programului în care acest
identificator este valid, adică poate fi utilizat ca origine a unei căi de acces: un proces poate
utiliza acest identificator pentru a desemna un obiect.
Mulţimea obiectelor la care procesul are acces este definită pentru orice moment de timp,
aplicând identificatorilor valizi regulile de interpretare, specificate de mediul curent.
Exemplul 5.2. Fie procesul asociat utilizatorului unui sistem interactiv. În mediul, definit de
interpretorul limbajului de comandă, lexica conţine numele fişierelor accesibile utilizatorului.
Atunci când utilizatorul comandă execuţia unei proceduri, mediul se modifică: lexica conţine
identificatorii definiţi în interiorul procedurii de regulile de accesibilitate ale limbajului şi
interpretaţi conform regulilor proprii acestui limbaj.

ident.
context

reguli de
lexica interpretare obiect
cale de acces
mediul
Fig.5.3. Contextul de execuţie a unui proces 191
01.09.2020 12:47:15
Starea de execuţie a unui proces (“valoarea” obiectelor contextului său) se poate modifica la
execuţia fiecărei instrucţiuni, însă conţinutul contextului său (identitatea obiectelor care-l
formează), se schimbă cu o frecvenţă mai mică.

Evenimentele principale care pot modifica conţinutul contextului unui proces:


• Schimbarea mediului, implicând o modificare a compoziţiei lexicii şi, eventual, aplicarea unor reguli de
interpretare noi: apel de procedură, intrarea într-un bloc nou (într-un limbaj cu structură de blocuri),
schimbarea catalogului curent (într-un limbaj de comandă).
• Modificarea explicită a căii de acces, pornind de la un identificator al lexicii: asocierea unui fişier sau
unui periferic unui flux de intrare-ieşire.
• Crearea sau distrugerea explicită a unui obiect desemnat de un identificator din lexică: crearea sau
distrugerea unui fişier, alocarea sau eliberarea unei variabile administrate dinamic.

Examinând aceste cazuri putem diferenţia durata de viaţă a unui obiect, a unui identificator,
care desemnează acest obiect şi cea a unei căi de acces, care conduce la obiectul în cauză.

Sunt posibile diferite situaţii:


• un identificator poate fi legat succesiv de diferite obiecte;
• reciproc, un obiect poate succesiv (sau simultan) fi desemnat de mai mulţi identificatori
diferiţi;
• un obiect poate deveni inaccesibil (nici o cale de acces nu conduce la el).

01.09.2020 12:47:15 192


Exemplul 5.3.Diferite clase de obiecte, accesibile unui proces în cursul execuţiei unei
proceduri, exprimată într-un limbaj de programare de nivel înalt. Aceste clase
diferă din punct de vedere a duratei de viaţă, duratei legăturii şi modului de
partajare a obiectelor.
1. Obiecte interne: acestea sunt instrucţiunile, care compun textul procedurii.
Durată lor de viaţă coincide cu durată de viaţă a procedurii.
2. Obiecte locale: acestea sunt variabilele, declarate în interiorul procedurii.
Aceste obiecte sunt create la fiecare apel al procedurii şi distruse la retur.
3. Obiecte remanente şi obiecte globale: acestea sunt obiectele care existau
deja la apelul procedurii şi care vor supravieţui la retur; durata lor de viaţă
este fie cea a procesului (obiecte remanente), fie cea a unei proceduri, care
înglobează procedura dată (obiecte globale).
4. Obiecte externe: sunt obiectele construite şi păstrate independent de
procedura şi procesul considerat. Durata lor de viaţă nu depinde de cea a
procedurii sau a procesului; ele pot fi create sau distruse în mod dinamic în
timpul execuţiei procedurii.
5. Parametri: parametrii formali sunt identificatori, utilizaţi în interiorul
procedurii şi care sunt legaţi doar în momentul apelării. ◄
01.09.20
20 193
12:47:15
5.1.3. Legarea
Numim legare procesul construirii unei căi de acces. Legarea obiectelor unui
program poate fi efectuată la diferite momente de viaţă a programului:
• În momentul scrierii programului.
• La una din fazele de translatare (asamblare sau compilare).
• La o fază de editare a legăturilor sau încărcare. Faza editării legăturilor are ca scop
stabilirea legăturii referinţelor externe. Faza încărcării are drept scop înlocuirea adreselor
relative prin adrese absolute, fixând originea programelor în memorie. Încărcarea şi
editarea legăturilor pot fi combinate într-o singură operaţie sau realizate separat.
• În timpul execuţiei; legătura este numită în acest caz dinamică. Există mai multe
considerente de întârziere a stabilirii legăturii până la faza de execuţie:
o informaţiile necesare pot fi cunoscute doar la această fază, în particular dacă obiectele desemnate sunt
create dinamic, fiind, deci necunoscute la momentul compilării,
o calea de acces trebuie modificată în timpul execuţiei: este cazul când un identificator este reutilizat
pentru a desemna succesiv mai multe obiecte (de exemplu, flux de intrare-ieşire reasociat mai multor
fişiere diferite),
o mecanismul interpretării impune o legătură dinamică: poate fi cazul, de exemplu, al variabilelor locale
ale unei proceduri recursive, adresa cărora poate fi stabilită doar în cursul execuţiei.
Legarea dinamică constă în completarea unei căi de acces existente deja parţial.

01.09.20
20 194
12:47:15
5.1.4. Protecţia
Protecţie - mulţimea metodelor şi mecanismelor, care vizează specificarea regulilor
de utilizare a obiectelor şi garantează respectarea acestor reguli.
Protecţia este asigurată de o combinaţie de dispozitive fizice şi logice. Există
legături strânse între desemnarea obiectelor şi protecţia lor.
Trei observaţii, legate de protecţie:
• O modalitate simplă de a interzice unui proces orice acces la un obiect constă în
suprimarea tuturor căilor de acces la acest obiect (retragere din contextul
procesului).
• Atunci când operaţiile permise asupra unui obiect sunt specificate prin
apartenenţa la o clasă sau un tip, este posibilă verificarea prealabilă execuţiei
(adică în momentul compilării sau editării legăturilor) dacă obiectul este utilizat
conform regulilor specificate,
• În cazul în care verificarea este făcută în momentul execuţiei, o procedură de
acces facilitează implementarea verificării şi reduce riscul unor erori. Această
procedură poate fi la nivel logic (un interpretor, de exemplu) sau fizic (un
dispozitiv va aproba trecerea mai departe).
01.09.2020 12:47:15 195
5.1.4.1. Domenii şi drepturi de acces

Obiecte “active”. Regulile de utilizare pot fi exprimate specificând drepturile de


acces ale fiecărui obiect activ, adică mulţimea de operaţii pe care obiectele active
sunt autorizate să le execute asupra altor obiecte. Am putea să legăm drepturile
direct de procese, însă această alegere nu permite exprimarea simplă:
• a posibilităţii evoluţiei dinamice a drepturilor unui proces,
• a faptului, că mai multe procese pot avea, în aceleaşi circumstanţe, acelaşi set de
drepturi.
Pentru a ţine cont de aceste două aspecte a fost introdusă noţiunea de domeniu de
protecţie. Această noţiune este un caz particular al noţiunii de mediu - un domeniu
defineşte:
• o mulţime de obiecte accesibile sau context,
• pentru fiecare dintre aceste obiecte, o mulţime de operaţii permise (drepturi),
• un mecanism, care asigură accesul la aceste obiecte, respectând restricţiile de mai sus.

Un proces este întotdeauna executat într-un domeniu bine definit; contextul său
este cel ataşat domeniului, procesul posedând drepturile specificate asupra tuturor
obiectelor acestui context.
Un proces poate schimba domeniul cu ajutorul unei operaţii particulare (apelare
domeniu). Un domeniu este el însuşi un obiect asupra căruia poate fi executată
operaţia de apel.
01.09.2020 12:47:15 196
Domeniile de protecţie pot fi definite prin mai multe modalităţi; exemplificăm câteva mai jos.
un domeniu pentru sistemul de operare, unul pentru fiecare utilizator,
un domeniu pentru fiecare subsistem, care realizează o funcţie particulară,
un domeniu pentru fiecare mediu (definit, de exemplu, de cuplul (procedură, catalog curent)).
Alegerea depinde de funcţiile cerute şi, cel mai important, de mecanismele disponibile.
Presupunem pentru început, că există un număr constant de obiecte. Regulile de protecţie pot fi
reprezentate sub forma unui tablou bidimensional, numit matricea drepturilor. Acest tablou
conţine câte o linie pentru fiecare domeniu Di şi câte o coloană pentru fiecare obiect Oj
(notăm, că domeniile, fiind obiecte particulare, apar de asemenea şi în coloane). Caseta (i,
j) conţine drepturile pe care le are un proces, care se execută în domeniul Di, asupra unui
obiect Oj.

fişierul 1 fişierul 2 periferic D1 D2 D3


D1 <citire, scriere, <citire, scriere, <alocare, <> <apelare> <schimbare
executare> executare> retragere> drepturi>
D2 <citire, scriere, <citire, scriere, <cerere, <apelare> <> <apelare>
executare> executare> eliberare>
D3 <citire, scriere, <citire, scriere, <> <nil> <apelare> <>
executare> executare>
Notaţia nil semnifică faptul, că obiectul Oj nu figurează în contextul domeniului Di, iar notaţia
<> defineşte o listă vidă. În ambele cazuri Oj este inaccesibil în Di; diferenţa apare dacă se vrea
să se ofere lui Di drepturi asupra lui Oj: în primul caz este necesar să se introducă Oj în contextul
lui Di, adică să-l legăm; în cel de-al doilea caz este suficient să extindem197
lista existentă.

01.09.2020 12:47:15
Reprezentarea coloanelor: lista de acces
Lista de acces, asociată unui obiect este o listă (Di, <di>), unde Di este un domeniu, care conţine
obiectul, iar <di> este mulţimea drepturilor acestui domeniu asupra lui.
O metodă frecvent utilizată pentru a reprezenta mai compact listele de acces constă în
specificarea pentru un obiect a unor drepturi implicite (default) pe care le posedă fiecare
domeniu. De exemplu, putem specifica implicit, că orice fişier este accesibil doar pentru lectură
fiecărui utilizator. Lista de acces va conţine doar cuplurile (Di, <di>) pentru care drepturile
diferă de cele implicite.
Reprezentarea liniilor: lista de drepturi
Lista drepturilor asociată unui domeniu este o listă (Oj, <dj>) în care Oj desemnează un obiect,
care figurează în contextul domeniului, iar <dj> este mulţimea drepturilor domeniului asupra lui
Oj. Un proces, care este executat în domeniul considerat, primeşte această listă de drepturi; la
fiecare accesare a unui obiect mecanismul de accesare trebuie să verifice că operaţia curentă
este licită, adică este în <dj>. Din considerente de eficacitate, este de dorit ca acest mecanism
să fie cablat. Forma cea mai primitivă în acest sens este bitul supervizor-slave a cuvântului de
stare a unui procesor.
O operaţie importantă este cea de schimbare a domeniului, care permite unui proces să-şi
modifice mediul şi drepturile asupra obiectelor. Pentru a garanta respectarea regulilor de
protecţie, trebuie luate măsuri de precauţie de fiecare dată, când are loc extinderea drepturilor.
Această circumstanţă se poate produce în egală măsură atât la apel, cât şi la retur. Pentru
controlarea operaţiei de schimbare, se cere ca apelul şi returul domeniului să se facă în mod
exclusiv prin execuţia unor proceduri speciale (ghişeu de apel sau de retur), programele cărora
01.09.20
garantează respectarea regulilor specificate. 20 198
12:47:15
5.2. Desemnarea şi legarea fişierelor şi intrărilor-ieşirilor
Vom examina modul de desemnare a fişierelor, legarea lor cu programele, care le utilizează şi
relaţiile lor cu intrările-ieşirile. Ne va interesa organizarea unui fişier ca un tot întreg.
5.2.1. Căi de acces la un fişier
Un fişier este un obiect compus: el posedă un descriptor, care conţine informaţiile, necesare
localizării sale fizice şi realizării funcţiilor de acces. Pentru SO, numele descriptorului unei fişier
permite accesul la fişier. Acest nume al descriptorului, de obicei necunoscut de utilizatori şi
rezervat doar pentru SO, este numit nume intern al fişierului. Descriptorul şi numele intern al
fişierului sunt unice.
Un fişier este desemnat de către utilizatorii externi cu ajutorul identificatorilor – nume externe.
Aceste nume externe sunt definite într-un mediu comun mai multor utilizatori. Structurile de
date, care permit construirea căii de acces la un fişier pornind de la unul din numele sale
externe, sunt numite cataloage, mape, foldere sau directorii.
În afara numelor interne şi externe, adesea mai este definit un nume, zis local sau temporar. Un
nume local este definit într-un mediu propriu unui utilizator şi are o existenţă doar temporară
Legarea numelor locale este realizată prin înlănţuire: un nume local desemnează un descriptor
local, care la rândul său, direct sau indirect, reperează descriptorul unic al fişierului.
Mediul global Mediul local Mediul SGF

nume externe nume local nume intern

(Cataloage) descriptor local Descriptor


fişier

Fig.5.4. Căi de acces la un fişier 199


01.09.2020 12:47:15
5.2.2. Desemnarea externă a fişierelor. Cataloage
Vom examina modul în care un utilizator poate nota fişierele cu ajutorul identificatorilor sau
nume externe, şi structurile de date sau cataloagele, care permit determinarea descriptorului
fişierului, pornind de la un nume extern. Pentru simplificare vom presupune, că descriptorii se
conţin direct în catalog; în realitate doar o parte a descriptorului se poate afla în catalog,
însoțită de un nume intern, care permite determinarea restului.
Un catalog defineşte un mediu, adică o mulţime de identificatori (sau o lexică) şi regulile de
interpretare a acestor identificatori. Organizarea cea mai simplă poate fi schematic reprezentată
de un tabel, care asociază unui identificator descriptorul fişierului pe care acesta îl desemnează.
Organizarea pe un singur nivel (fig.5.5, (a)) nu este folosită, cu excepţia unor sisteme mono-
utilizator foarte mici. Este preferată cea ierarhică în care fişierele şi cataloagele sunt organizate
conform unei structuri arborescente. Această structură se reflectă în structura identificatorilor.
Adâncimea arborescenţei poate fi limitată: de exemplu, o structură cu două nivele (fig.5.5 (b))
permite definirea a câte un catalog pentru fiecare utilizator a unui sistem, aceste cataloage fiind
şi ele grupate într-un catalog general. catalogul
(a) (b) utilizatorilor
catalog
Mos Ion ... Christy ... Eugen

fişier program doc ... ... ...


test doc program doc program fişier
200
Fig. 5.5. Organizarea fişierelor pe niveluri 01.09.2020 12:47:15
5.2.3. Legarea fişierelor cu fluxurile de intrare-ieşire
Un program schimbă informaţii cu mediul exterior prin intermediul unor operaţii de intrare-
ieşire. care permit comunicarea cu un fişier sau un periferic. În momentul elaborării programului
nu este încă cunoscut cu care fişier sau periferic se vor produce intrările-ieşirile; adesea este
necesar să se utilizeze fişiere sau periferice, care diferă de la o execuţie la altă. Din aceste
considerente este util să se poată întârzia legătura unui program cu fişierele sau perifericele pe
care acesta le utilizează. În acest scop se introduce noţiunea de flux de intrare-ieşire.
Un flux de intrare-ieşire este un obiect, care posedă toate caracteristicile unui periferic de
intrare-ieşire (nume, operaţii de acces), dar care nu are o existenţă reală. Pentru a fi efectiv
utilizat în transferul informaţiilor, un flux trebuie să fie în prealabil legat, cu ajutorul unei
operaţii, numite asociere, cu un fişier sau periferic. Transferul informaţiei, descris de operaţiile
asupra fluxului, vor fi executate asupra fişierului sau perifericului, asociat fluxului. Asocierea
poate fi modificată de la o execuţie la alta, însă textul programului, care face referinţă doar la
numele fluxului, rămâne invariant.
nume de flux nume de flux
nume de flux
fişier perif
nil descriptor descriptor descriptor
de flux de fişier de
periferic

tampon procedură tampon procedură


(a) până la asociere de acces de acces

(b) după asociere la un fişier (c)201


după asociere la un periferic
Fig.5.7. Asocierea unui flux de intrare-ieşire 01.09.2020 12:47:15
5.3. Legarea programelor şi datelor

Am prezentat mai sus diferite momente în care poate fi stabilită legătura dintre instrucţiunile şi
datele unui program. Vom prezenta în rezumat cele mai frecvente scheme înainte de a trece la
realizarea lor. Această prezentare vizează, în principal, expunerea folosirii noţiunii de legare,
fără a detalia aspectele tehnice ale funcţionării unui încărcător sau editor de legături.
1. Program interpretat date

program sursă program interpretat rezultat


2. Program compilat
program obiect
program translator program obiect încărcător (adrese absolute)
sursă (adrese relative)
date calculatorul

rezultatul
Compararea acestor două scheme pune în evidenţă diferenţa importantă între
interpretare şi compilare: modificarea unui program interpretat are efect imediat, în timp ce în
cazul compilării suntem nevoiţi să parcurgem toate etapele, începând cu translatarea.
Program compus
Constituirea unui program unic, pornind de la programe construite independent, se realizează
pornind de la programe obiect în adrese relative (deplasabile), adică obţinute după translatare,
prin legarea referinţelor externe. Această operaţie poate fi combinată cu încărcarea.
01.09.2020 12:47:15 202
5.3.2. Funcţionarea unui încărcător

Un încărcător este destinat să pună în formă absolută un program (sau modul) obiect în adrese
relative. Această operaţie constă în înlocuirea tuturor adreselor relative la originea
modulului prin adrese absolute. Pentru aceasta se va efectua un lucru preliminar în faza de
translatare: înregistrărilor modulului obiect, care conţin o adresă translatabilă, li se va
ataşa un indicator, care va fixa poziţia acestei adrese în interiorul înregistrării (dacă poziţia
nu este specificată în mod implicit). Adresele translatabile pot să apară:
• sau în câmpul de adresă al instrucţiunii,
• sau în cazul datelor, în ”expresii pentru calcularea adresei”, destinate a fi utilizate ca
relaţii de direcţionare sau să fie încărcate în registrele de bază.

Încărcătorul utilizează metoda substituţiei: orice adresă relativă a este înlocuită prin adresa
absolută a+originea, unde originea este adresa absolută începând cu care este încărcat
modulul.

Dacă programul încărcat trebuie imediat executat, o funcţie suplimentară a încărcătorului va


determina adresa absolută de la care trebuie să înceapă execuţia. Această adresă este
adesea fixată prin convenţie (de exemplu, se va porni de la primul amplasament al
modulului).

Pentru cazuri mai generale, modulul poate avea mai multe puncte de intrare, desemnate cu
ajutorul identificatorilor; el va conţine în acest caz un tabel al punctelor de intrare,
construit de translator, care asociază o adresă relativă01.09.20
fiecărui identificator. Aceste adrese
sunt transformate în adrese absolute; adresa punctului de20intrare203
12:47:15
este determinată pornind
de la identificator prin intermediul unei căutări în tabel.
Pentru a ilustra prezentăm un format posibil al unui modul obiect translatabil şi programul
corespunzător al încărcătorului.
en-tête <id_modul, lungime,...>
...
corpul modulului <adr, n, r, cod>
...
...
tabelul punctelor de intrare <identificator, adresă relativă>
...
O înregistrare a corpului modulului este de forma <adr, n, r, cod> cu
adr : adresa relativă a codului <cod> în modul
n : lungimea lui <cod> în octeţi
r : 1 sau 0 (cod translatabil sau nu)
cod : n octeţi ai programului.

01.09.20
20 204
12:47:15
Algoritmul încărcătorului poate fi următorul:

Parametrii de apel : identitatea modulului (numele fişierului)


: adr_încărcare (adresa absolută de încărcare)
: id_început (identificatorul punctului de intrare)
citire(en-tête);
<verificare dacă lungimea permite încărcarea>
repeat
citire înregistrare; -- <adr, n, r, cod>
if r = 1 then
translatare(cod)
endif;
adr_implantare := adr + adr_încărcare;
<ordonarea codului pornind de la adr_implantare>
until corp de modul epuizat
citire(tabel de puncte de intrare);
căutare(id_început,adr_exe);
if eşec then
<ieşire eroare> -- sau alegerea unei adrese implicite
else -- implicit
adr_exe := adr_exe + adr_încărcare
endif;
<ramificaţie la adresa adr_exe>
Procedura translatare(cod) modifică <cod>-ul, translatând01.09.20
adresele relative ale acestuia:
fiecare adresă relativă este incrementată cu adr_încărcare.
20 Poziţia
205acestor adrese în
12:47:15
interiorul înregistrării trebuie.
6. Gestiunea fişierelor
6.1. Noţiuni generale 6.4. Realizarea funcţii de acces elementar
6.1.1. Funcţiile unui SGF 6.4.1. Organizarea descriptorilor
6.1.2. Organizarea generală 6.4.2. Crearea şi distrugerea
6.2. Organizarea logică a fişierelor 6.4.3. Deschiderea şi închiderea
6.2.1. Introducere 6.4.4. Acces elementar la informaţii
6.2.2. Acces secvenţial 6.5. Securitatea şi protecţia fişierelor
6.2.3. Acces direct 6.5.1. Despre securitate şi protecţie
6.3. Organizarea fizică a fişierelor 6.5.2. Securitatea fişierelor
6.3.1. Implantare secvenţială 6.5.3. Protecţia fişierelor
6.3.2. Implantare non contiguă 6.5.4. Autentificarea în Windows NT
6.3.3. Alocarea memoriei secundare 6.6. SGF din sistemul de operare Unix
Acest capitol este consacrat studierii detaliate a gestiunii fişierelor în sistemele de operare:
organizarea logică, reprezentarea informaţiei, realizarea funcţiilor de acces, protecţia şi
securitatea. Noţiunile menţionate sunt ilustrate cu exemple de gestionare a fişierelor în
sistemele de operare Windows şi Unix.

6.1. Noţiuni generale


6.1.1. Funcţiile unui sistem de gestiune a fişierelor
Fişier - mulţime de informaţii, formate cu scopul păstrării şi utilizării lor în cadrul unui SI.
Fişierele au o durată de viaţă superioară timpului de execuţie a unui program sau duratei unei
sesiuni de lucru: ca rezultat, suportul lor permanent este memoria secundară.
Fişierul este un obiect: el posedă un nume, care permite desemnarea sa, are asociate funcţii de
acces, adică operaţii, care permit crearea sau distrugerea, consultarea sau modificarea
informaţiilor, etc.
Componentele unui sistem de operare, care asigură posibilitatea păstrării fişierelor şi realizează
funcţiile de acces se numeşte sistem de gestiune a fişierelor (SGF).
Utilizatorul unui SI organizează informaţiile fişierelor conform necesităţilor proprii, impunându-
le o organizare, numită logică; funcţiile de acces sunt exprimate cu ajutorul acestei organizări.
Reprezentarea informaţiilor fişierelor în memoria secundară (adresa de implantare, codificarea
informaţiei...) determină organizarea fizică a fişierelor. Reprezentarea structurii logice a
fişierelor printr-o organizare fizică este sarcina SGF.
Adesea un fişier este definit ca o colecţie de informaţii elementare de aceeaşi natură, numite
înregistrări sau articole (eng. “items” sau “records”).
01.09.2020 12:47:15 207
Funcţiile principale, asigurate de un sistem de gestiune a fişierelor sunt:
• crearea unui fişier (definirea numelui, alocarea eventuală a spaţiului),
• distrugerea unui fişier (eliberarea numelui şi a spaţiului, alocat fişierului),
• deschiderea unui fişier (declararea intenţiei de a folosi fişierul cu ajutorul funcţiilor de acces),
• închiderea unui fişier anterior deschis (interzicerea oricărui acces ulterior),
• diverse funcţii de consultare şi modificare: citire, scriere, modificarea lungimii, etc.
Funcţiile sunt materializate prin operaţiile de bază, prezente în toate SGF. Adăugăm diverse
funcţii detaliile cărora depind de organizarea sistemului de gestiune: specificarea şi consultarea
drepturilor de acces, consultarea caracteristicilor (data creării, modificării, etc.), operaţii asupra
numelui (schimbarea numelui, etc.).
Păstrarea fişierelor şi realizarea funcţiilor de acces impune SGF să aibă în şarjă:
• gestiunea suporturilor fizice, ascunzând unui utilizator obişnuit detaliile organizării fizice,
• securitatea şi protecţia fişierelor, adică garantarea integrităţii lor în caz de accident sau de rea voinţă şi
respectarea regulilor stabilite de utilizare (drepturi de acces, condiţii de partajare).
Într-un sistem de operare SGF joacă rolul central, deoarece el trebuie să comande cea mai mare
parte a informaţiilor utilizatorilor, cât şi a sistemului propriu-zis.
SGF are legături strânse cu sistemul de intrare-ieşire, este adesea convenabil conceptual să nu
se facă distincţie între fişiere şi unităţile periferice ca suport sursă sau destinaţie a informaţiei în
timpul execuţiei unui program.
01.09.2020 12:47:15 208
6.1.2. Organizarea generală
SGF realizează corespondenţa între organizarea logică şi organizarea fizică a fişierelor.
Organizarea logică, unică cunoscută de utilizator, este determinată de consideraţii de
comoditate şi universalitate. Organizarea fizică, legată de suporturile de memorie utilizate, este
determinată de considerente de economisire a spaţiului şi eficacitatea accesului. Aceste două
organizări sunt, în genere, diferite fiecare fiind definite prin structuri de date proprii, controlate
de SGF. Drept rezultat, SGF sunt construite conform unei structuri ierarhice, care are cel puţin
două niveluri corespunzătoare celor două organizări, menţionate mai sus: orice acţiune, definită
la nivelul logic este interpretată de un set de acţiuni la nivelul fizic.
Pentru separarea organizării fizice de organizarea logică este recomandabil să fie introdusă o
organizare intermediară, care joacă rol de interfaţă. Această organizare intermediară poate fi un
segment, adică o suită de amplasamente adiacente, desemnate de valori întregi pozitive, numite
adrese logice sau deplasări. Putem separa, în acest caz, în două etape stabilirea corespondenţei
între organizarea logică şi cea fizică (fig.6.1):
• traducerea numelor, specificate de funcţiile de acces la fişier, în adrese logice (un atare nume
desemnează o înregistrare sau un câmp al acesteia),
• traducerea adreselor logice în adrese fizice
funcţii de acces

desemnarea înregistrării adresă logică adresă fizică


01.09.20
20 209
12:47:15
Fig.6.1. Adresare logică într-un fişier
Completând modelul de mai sus cu elementele, legate de desemnarea
fişierelor, organizarea SGF poate fi reprezentată conform schemei de mai jos
Funcţii de acces logic
Nume externe
şi locale Interfaţa
legarea numelor utilizatorului

Interpretarea Interpretarea
numelor locale numelor externe

Nume Realizarea
interne funcţiilor de acces
logic

Adrese Realizarea Interfeţe interne la SGF


logice funcţiilor de acces
fizic

Adrese Alocarea Realizarea


fizice memoriei I-E
secundare fizice

Fig.6.2. Organizarea unui sistem de gestiune a fişierelor


01.09.20
20 210
12:47:15
6.2. Organizarea logică a fişierelor
Modurile principale de organizare logică a unui fişier şi realizarea lor: la
această fază a studiului este suficient să traducem în adrese logice sau
deplasare localizarea înregistrărilor, manipulate de funcţiile de acces.
Pentru specificarea organizării logice a unui fişier definim mai întâi o
structură abstractă a fişierului:
Un fişier este o mulţime de înregistrări. Fiecărei înregistrări îi este asociat
un număr constant de n atribute, aceleaşi pentru toate articolele. Un
atribut este definit printr-un nume şi un domeniu de valori. Numele este
pentru desemnarea atributului; două atribute distincte au nume diferite.
Domeniul de valori specifică valorile pe care le poate lua atributul.
Specificarea organizării fişierului este completată de restricţiile, care
trebuie să fie satisfăcute de către înregistrări. Aceste restricţii pot lua
forme diverse (restricţii de ordine a înregistrărilor, restricţii legate de
valorile atributelor, relaţii între atributele diferitelor înregistrări, etc.).
Desemnarea înregistrării, în expresia funcţiilor de acces, utilizează
atributele înregistrării, ţinând cont de restricţiile specificate.
01.09.20
20 211
12:47:15
Exemplul 6.1. Fişier secvenţial de caractere.
Fiecare înregistrare a fişierului posedă următoarele atribute:
(număr de ordine, <întreg>)
(conţinut, <caracter ASCII>)
Restricţie: articolele fişierului sunt ordonate, articolele succesive având drept număr
de ordine valori întregi consecutive.
În reprezentarea fişierului atributul număr de ordine nu este reprezentat explicit, dar este
definit de ordinea articolelor. Mai mult, atributul valoare este reprezentat doar prin valoarea sa,
iar fişierul este reprezentat sub forma unei suite de caractere.
Utilizarea atributului număr de ordine permite specificarea diferitor funcţii de acces. De exemplu,
dacă ne vom limita la consultare:
citire(urm) citeşte caracterul, care urmează după o poziţie curentă specificată
(poziţia ultimei lecturi); pune valoarea caracterului în urm.
citire(i, c) citeşte caracterul cu numărul i; valoarea acestuia este pusă în c.
În ambele cazuri se va specifica efectul funcţiei, dacă caracterul nu există.
Prima funcţie este de tip acces secvenţial, cea de-a două de tip acces direct. ◄

01.09.2020 12:47:15 212


Exemplul 6.2. Fişier de tip document.
Fiecare înregistrare a acestui fişier are următoarele atribute:
(nume_lucrare, <identificatorul lucrării>)
(autor, <lanţ de caractere>)
(editor, <lanţ de caractere>)
(an, <întreg>)
(subiect, <lanţ de caractere>)
Restricţie: 2 articole diferite au ca nume identificatori de lucrări distincte.
Dacă stabilim o anumită ordine a celor cinci atribute, numele acestor
atribute (care sunt acelaşi pentru orice înregistrare), nu este necesar să fie
păstrat în mod explicit. Orice articol este reprezentat de un şir din cinci
câmpuri, fiecare având un format prestabilit.
Pot fi specificate funcţii de acces direct, desemnând un articol prin
atributul nume_lucrare (dacă această desemnare este unică).
Pentru a specifica funcţii de acces secvenţial va fi necesar să ordonăm în
prealabil înregistrările cu ajutorul unei restricţii suplimentare (o relaţie de
ordine, de exemplu, definind o ordine a numelor, autorilor, anului de
editare, etc.). ◄ 01.09.20
20 213
12:47:15
6.2.2. Acces secvenţial
Este permisă doar utilizarea funcţiei “succesor”. Accesul secvenţial este modul
obişnuit de utilizare a unui fişier, implantat fizic pe un suport în care accesarea
amplasamentelor este ea însăşi secvenţială, cum ar fi banda magnetică.
Un fişier f poate fi deschis pentru citire sau scriere. Unele organizări autorizează
scrierea începând de la o înregistrare oarecare. Considerăm, că scrierea se face la
sfârşitul fişierului şi deschiderea pentru scriere iniţializează fişierul în “vid”.
Deschiderea este realizată prin operaţia:
deschide(mod)
if mod=citire then
f.rest:=<şirul înregistărilor fişierului>
else
f:=<vid>
endif;
f.mod:=mod;
avansare
unde funcţia avansare este definită după cum urmează:
if f.rest=vid then
f.sfârşit:=true
else
f.primul:=<pointer pe primul(f.rest)>;
f.rest:=f.rest-primul(f.rest)
endif 01.09.2020 12:47:15 214
Operaţia de citire a unei înregistrări are forma:
citire(f, a):
if f.sfârşit=false then
a:=<înregistrarea desemnată de f.primul>;
avansare
endif
Scrierea adaugă o înregistrare la sfârşitul fişierului:
scriere(f,a)
if mod=citire then
<eroare>
else
alocare spațiu pt înregistrare nouă;
if eşec then -- lungimea maximă a fost atinsă sau este necesar un spaţiu mai mare
<eroare>
else
f.pa:=<pointer pe amplasamentul înregistrării noi>;
<copiere a în amplasamentul desemnat de f.pa>
endif
endif
Aceste funcţii de acces se traduc utilizând adresele logice. Dacă articolul curent nu este ultimul
în fişier, adresa logică a succesorului său este dată de adresa(curentă)+lungimea(curentă).
Dacă articolele sunt de lungime variabilă, lungimea înregistrării curente poate fi obţinută
plecând de la conţinutul acestui articol.
215
01.09.2020 12:47:15
6.2.3. Acces direct
Funcţiile de acces sunt exprimate ca funcţii ale atributelor înregistrărilor; aceste
atribute sunt valori ale diferitor câmpuri. Se numeşte cheie orice câmp al unei
înregistrări valoarea căruia poate servi la identificarea înregistrării. Conform
organizării adoptate, unul sau mai multe câmpuri pot servi drept cheie.
6.2.3.1. Cheie unică
Într-un fişier cu cheie unică fiecare înregistrare conţine o singură cheie, care
identifică înregistrarea fără ambiguitate; restul înregistrării este informaţia propriu-
zisă. Două înregistrări distincte vor avea totdeauna două valori diferite ale cheii.
Definim o procedură căutare(cheie, al), care pentru orice valoare a cheii:
• sau pune la dispoziţie adresa logică al (unică) a înregistrării pentru care cheia posedă
valoarea dată (caz de succes)
• sau semnalizează cu ajutorul unui mecanism, că o atare înregistrare nu există (caz de
eşec): excepţie, cod de condiţie; valoarea al este adresa la care înregistrarea ar putea fi
inserată (valoare specială, dacă nu mai este spaţiu liber).
Procedura căutare serveşte la realizarea funcţiilor elementare de acces direct
citire(cheie, info), adăugare(cheie, info), suprimare(cheie, info), modificare(cheie, info).
Pentru realizarea procedurii căutare pot fi utilizate două metode: adresarea
dispersată şi indexarea. 01.09.20
20 216
12:47:15
Adresare dispersată (“hash-coding”)
Aici căutare este realizată direct, construind al = f(cheie). Funcţia f se numeşte funcţie hash.
Dacă dorim să evităm utilizarea ineficientă a spaţiului memoriei va trebui să ne îndreptăm
atenţia spre alegerea funcţiei de corespondenţă între adresele logice şi fizice.
O funcţie hash ideală realizează o permutare între mulţimea cheilor şi cea a adreselor logice,
limitată la numărul de înregistrări din fişier. Pentru simplitate presupunem, că adresele logice
pentru un fişier cu n înregistrări sunt 0,..., n-1. Funcţia de dispersare trebuie să posede
următoarele proprietăţi:
• pentru orice înregistrare din fişier cu cheia c: 0 ≤ f(c) < n, (6.1)
• pentru orice cuplu de înregistrări f(c1) ≠ f(c2), dacă c1 ≠ c2. (6.2)
În practică este dificil să se satisfacă proprietatea (6.2): din această cauză trebuie admisă
posibilitatea coliziunilor - numărul de valori distincte calculate de funcţia de dispersare este
inferior valorii lui n. În caz de coliziune este necesară o fază suplimentară pentru determinarea
înregistrării căutate sau, în cazul unei inserări, să i se caute un loc.
Alegerea funcţiei de dispersare în scopul reducerii probabilităţii coliziunilor şi a metodelor de
tratare a coliziunilor trebuie să ţină cont de caracteristicile utilizării fişierului:
• probabilitatea unor valori diferite ale cheii,
• frecvenţa relativă a operaţiilor de căutare, inserare şi suprimare a articolelor.

01.09.20
20 217
12:47:15
Principalul avantaj al metodei adresării dispersate (dacă se reuşeşte să se asigure un nivel
acceptabil al coliziunilor) este rapiditatea: în lipsa coliziunilor găsirea unei înregistrări necesită o
singură accesare a discului.
Totuşi, în cazul cel mai frecvent, când mulţimea cheilor este ordonată, funcţia de dispersare nu
întotdeauna asigură o relaţie simplă între ordinea cheilor şi ordinea adreselor logice a
înregistrărilor respective.
Metodele accesului indexat permit remedierea acestui inconvenient.
218
01.09.2020 12:47:15
Fişiere indexate
Metodele accesului indexat sunt utilizate în cazul când mulţimea cheilor este ordonată. Relaţia
dintre cheie şi adresa logică este materializată printr-un tabel, numit tabel al indicilor, în care
ordinea cheilor este semnificativă. Schema principiului organizării indexate este dată de fig.6.4
Schemele utilizate efectiv în practică sunt mai complexe pentru a permite:
• accelerarea căutării în cadrului indicelui,
• facilitarea inserării şi a suprimării înregistrărilor.

01.09.2020 12:47:15 219


6.2.3.2. Chei multiple
Este cazul când pot fi utilizate mai multe
chei pentru a desemna o înregistrare.
În caz general, pot exista mai multe
înregistrări pentru care o cheie particulară
are o valoare dată.
O cheie, valoarea căreia determină
înregistrarea în mod univoc, se numeşte
cheie primară; termen aplicat, prin extensie,
şi pentru o combinaţie de chei.
Tehnica de bază folosită pentru manipularea
unui fişier cu chei multiple este organizarea
multilistă. Este utilizat câte un indice
distinct pentru fiecare cheie. Fiecare intrare
a tabelului indicilor, asociată unei valori
concrete a cheii, punctează topul unei liste În afara tabelului indicilor referinţelor au mai fost
în care sunt toate înregistrările pentru care introduse un tabel al autorilor şi unul al editorilor.
cheia considerată posedă valoarea dată. Fiecare intrare a tabelului indicilor autorilor este topul
Pentru realizarea acestor liste fiecare unei liste, care grupează toate înregistrările pentru care
înregistrare trebuie să conţină tot atâţia valoarea câmpului autor este aceeaşi. Pointerii acestor
pointeri câte chei ale referinţelor distincte liste sunt adrese logice. Este simplu de găsit toate
există. lucrările unui autor publicate la una şi aceeaşi editură.
Pot fi obţinute combinaţii
01.09.20 pentru aceste cereri cu
Figura 6.5 ilustrează această organizare 20 220
pentru exemplul unui fişier document.
ajutorul operaţiei intersecţie.
12:47:15
Este posibilă comprimarea reprezentării
fişierului, utilizând liste circulare, care includ
intrările corespunzătoare ale tabelelor indicilor
(lista lucrărilor scrise de Paul, de exemplu, se tabelul
adresă
închide la intrarea Paul din tabelul indicilor logică
indicilor
autorilor). referinţelo
r
Câmpurile autor şi editor ale părţii info a
reprezentării înregistrărilor pot fi suprimate
pentru că ele pot fi determinate din listele tabelul
înregistrăr
respective. indicilor
i
autorilor
Dezvoltând această idee, se poate crea câte un
indice distinct pentru fiecare câmp;
reprezentarea înregistrărilor va conţine doar tabelul
pointeri şi toată informaţia se conţine doar în indicilor
editorilor
tabelele indicilor.
Un fişier reprezentat în acest mod se numeşte tabelul
inversat. Această reprezentare permite un indicilor
răspuns imediat la cereri legate de combinaţii anilor
ale câmpurilor şi poate fi combinată cu Fig.6.6. Organizarea unui fişier inversat
organizarea directă, utilizând o cheie primară.
Tabelele indicilor secundari conţin în acest caz
listele valorilor cheii primare. Pentru exemplul
unui fişier documentar organizarea descrisă mai 01.09.20
20
sus este schematic prezentată în figura 6.6. 12:47:15
221
6.3. Organizarea fizică a fişierelor
În modelul prezentat mai sus, problema organizării fizice a fişierelor poate fi
formulată astfel: să se elaboreze o implantare în memoria secundară a unei
mulţimi de fişiere respectând următoarele ipoteze:
• orice fişier este definit logic ca un segment, adică ca o mulţime de
informaţii, care ocupă amplasamente adiacente, reperate prin adrese
logice sau deplasări,
• dacă nu există concretizări particulare (bandă magnetică, de exemplu),
memoria secundară este de tip disc, organizată ca o mulţime de blocuri de
lungime fixă.
Notăm aici, că dacă sistemul de operare realizează o memorie virtuală
segmentată, implantarea fizică a segmentelor şi realizarea funcţiilor de acces
elementar (citire, scriere, execuţie) sunt puse în şarja sistemului. Este posibilă
în acest caz confundarea noţiunilor de segment şi fişier.
Vom trata cazul unei gestionări directe de către SGF a implantării fizice a
fişierelor. Pot fi evidenţiate două clase de metode, dacă luăm în considerare
respectarea sau nerespectarea contiguităţii adreselor logice.

01.09.20
20 222
12:47:15
6.3.1. Implantare secvenţială (contiguă)
În acest caz fiecare fişier ocupă o mulţime de blocuri consecutive în memoria
secundară. Este unicul mod de implantare în cazul unei benzi magnetice: fişierele
sunt aranjate consecutiv pe bandă, fiecare fiind separat de următorul cu ajutorul
unui simbol, numit sfârşit de fişier (end of file, EOF). Un EOF dublu marchează
sfârşitul părţii utilizate a benzii. Descriptorul unui fişier este plasat la începutul
fişierului şi, adesea, repetat la sfârşitul fişierului. În interiorul fişierului
înregistrările sunt aranjate consecutiv; dacă lungimea lor este variabilă, ea va fi
prezentă la începutul fiecărei înregistrări. Caracterul EOF este detectat în mod
automat de controlerul mecanismului de derulare a benzii. O operaţie “căutarea
EOF-ului fişierului” permite saltul de la un fişier la altul pentru căutarea unui fişier
cu numele dat.
Implantarea secvenţială poate fi în egală măsură folosită şi pentru discuri.
Avantajul principal constă în garantarea unui acces secvenţial eficient
(informaţiile cu adrese logice succesive sunt implantate în blocuri adiacente)
permiţând în acelaşi timp un acces direct eficient (calcularea adresei fizice
pornind de la adresa logică este foarte simplă şi nu cere accesarea discului).
Totuşi, această metodă prezintă inconveniente grave în cazul în care crearea,
distrugerea sau modificarea lungimii unui fişier sunt operaţii frecvente.
Implantarea contiguă pe disc este utilizată pentru fişierele numărul şi lungimea
cărora nu variază (de exemplu, fişiere create odată pentru totdeauna şi utilizate
mai apoi doar pentru consultare); sisteme primitive pentru microcalculatoare,
când simplitatea realizării este un factor preponderent.
01.09.2020 12:47:15 223
6.3.2. Implantare non contiguă
Dacă abandonăm restricţia contiguităţii implantării, memoria secundară se transformă într-o
resursă banalizată, blocurile memoriei secundare fiind echivalente din punctul de vedere al
alocării lor.
6.3.2.1. Blocuri înlănţuite

Fig.6.7. Alocare prin blocuri înlănţuite


Blocurile fizice, care conţin amplasamente logice consecutive sunt înlănţuite între ele; pentru
această înlănţuire trebuie să fie rezervat în fiecare bloc un pointer. Descriptorul conţine un
pointer la primul şi ultimul bloc şi numărul blocurilor ocupate (fig.6.7).
Ultimul bloc, care poate fi utilizat parţial, trebuie să conţină indicaţii despre numărul de
amplasamente ocupate. Deoarece există un pointer la ultimul bloc este simplu să extindem un
fişier, adăugând informaţii la sfârşit.
Este bine adaptat accesului secvenţial. Putem accesa un bloc doar respectând înlănţuirea;
accesul direct este costisitor, deoarece fiecare citire a unui 01.09.20
pointer necesită o accesare a
20
discului. La fel şi extinderea altfel, decât la sfârşit, este foarte dificilă.
12:47:15
224
6.3.2.2. Tabele de implantare
În cazul accesului direct timpul de acces la un bloc trebuie să nu depindă de adresa sa, ceea ce
poate fi obţinut punând toţi pointerii într-un tabel unic de implantare. Problema principală este
garantarea uniformităţii timpilor de acces pentru tabelele de lungime mare şi permiterea
inserării şi distrugerii blocurilor în orice punct al fişierului.
Tabel unic
Figura 6.8 (a) descrie o organizare cu tabel unic. Lungimea fişierului este limitată de numărul
blocurilor pe care descriptorul le defineşte în tabel (el însuşi conţinându-se într-un număr întreg
de blocuri).
Tabel înlănţuit
Conform organizării din fig.6.8 (b) tabela de implantare constă dintr-o suită de blocuri
înlănţuite. Putem depăşi în acest fel limitarea dimensiunii unui fişier, devine posibilă inserarea
blocurilor în mijlocul fişierului, cu condiţia rezervării unor amplasamente libere în tabel.
Reorganizarea generată de inserare este legată de un bloc al tabelului, iar dimensiunea tabelului
de implantare este limitată de costul căutării în acest tabel. Pentru tabele mari organizarea
descrisă este mai eficace.
Tabele cu mai multe nivele
Figura 6.9 descrie o organizare în care tabelul de implantare a fişierului este organizat în mod
arborescent, pe niveluri (de obicei, două sau trei niveluri). Organizarea dată permite un acces
direct rapid la un bloc cu adresa logică dată; ea permite inserările cu unele măsuri de precauţie.
01.09.20
20 225
12:47:15
Fig.6.8. Tabel de implantare cu un
nivel

01.09.20
20 226
12:47:15
Fig.6.9. Tabel de implantare cu două
nivele
6.3.3. Alocarea memoriei secundare
Problema alocării memoriei secundare poate fi pusă în termeni similari cu cea a memoriei
principale; restricţiile principale sunt:
• alocarea prin blocuri de lungime fixă,
• costul ridicat al accesului,
• caracteristicile proprii fiecărui suport: piste, dispozitive de citire-scriere mobile sau fixe.

Interfaţa alocatorului memoriei secundare conţine două primitive:


cerere_zonă(n,a) date: n (întreg), numărul de blocuri contigue cerute
rezultat: a (adresă), adresa primului bloc
excepţie: număr de blocuri insuficiente
eliberare_zonă(n,a) date: n (întreg), numărul de blocuri contigue eliberate
a (adresă), adresa primului bloc
excepţie: număr de blocuri eliberate

Cazul n=1 - primitive particulare (cerere_zonă, eliberare_zonă).

Structura de date cel mai des utilizată pentru a descrie starea de ocupare a memoriei este un
lanţ de biţi, bitul cu numărul i indicând starea (ocupat sau liber) a blocului cu acelaşi număr.
Acest tabel de ocupare poate atinge dimensiuni importante; de exemplu, sunt necesari 12,5 Ko
pentru a descrie ocuparea unui disc de 200 Mo alocaţi prin blocuri de 2 Ko. Pentru a spori
eficienţa algoritmilor de alocare tabelul poate fi organizat pe mai multe niveluri.
227
01.09.2020 12:47:15
6.4. Realizarea funcţiilor de acces elementar
6.4.1. Organizarea descriptorilor
Un descriptor de fişier trebuie să conţină informaţii diverse:
• informaţii pentru localizarea fizică,
• informaţii referitoare la utilizare,
• informaţii asociate protecţiei şi securităţii.
6.4.1.1. Localizarea fizică
Dacă aceste informaţii sunt de dimensiune fixă şi redusă (implantare contiguă, blocuri
înlănţuite) ele se conţin direct în descriptor; în caz contrar (tabele de implantare înlănţuite sau
pe mai multe niveluri), descriptorul conţine doar un pointer la tabelul de implantare şi nişte
informaţii sintetice, cum ar fi dimensiunea fişierului, dimensiunea tabelului de implantare, etc.
6.4.1.2. Informaţii de utilizare
Informaţiile, legate de utilizarea unui fişier pot fi clasificate după cum urmează:
• Informaţii de stare. Aceste informaţii definesc starea curentă a fişierului: deschis sau
închis, gradul de partajare, disponibilitatea pentru modificare, etc.
• Informaţii despre conţinutul fişierului. Aceste informaţii permit interpretarea conţinutului
fişierului. Este posibil să se asocieze unui fişier un tip, care specifică operaţiile permise.
• Informaţii despre structura logică. Aici pot fi plasate informaţiile care permit trecerea de la
structura logică la structura fizică a fişierului. De exemplu, în cazul înregistrărilor de
lungime fixă este convenabil să se aleagă lungimea înregistrării multiplu sau submultiplu al
lungimii blocului fizic. Raportul lungimea blocului/lungimea înregistrării, adesea numit
factor de bloc, figurează în cadrul descriptorului.
• Informaţii despre utilizările precedente. Aceste informaţii pot fi de natură statistică
(numărul deschiderilor, accesărilor, intervalul mediu timp 01.09.20de între accesări, gradul mediu
de partajare, etc.) şi au scopul de a înţelege mai bine funcţionarea
20
12:47:15
sistemului pentru
228
ameliorarea lui.
Ca şi majoritatea funcţiilor unui sistem de operare, aceste primitive pot fi
apelate în două moduri: cu ajutorul unor instrucţiuni sau prin apelarea regimului
supervizor.

La nivelul limbajului de comandă fişierele sunt desemnate prin numele lor


simbolic, care este interpretat în contextul curent. Dacă o primitivă este apelată
printr-un apel al supervizorului, în timpul execuţiei unui program, fişierele sunt,
de obicei, desemnate de numele local, care este cel al unui descriptor valid în
interiorul programului curent.

Corespondenţa între numele simbolice şi numele locale este realizată prin


instrucţiuni de asociere. Interpretarea numelor fişierelor este comună tuturor
primitivelor.

În continuare pentru fiecare primitivă vom prezenta:


• specificările interfeţei,
• algoritmul care o realizează,
• situaţiile anormale posibile.

01.09.20
20 229
12:47:15
6.4.2.1. Crearea
Specificarea interfeţei
Parametrii furnizaţi sunt:
numele fişierului
tipul (opţional)
lungimea (opţional)
starea iniţială (opţional)

Cel mai frecvent, parametrii starea iniţială şi lungimea nu sunt furnizaţi, având valori
implicite: lungimea = 0, fişierul este închis, lista de acces predefinită.
Operaţii
• să se creeze un descriptor pentru fişier, obţinem astfel un nume intern,
• dacă numele furnizat este un nume extern, să se creeze o intrare a acestui nume în
catalogul curent,
• să se aloce memorie fişierului; chiar dacă lungimea sa este nulă, un fişier conţine un
antet, care ocupă primul său bloc,
• să se iniţializeze descriptorul cu informaţiile de localizare, lungime, protecţie (lista
drepturilor iniţiale de acces),
• dacă descriptorul nu se conţine direct în catalog, să se introducă o intrare în catalog
cu numele intern al fişierului (adresa descriptorului).
Cazuri anormale
• nume furnizat incorect (incorect construit sau care desemnează un fişier deja
existent);
• memorie insuficientă în memoria secundară. 01.09.20
20 230
Fişierul nu poate fi creat şi situaţia anormală este semnalată.
12:47:15
6.4.2.2. Distrugerea
Specificarea interfeţei
Unicul parametru furnizat este numele fişierului. Efectul operaţiei este de a suprima
orice acces ulterior la fişier, invalidând toate numele acestuia şi eliberând toate
resursele pe care fişierul le utilizează (intrări în tabele, memorie).
Operaţii
• să se elibereze toată memoria, care a fost alocată fişierului;
• să se elibereze memoria alocată descriptorului şi numele intern să devină reutilizabil;
• suprimarea numelui extern al fişierului în catalogul, care-l include, de asemenea,
dacă este cazul, în tabelul numelor locale.
Ultima operaţie poate fi destul de delicată, dacă există mai multe căi de acces la fişier.
Poate fi utilizată una din următoarele soluţii:
• dacă căile multiple de acces sunt legături, nu se va lua nici o măsură; un acces
ulterior prin una din aceste legături va conduce la numele extern. Inexistenţa
fişierului va fi detectată (cu excepţia cazului în care un fişier cu acelaşi nume a fost
creat în intervalul de timp dat);
• dacă căile multiple de acces sunt nume (ceea ce se poate produce, dacă structura
catalogului nu este o arborescenţă) vor fi utilizate sau legături inverse (metodă
costisitoare), sau un contor al referinţelor păstrat în descriptor, care duce evidenţa
numărului căilor de acces.
Un fişier poate fi distrus doar dacă există o singură cale de acces. Această soluţie este
utilizată, de exemplu, în sistemul Unix.
01.09.2020 12:47:15 231
6.4.3.1. Deschiderea
Specificarea interfeţei
Parametrii operaţiei de deschidere sunt:
numele fişierului, condiţiile de utilizare: modul de acces (citire, scriere, execuţie, etc.),
procedurile de acces (secvenţial, direct, sincron, etc.), parametrii de transfer (tampoane,
etc.)

Scopul - de a pune un fişier în starea în care accesul este posibil conform modului specificat.
Această operaţiei este de dublă utilitate pentru SGF:
Protecţie. SGF poate să controleze:
la deschidere, dacă utilizatorul este autorizat să acceseze fişierul în condiţiile specificate,
la fiecare accesare a fişierului, dacă condiţiile de acces sunt compatibile cu cele specificate la
deschidere,
în caz de partajare, dacă condiţiile de accesare ale utilizatorilor sunt reciproc compatibile.
Eficienţă. SGF poate să accelereze accesul la fişierele deschise, aducând în memorie descriptorii
lor, tabelele de implantare şi textele procedurilor de acces. Fişierul însuşi poate fi
transferat, eventual, pe un suport cu acces mai rapid; dacă el se află pe un suport amovibil
nemontat, montarea este necesară.
Operaţii
La deschidere vor fi realizate următoarele operaţii:
localizarea fişierului şi, eventual, transferarea lui pe un suport mai rapid,
controlarea dreptului utilizatorului de a deschide fişierul în modul specificat,
crearea unui descriptor local şi atribuirea unui nume local,
alocarea eventuală a memoriei pentru zonele tampon de intrare-ieşire.
01.09.20
Cazuri anormale 20
12:47:15
232
condiţii de deschidere incompatibile cu drepturile utilizatorului, imposibilitatea deschiderii,
datorată restricţiilor specificate pentru partajare, lipsa spaţiului în memorie.
6.4.3.2. Închiderea

Specificarea interfeţei
Unicul parametru necesar este numele fişierului. Efectul operaţiei este de a interzice orice acces
ulterior la fişier şi de a-l transfera într-o stare coerentă şi stabilă, redându-i definitiv toate
modificările operate în perioada cât a fost deschis.

Operaţii
Descriptorul fişierului este actualizat (dacă aceasta nu a fost făcut anterior) pentru a înregistra
definitiv modificările operate în perioada cât a fost deschis; descriptorul local este
suprimat, numele local putând fi reutilizat. Memoria ocupată de zonele tampon şi
procedurile de intrare-ieşire este eliberată, dacă ea a fost alocată doar pentru perioada de
deschidere a fişierului. Fişierul este, eventual, transferat pe suportul său de origine; o
cerere de demontare este trimisă dacă suportul de origine este amovibil.

Unele sisteme operează cu fişiere temporare, adică fişiere desemnate doar de numele local. La
închiderea unui astfel de fişier, utilizatorul are de ales între două posibilităţi:
să catalogheze fişierul, atribuindu-i un nume extern; fişierul va fi în acest caz salvat.
(implicit) să nu facă nimic, fişierul fiind distrus în acest caz.

Cazuri anormale
Pentru garantarea coerenţei fişierului, în timpul închiderii nu trebuie să aibă loc operaţii de
transfer (a descriptorului sau a fişierului).
01.09.20
20 233
12:47:15
6.4.4. Acces elementar la informaţii

Parametrii primitivelor de transfer permit specificarea:


• “metodei de acces” utilizate, care determină modul de desemnare a înregistrărilor -
obiectul transferului (acces secvenţial, direct, cu chei, etc.),
• sincronizarea transferului (transfer sincron sau asincron); în cazul unui transfer asincron,
modul de deblocare a unui proces apelant,
• zonele tampon utilizate (specificate de către utilizator sau furnizate de SGF).

Accesul elementar (citire sau scriere) la o înregistrare a fişierului constă din două etape:

• determinarea adresei fizice a înregistrării plecând de la desemnarea sa logică;


• executarea transferului fizic.

01.09.20
20 234
12:47:15
6.5.1. Despre securitate şi protecţie

Fişierele conţin toată informaţia administrată de sistemul de operare, inclusiv informaţia


necesară gestiunii sistemului. Este important să se garanteze integritatea acestor informaţii în
eventualitatea unor pene fizice, logice sau în caz de rea voinţă. Obiectivele şi metodele pot fi
considerate aparţinând la două direcţii: securitate şi protecţie.

Cu titlul securitate vom îngloba mulţimea metodelor, care sunt chemate să garanteze execuţia
tuturor operaţiilor asupra unui fişier în conformitate cu specificaţiile lor, chiar în cazul unor
defecte în cursul execuţiei, şi că informaţiile conţinute într-un fişier nu sunt alterate, dacă nici o
operaţie nu a fost executată. Metodele utilizate sunt, în caz general, cele care asigură toleranţa
sistemului la defecte; baza lor este redundanţa informaţiilor.

Prin protecţie vom înţelege mulţimea metodelor chemate să specifice regulile de utilizare şi să
garanteze respectarea lor. O descriere succintă a metodelor principale de protecţie a fost adusă
în 5.1.4. Ele se bazează pe noţiunea de drept de acces şi existenţa unui mecanism, care permite
să se garanteze conformitatea operaţiilor drepturilor de acces specificate.

01.09.20
20 235
12:47:15
6.5.2. Securitatea fişierelor
Securitatea fişierelor este asigurată, după cum a fost menţionat, prin redundanţa informaţiilor.
Redundanţa poate fi introdusă în două moduri: salvarea periodică a unor informaţii, pentru a
putea restabili o stare anterioară în caz de distrugere, şi redundanţa internă, care permite
reconstituirea unor informaţii devenite incoerente din cauza unui accident de origine fizică sau
logică, care a provocat o alterare parţială.
6.5.2.1. Redundanţa internă şi restabilirea informaţiilor
Principiul redundanţei interne constă în organizarea structurilor de date astfel, încât orice
informaţie să poată fi obţinută prin cel puţin două căi distincte. Se reduce astfel probabilitatea
că distrugerea accidentală a unei părţi a informaţiei va conduce la pierderea iremediabilă a
conţinutului fişierului.
Tehnicile frecvent utilizate în acest scop sunt următoarele:
pentru un fişier păstrat pe disc în blocuri înlănţuite se va folosi înlănţuirea dublă, se va include
în fiecare bloc un pointer la blocul, care conţine descriptorul, sau indicaţia că blocul este liber,
se va include în descriptor numele simbolic al fişierului şi un pointer la catalogul în care se
conţine fişierul, o parte a descriptorului va fi dublată.
6.5.2.2. Salvare periodică
Se poate apriori conveni să fie salvate, la intervale regulate de timp, toate informaţiile conţinute
într-un SGF. Poate fi realizată salvarea doar a modificărilor, care au avut loc pentru ultima
perioadă, concomitent cu lucrul normal al sistemului.
01.09.20
20 236
12:47:15
6.5.3. Protecţia fişierelor

Protecţia fişierelor foloseşte principiul listelor de acces. O listă de


acces, asociată unui fişier, conţine drepturile fiecărui utilizator
asupra fişierului, adică mulţimea operaţiilor care îi sunt permise.

În practică, diferite convenţii permit reducerea listei. Este definită


mai întâi mulţimea drepturilor atribuite implicit fiecărui utilizator
(mulţime, care poate fi vidă); lista de acces va conţine doar
utilizatorii, drepturile cărora diferă de cele implicite.

Convenţii de grupare permit asocierea unei mulţimi de drepturi


unui grup de utilizatori (membrii unui proiect, etc.), ceea ce reduce
şi mai mult lista. Lista de acces serveşte la verificarea validităţii
oricărei operaţii asupra fişierului.

01.09.20
20 237
12:47:15
7. Alocarea resurselor
7.1. Noţiuni generale
7.1.1. Definiţii
7.1.2. Probleme în alocarea resurselor
7.1.3. Exemple de sisteme cu fire de aşteptare
7.2. Modele pentru alocarea unei resurse unice
7.2.1. Alocarea procesorului
7.2.1.1. Introducere
7.2.1.2. Prim sosit, prim servit
7.2.1.3. Cererea cea mai scurtă servită prima
7.2.1.4. Caruselul şi modele derivate
7.3. Tratarea blocărilor
7.3.1. Enunţul problemei
7.3.2. Algoritmi de prevenire
7.3.2.1. Algoritmi de profilaxie
7.3.2.2. Algoritmul bancherului
7.3.3. Algoritmi de detectare şi tratare
În acest capitol prezentăm principiile de alocare a
resurselor într-un SI. Sunt abordate două aspecte:

• utilizarea rezultatelor teoriei firelor de aşteptare pentru


analiza câtorva modele simple ale sistemelor informatice,
în special pentru alocarea procesoarelor;
• prezentarea unor metode de evitare a impasurilor
(blocarea reciprocă a mai multor procese rezultată din
alocarea eronată a unor resurse comune).

01.09.20
20 239
12:47:15
7.1. Noţiuni generale
7.1.1. Definiţii
Resursă - orice obiect, care poate fi utilizat de un proces. Unei resurse îi sunt asociate proceduri
de acces, care permit utilizarea resursei, şi reguli de utilizare - “modul de utilizare”.
Nu există vre-o diferenţă fundamentală între noţiunea de obiect şi cea de resursă. Folosirea celor doi termeni semnifică
mai mult o diferenţă de domeniu: se utilizează noţiunea obiect atunci când ne interesează specificarea şi realizarea
obiectului şi a funcţiilor sale de acces, iar resursă pentru problemele de alocare şi partajare.
O resursă este alocată unui proces dacă procesul poate utiliza resursa, folosind procedurile ei de
acces. Legarea unei resurse de un proces poate fi implicită sau explicită. În primul caz, este
suficientă trecerea procesului într-o anumită stare pentru ca el să devină candidat la utilizarea
resursei; în cel de-al doilea caz, solicitarea trebuie să fie formulată explicit sub forma unei cereri
adresate unui alocator al resursei.
Alocatoarele şi cererile pot lua forme diverse: de exemplu, un alocator poate fi un proces căruia
cererile îi sunt transmise prin emiterea unor mesaje; sau chiar un monitor o procedură a căruia
serveşte la emiterea unor mesaje.
Reacţia unui alocator la o cerere poate de asemenea fi diferită: alocarea resursei solicitate, refuz
cu sau fără blocarea procesului solicitant. Terminarea utilizării unei resurse de către un proces
poate la fel lua diferite forme: eliberarea explicită sau implicită a resursei sau retragerea forţată
a resursei de către alocator.

01.09.2020 12:47:15 240


Exemplul 7.1. Procesorul. Procedurile “de acces” la procesor sunt determinate de
instrucţiuni şi cuvântul de stare; alocarea procesorului unui proces se face prin încărcarea
cuvântului său de stare. Nu există cereri explicite: pentru a fi în stare să depună o astfel de
cerere, procesul ar trebui să posede deja procesorul – obiectul cererii! Un proces devine în
mod implicit candidat la utilizarea procesorului din momentul când trece în starea eligibil.
Alocatorul constă din două proceduri: planificatorul şi dispecerul. ◄

Exemplul 7.2. Memoria principală. Alocarea memoriei principale pune în funcţie două
mecanisme distincte:
Alocarea explicită: este mecanismul de obţinere a unei zone de memorie fie de către un program
în curs de execuţie, fie de către sistemul de operare înaintea încărcării unui program nou.
Alocarea implicită: pentru acest mod de alocare cererea este emisă în momentul executării unei
instrucţiuni, când adresa emisă de procesor este adresa unui amplasament nealocat
procesorului. Acest mecanism stă la baza realizării memoriei virtuale. ◄

Exemplul 7.3. Memoria secundară. Memoria secundară este alocată prin blocuri banalizate
de lungime fixă. Alocarea şi eliberarea poate fi explicită sau implicită (de exemplu,
extinderea unui fişier provoacă emiterea unei cereri pentru un bloc suplimentar). ◄

Exemplul 7.4. Linii de comunicaţie. Dacă mai multe procese partajează serviciile unui
dispozitiv de intrare-ieşire comun (o imprimantă sau o linie de comunicaţie, de exemplu),
cererile sunt transmise sub formă de mesaje unui proces, numit server, care administrează
acest dispozitiv. Fiecare mesaj conţine informaţiile necesare execuţiei transferului cerut.
Mesajele sunt administrate cu ajutorul unui fir de aşteptare
01.09.20 cu sau fără priorităţi. ◄
20 241
12:47:15
7.1.2. Probleme în alocarea resurselor

Obiectivul unui sistem de alocare a resurselor este să satisfacă cererile într-un mod echitabil,
asigurând în acelaşi timp şi performanţe acceptabile. Dacă toate procesele au aceeaşi
prioritate, o alocare este echitabilă, atunci când este asigurată o tratare asemănătoare
fiecărui proces, de exemplu, aşteptarea medie este identică. Dacă între procese există
priorităţi, este dificil să se definească noţiunea de echitate în caz general, dar ea poate fi
exprimată prin faptul, că calitatea serviciului (măsurată, de exemplu, prin valoarea inversă
a timpului mediu de aşteptare sau printr-o altă expresie semnificativă) este funcţie
crescătoare de prioritate, două procese de aceeaşi prioritate beneficiind de aceeaşi tratare.

Unii algoritmi de alocare conţin riscul de a face un proces să aştepte la infinit - privaţiune.

Dacă resursele sunt utilizate de mai multe procese pot avea loc două fenomene nedorite:
• Blocarea - este stoparea a mai multor procese pentru un interval de timp nedefinit, fiecare
dintre procese fiind în aşteptarea eliberării resurselor alocate altor procese.
• Căderea –o cerere excesivă a unui oarecare tip de resurse conduce la degradarea
performanţelor sistemului.

Vom presupune, că alocarea se va face în mod centralizat, adică algoritmii utilizaţi ştiu situaţia
de alocare a mulţimii resurselor la orice moment.

Instrumentul principal, utilizat pentru studiul cantitativ al alocării


01.09.20 resurselor sunt modelele
firelor de aşteptare. 20
12:47:15
242
7.1.3. Sisteme cu fire de aşteptare

Un sistem informatic este constituit din N instalaţii identice, fiecare fiind descrisă de modelul
M/M/1, cu parametrii λ şi μ (fig. 7.1a). Vom examina influenţa asupra timpului de răspuns
al acestui sistem a utilizării comune a resurselor, caracteristicile totale de tratare fiind
constante.

Fig.7.1. Modelul unui sistem de servire în masă

Timpul mediu de răspuns pentru fiecare caz va fi:


tma = 1/[μ(1-ρ)]
tmb = 1/μ+C(N,Nρ)/[Nμ(1-ρ)]
tmc = 1/[Nμ(1-ρ)]
01.09.20
Aici avem tmc = tma/N şi putem demonstra, calculând C(N, Nρ), 20că tma >243
tmb > tmc. De exemplu,
pentru N=2, μ=1 şi ρ=0,8 vom avea tma = 5, tmb = 2,8, tmc = 2,5.
12:47:15
7.2. Modele pentru alocarea unei resurse unice

7.2.1. Alocarea procesorului


7.2.1.1. Introducere
Algoritmii de alocare a procesorului pot fi clasificaţi în funcţie de mai multe caracteristici.
1) Algoritmi cu sau fără retragere
2) Cu prioritate

Prioritatea unui proces este o informaţie, care permite clasificarea procesului în cadrul altor
procese, dacă trebuie făcută o alegere.

Prioritatea poate fi definită prin mai multe moduri:


• prioritate constantă: definită apriori, funcţie de timpul de servire cerut.
• prioritate variabilă în timp: funcţie de timpul de aşteptare scurs, de serviciul deja acordat, etc.

Variabila principală, care prezintă interes este timpul mediu de răspuns. Cererea este
caracterizată de repartiţia intervalelor de sosire şi de timpul de servire.

Din practică este cunoscut, că un utilizator suportă cu atât mai greu aşteptarea servirii unei
cereri cu cât lucrul trimis de el este de durată mai mică; aceasta este adevărat atât pentru
lucrul interactiv, cât şi pentru cel de fond. Din aceste considerente metodele de alocare a
procesorului au drept scop reducerea timpului mediu de aşteptare a lucrărilor celor mai
scurte.
01.09.20
Ele diferă conform modului de estimare a duratei lucrărilor 12:47:15
şi în20dependenţă
244 de privilegiile
acordate lucrărilor funcţie de această durată estimată.
7.2.1.2. Prim sosit, prim servit

Disciplina “PSPS” (FIFO) utilizează un fir unic, fără prioritate şi fără retragere. Procesul ales este
executat până la terminarea sa, iar cel care va urma este procesul din topul firului de
aşteptare. Un proces nou intră în coada firului.

Timpul mediu de răspuns este dat de formula Pollaczek-Khintchine:


tm = tms[1+ρ(1+C2ts)/2(1- ρ)], C2ts= Var(ts)/(tms)2 (7.1)

tm

Var(ts
)

1 ρ=λts
Fig.7.2. Timpul mediu de răspuns pentru
Variaţia timpului mediu de răspuns f de încărcarea sistemului şi de variaţia timpului de servire.
Putem remarca:
• creşterea rapidă a timpului mediu de răspuns, atunci când sistemul
01.09.20 se apropie de saturaţie: un sistem
este cu atât mai sensibil la o variaţie a şarjei, cu cât este mai 12:47:15
ridicat
20 ρ, 245
• influenţa dispersiei timpilor de servire asupra timpilor de răspuns.
Aceste două efecte pot fi întâlnite în toate disciplinele de alocare.
7.2.1.3. Cererea cea mai scurtă servită prima

În acest caz cererile sunt ordonate în cadrul firului de aşteptare conform timpului lor de servire,
presupus apriori cunoscut, cererile cu durata de servire cea mai scurtă aflându-se în top.
Timpul mediu de aşteptare tm funcţie de timpul de servire ts este dat de formula (7.2):
t m (1  C t )
2 2 ts
tm(ts) = s s
cu  (t s )    tdB ((7.2)
t)
2[1   (t s )] 2 0

Formulele de aproximare sunt

pentru valori mici ale ts, unde ρ(ts) poate fi neglijat:


t m (1  C t )
2 2

tm(ts) ≈ (7.3)
s s

pentru valori mari ale ts, unde ρ(ts) este aproape de λtms, fie ρ:
t m (1  C t )
2 2

tm(ts) ≈ (7.4)
s s

2(1   ) 2

01.09.20
20 246
12:47:15
CSSP are două dezavantaje: ea prezintă un risc de privaţiune
pentru cererile lungi, dacă rata de sosire a cererilor scurte
este ridicată şi necesită cunoaşterea apriori exactă a ts. tm
CSSP
Evitarea riscului de privaţiune - cererilor priorităţi care vor
creşte odată cu creşterea timpului lor de aflare în firul de
aşteptare, prioritatea iniţială fiind determinată de timpul de FIFO
servire estimat.
Disciplinei HRN (Highest Response Ratio Next) prioritatea
unei cereri la un moment de timpτ
p(t) = [t(τ)+ts)]/ts (7.5) ts
unde t(τ) este timpul de aflare a unei cereri în firul de Fig.7.3. Dependenţa timpului mediu de răspuns d
aşteptare (fie t(τ)= τ – τs, aici τs fiind momentul sosirii timpul de servire în cazul disciplinelor FIFO şi
cererii), iar ts timpul de servire estimat. Pentru două cereri
cu acelaşi timp de aşteptare, prioritate are cererea mai
scurtă. În practică, priorităţile sunt recalculate în momente
discrete de timp şi firul de aşteptare este reordonat la
necesitate.
Ideea directoare a acestui algoritm este de a partaja echitabil procesorul, încercând să se
menţină o valoare constantă a raportului k = t/ts, unde t este timpul total de aflare a unei
cereri în sistem. Dacă aceasta se respectă, totul se va petrece pentru fiecare lucrare ca şi
cum ea ar dispune de un procesor de k ori mai slab (mai puţin rapid) decât procesorul real.
Disciplina HRN privilegiază lucrările scurte, însă penalizarea lucrărilor de lungă durată este
01.09.20
redusă de efectul priorităţii variabile. 20 247
Algoritmii descrişi mai jos vizează la fel partajarea echitabilă
12:47:15 a procesorului, dar nu necesită

cunoaşterea apriori a timpului de servire.


7.2.1.4. Caruselul şi modele derivate
În modelul caruselului (“round robin”) procesorul este alocat succesiv proceselor eligibile pentru
o perioadă constantă de timp τ, numită cuantă. Dacă un proces se termină sau se blochează
înainte de sfârşitul cuantei, procesorul este imediat alocat procesului următor. Această
disciplină de servire este implementată ordonând procesele într-un fir de aşteptare
circular; un pointer de activare, care avansează cu o poziţie la fiecare realocare a
procesorului, desemnează procesul ales (fig.7.4).

ieşire
intrar
e
f_eligibil proc_ale
s
Fig.7.4. Alocarea procesorului: metoda
caruselului
Caruselul este un exemplu de disciplină cu retragere. Ea poate fi considerată o aproximare a
disciplinei “cel mai scurt primul” pentru cazul când durata execuţiei lucrărilor nu este
cunoscută anticipat. Este utilizată în sistemele interactive; valoarea cuantei este aleasă
astfel ca majoritatea cererilor interactive să poată 01.09.20
fi executate în timpul unei cuante.
Evident, valoarea cuantei trebuie să fie net mai mare decât 20 durata
12:47:15
comutării procesorului.
248
Analiza este mai simplă (τ →0, timpul de comutare a procesorului neglijat)
- procesor partajat (PP), totul are loc ca şi cum fiecare proces dispune imediat de
un procesor viteza de procesare a căruia este cea a procesorului real, divizată la
numărul curent al proceselor servite:
ta(ts) = ρts/(1-ρ),
iar timpul de răspuns este
t(ts) = ts/(1-ρ).

Modelul procesorului partajat realizează o alocare echitabilă, în care timpul de


aflare a unui proces în sistem este proporţional cu durata serviciului cerut.

O îmbunătăţire a modelului caruselului, chemată să reducă timpul de servire a


lucrărilor de scurtă durată, este caruselul multinivel.

Acest model conţine n fire de aşteptare F0, F1,..., Fn-1. Fiecărui fir Fi îi este asociată o
cuantă proprie τi, valoarea căreia creşte odată cu i. O lucrare din Fi este servită
doar dacă firele de număr inferior lui i sunt vide.
Dacă o lucrare din Fi şi-a epuizat cuanta sa fără a se termina, ea intră în firul Fi+1;
lucrările din Fn-1 se întorc tot aici. Lucrările noi intră în F (fig. 7.5).
01.09.20 0
20 249
12:47:15
t(ts) t(ts)
CM PP CM
PP
CSSP

CSSP

ts ts
FIFO – prim sosit prim servit PP – procesor partajat
intrare procesor ieşire CSSP – cerere scurtă servită prima CM – carusel
multinivel
Fig. 7.5. Carusel cu mai multe niveluri Fig. 7.6. Compararea disciplinelor de alocare a procesorului

01.09.20
20 250
12:47:15
7.3. Tratarea blocărilor

7.3.1. Enunţul problemei


Un exemplu de blocare reciprocă a fost prezentat în capitolul 4, când două secţiuni critice,
corespunzătoare la două resurse distincte, sunt imbricate eronat, existând un risc de
blocare pentru o perioadă de timp nedefinită.

O atare situaţie poate fi generalizată pentru un număr oarecare de procese şi resurse, dacă sunt
îndeplinite următoarele condiţii:
1) resursele sunt utilizate în excludere mutuală,
2) fiecare proces trebuie să utilizeze simultan mai multe resurse, şi acaparează fiecare
resursă pe măsura necesităţilor sale, fără a le elibera pe cele pe care le posedă deja,
3) cererile de resurse sunt blocante şi resursele nu pot fi retrase,
4) există o mulţime de procese {p0,..., pn}, astfel încât p0 cere o resursă ocupată de p1, p1 cere
o resursă ocupată de p2, ..., pn cere o resursă ocupată de p0.

Problema impasului poate fi soluţionată în două moduri:


• prin prevenire: algoritmul de alocare a resurselor garantează, că o situaţie de blocare nu se
poate produce,
• prin detectare şi tratare: nu sunt luate măsuri preventive; blocarea este detectată doar
dacă are loc, iar tratarea şi “însănătoşirea” constă în aducerea sistemului într-o stare, în
care procesele sunt deblocate, în caz general, cu o pierdere de informaţii.

01.09.20
20 251
12:47:15
8. ADMINISTRAREA MEMORIEI 8.5. Principiile şi mecanismele de bază ale
paginaţiei
8.1. Concepte de bază
8.5.1. Paginarea unei memorii liniare
8.1.1. Memorie virtuală
8.5.2. Paginarea unei memorii segmentate
8.1.2. Probleme de alocare a memoriei
8.5.3. Implementarea paginării
8.1.3. Alocarea dinamică a memoriei
8.6. Gestiunea memoriei virtuale paginate
8.2. Comportamentul programului
8.6.1. Parametrii unei discipline de alocare
8.2.1. Comportamentul într-o memorie
virtuală liniară 8.6.2. Algoritmi de reamplsare cu partiţie fixă
8.2.2. Comportamentul programelor 8.6.3. Algoritmi cu partiţie variabilă. Reglarea
segmentate şarjei
8.3. Partiţionarea memoriei fără 8.7. Gestiunea unei memorii cu mai multe
reamplasare nivele ierarhice
8.3.1. Metoda du-te – vino simplă 8.7.1. Memorii ierarhice
8.3.2. Partiţionarea memoriei 8.7.2. Administrarea transferurilor
8.4. Alocarea dinamică a zonelor de 8.8. Resurse tehnice de administrare a
memorie memoriei în procesoarele Intel
8.4.1. Mecanisme de reamplasare
dinamică
8.4.2. Algoritmi de alocare
Separarea conceptuală a problemelor de desemnare şi de legare, pe de o parte, şi a problemelor
de alocare a memoriei, pe de alta, este prezentată schematic mai jos.

obiecte memorie memoria


nume desemnare virtuală alocarea fizică
legare memoriei

Memoria virtuală este mulţimea locaţiunilor desemnate de adresele generate de procesor.

Două metode de organizare:

1) Memoria virtuală liniară sau plată. Memoria virtuală este o suită de amplasamente identice,
organizate secvenţial şi desemnate de valori întregi consecutive, numite adrese virtuale.
Un obiect este reprezentat de una sau mai multe locaţiuni consecutive şi este desemnat de
adresa virtuală a primului amplasament.

2) Memorie virtuală segmentată. Memoria virtuală constă dintr-o mulţime de segmente. Un


segment ocupă o suită de amplasamente consecutive şi poate avea o lungime variabilă. O
adresă virtuală în acest caz este un cuplu (numărul segmentului, deplasarea cuvântului în
cadrul segmentului), numită adresă segmentată. Un obiect, care poate ocupa segmentul
parţial sau în întregime, este desemnat de adresa segmentată
01.09.20 a primului său amplasament.
20 253
12:47:15
8.1.2. Probleme de alocare a memoriei

Alocarea memoriei trebuie să permită unui proces să acceseze un obiect definit în memoria
virtuală, aducând în timp acceptabil acest obiect în memoria principală, unica care este
direct adresabilă. Ca rezultat, o disciplină de alocare a memoriei trebuie să soluţioneze
următoarelor două probleme:
a) stabilirea corespondenţei între adresele virtuale şi adresele fizice,
b) realizarea gestiunii memoriei fizice (alocarea locaţiunilor, transferul informaţiilor).
Dacă informaţiile aparţin mai multor utilizatori apar două restricţii suplimentare:
c) realizarea partajării informaţiilor între mai mulţi utilizatori,
d) asigurarea protecţiei reciproce a informaţiilor, care aparţin unor utilizatori distincţi.
Exemplul 8.1. Reacoperire (overlay). În acest exemplu:
memoria fizică

programul

arbore de
reacoperire

configuraţia 1

configuraţia 2
Fig.8.1. Execuţie cu reacoperire

• decuparea în segmente este realizată explicit de către programator,


01.09.20care specifică arborele de reacoperire,
• corespondenţa între adresele virtuale şi fizice este realizată odată pentru
20 totdeauna
254 de către încărcător,
12:47:15
• zonele de memorie asociate segmentelor sunt de asemenea alocate la încărcare,
• transferul segmentelor între memoria principală şi memoria secundară este realizată în timpul executării◄
1. Alocare statică – corespondenţa virtual-fizic stabilită odată pentru totdeauna

• un singur program în memorie


• partajarea memoriei între mai multe programe

2. Alocare dinamică - corespondenţa virtual-fizic variabilă în timp


Alocarea memoriei fizice
pe zone (de lungime variabilă)
pe pagini (de lungime fixă)

Scopul unei discipline de alocare dinamică a memoriei este să asigure, că la orice instanţă de
timp informaţia necesară pentru execuţia instrucţiunii curente este accesibilă procesorului
imediat, adică se află în memoria principală. O disciplină de alocare trebuie să specifice
următoarele momente:
Când va fi încărcat un obiect în memoria principală?
atunci când este necesar (încărcare la cerere),
înainte de a fi necesar (preîncărcare).
Unde va fi încărcat acest obiect?
dacă există spaţiu liber suficient, în care amplasamente (problema amplasării),
în caz contrar, care obiecte să fie întoarse în memoria secundară (problema reamplasării).

Criterii pentru evaluarea şi compararea algoritmilor de alocare a memoriei:


legate de utilizarea memoriei, măsurată, de exemplu, prin rata spaţiului neutilizat,
legate de accesarea informaţiei, cum ar fi timpul mediu01.09.20
de acces sau rata paginilor absente,
globale: rata utilizării unităţii centrale sau timpul de răspuns20
12:47:15
al unui
255sistem interactiv.
8.2.1. Comportamentul într-o memorie virtuală liniară

Considerăm un program, executat într-o memorie virtuală liniară, care conţine toate
instrucţiunile şi datele. Precizări:

Trecerea timpului este reperată prin execuţia unor instrucţiuni consecutive: executarea unei
instrucţiuni defineşte o unitate de timp. Acest timp se numeşte virtual, deoarece el este
asociat unei execuţii fictive a programului în ipoteza că el dispune de toate resursele
necesare (memorie şi procesor). În cazul partajării resurselor, putem considera că
programele sunt independente.

Cererea de memorie este evaluată împărţind memoria virtuală în pagini adiacente de lungime
fixă, care conţin un număr întreg np de amplasamente. Accesarea unui amplasament dintr-
un bloc se numeşte referire a acestui bloc. Blocurile sunt numerotate cu valori întregi
consecutive, care permit etichetarea referinţelor. Modificând valoarea lui np, putem
examina comportamentul programului la diferite nivele de detaliere. La nivelul cel mai fin
(np=1) putem urmări referinţele instrucţiune cu instrucţiune.

Comportamentul programului, la nivelul de detaliere ales, este definit de secvenţa numerelor de


pagini, care au fost obiectul referinţelor succesive în timpul execuţiei.

Această secvenţă este numită lanţ de referinţe pentru programul considerat şi lungimea aleasă a
paginii.
01.09.20
20 256
12:47:15
8.2.1.1. Proprietăţile lanţurilor de referinţe

Experienţa arată, că lanţurile de referinţe posedă caracteristici comune, care pot fi descrise
calitativ astfel:

Neuniformitate. Fie ni numărul total de referinţe la pagina pi. Repartiţia valorilor ni este
neuniformă: o parte mică a paginilor totalizează o parte importantă a numărului total de
referinţe. Pentru exemplificare: se constată frecvent că un număr de peste 75% de
referinţe sunt generate de mai puţin de 25% de pagini.

Localizare. Pentru o perioadă suficient de mică de observare, repartiţia referinţelor prezintă o


oarecare stabilitate: la un moment de timp dat, referinţele observate într-un trecut
apropiat sunt o bună estimare a referinţelor viitoare.

Această ultimă proprietate poate fi exprimată într-un mod mai precis cu ajutorul unui model al
comportamentului programelor. În acest model, care este doar o reprezentare simplificată
a realităţii, derularea unui program este definită ca o succesiune de “faze”, separate de
“tranziţii”. O fază i este caracterizată printr-o mulţime de pagini Si şi un interval de timp
(virtual) Ti. Când programul intră în faza i, el rămâne aici o perioadă de timp Ti şi
concentrează referinţele sale la paginile care aparţin lui Si. Apoi are loc o tranziţie, în cursul
căreia referinţele la pagini sunt dispersate, înaintea intrării în faza i+1.

Fazele constituie, deci, perioade de comportament stabil şi relativ previzibil, în timp ce tranziţiile
au un comportament mai greu de stăpânit. 01.09.20
20 257
12:47:15
Noţiunea de mulţime de lucru (“working set”)
este utilizată în egală măsură pentru
caracterizarea comportamentului unor
programe, cât şi pentru a încerca să
prognozăm acest comportament după
observări.
La orice moment de timp t, mulţimea de lucru
a ferestrei T, notată prin W(t,T), este mulţimea
paginilor, care au fost obiectul a unei referinţe
cel puţin în perioada t-T şi t (timp virtual).
Proprietatea de localizare este exprimată prin
faptul, că paginile care aparţin la W(t, T) au o
probabilitate mai ridicată, în comparaţie cu
alte pagini, să fie obiectul unei viitoare
referinţe la momentul de timp t, cu condiţia că
lungimea T a ferestrei este aleasă corect.

01.09.20
20 258
12:47:15

Fig.8.2. Referinţele unui program în memoria


8.2.1.2. Comportamentul într-o memorie cu capacitate limitată
Studiem performanţele sistemului în funcţie de volumul de memorie alocat programului.
Iniţial programul se află în memoria secundară; la un moment dat de timp, doar o submulţime a
paginilor sale sunt prezente în memoria operativă. Dacă referinţa următoare este făcută unei
pagini absente, are loc evenimentul, numit pagină lipsă, şi pagina absentă este încărcată în
memoria principală. Dacă nu există spaţiu disponibil suficient, pagina încărcată trebuie să ia
locul unei pagini deja prezente - algoritm de reamplasare.
Comportamentul unui program într-o memorie cu capacitate limitată pentru un algoritm de
reamplasare dat, este caracterizat de o secvență de evenimente pagină lipsă.
Experienţa arată, că sunt observate proprietăţi comune pentru majoritatea programelor şi
relativ independente de algoritmul de reamplasare utilizat.
Proprietăţile observate sunt ilustrate de două curbe, obţinute executând un program pe
memorii de lungime variabilă.

Intervalul între
două absenţe de
pagini

capacitatea memoriei
01.09.20
20 259
Fig.8.3. Intervalul mediu între două absenţe de
12:47:15
pagini în funcţie de capacitatea memoriei
8.3.2. Partiţionarea memoriei
8.3.2.1. Partiţionarea fixă
Într-un sistem cu partiţionare fixă memoria este împărţită în mod static într-un număr fix de
zone. Capacitatea şi limitele acestor zone sunt definite la generarea sistemului.
Fiecare program poate ocupa doar un singur segment şi este asociat în mod constant unei zone
de memorie. Programele sunt păstrate pe disc în cod absolut, iar adresele prezente în
fiecare program sunt adresele fizice, care corespund adreselor de implantare din zona
atribuită
sistemul zona 1 zona 2
memoria
fizică
A

C B
programe

1) Alocarea memoriei

A(1) B(2) C(1)


Unitatea programele
Activită centrală încărcare
(zone)
Canalul
ţi salvare
B(2) A(1) C(1) B(2)

2) Cronograma
Fig.8.6.activităţilor
Sistem cu partiţii fixe 01.09.20
Atunci când un program este transferat din sau spre zona sa,
260un
alt program dintr-o altă zonă
20
12:47:15
poate fi executat; bineînţeles este necesar un procesor de intrare-ieşire autonom (canal
sau ADM).
8.3.2.2. Partiţionarea variabilă

Într-un sistem cu partiţionare variabilă împărţirea în zone nu este fixată odată


pentru totdeauna, ci este redefinită la terminarea execuţiei unui program, spaţiul de
memorie eliberat fiind repartizat altor programe. Drept consecinţă, încărcarea unui
program (fixarea adreselor) poate fi făcută în ultimul moment, doar atunci când
spaţiul respectiv îi este atribuit.

Un program, odată încărcat în memorie, rămâne aici până la terminarea execuţiei


sale: nu este posibilă reamplasarea dinamică.

Multiprogramarea permite menţinerea unităţii centrale în stare activă pentru


perioada încărcării programelor sau operaţiilor de intrare-ieşire.

Acest mod de funcţionare este adaptat tratării pe loturi pe un calculator, care nu


dispune de un mecanism de reamplasare dinamică.

01.09.20
20 261
12:47:15
8.4.1. Mecanisme de reamplasare dinamică

Alocarea dinamică a memoriei, divizate în zone de capacităţi oarecare cere utilizarea unor
mecanisme de reamplasare dinamică a acestor zone:

Registre de bază. Amplasarea în memoria fizică a unui singur segment este definită de o
pereche de registre, numite registrul de bază şi registrul limită. Registrul de bază RB
conţine adresa fizică a originii segmentului; registrul limită RL joacă rol de protecţie,
interzicând accesul accidental la locaţiuni în afara segmentului. Pentru o adresă virtuală
(RB, RL, d), la fiecare accesare este efectuat următorul calcul al adresei:

a := RB+d;
if a ≤ RL then
adr.fiz.:= a
else
<eroare> - deviere tratată de sistem
endif

01.09.20
20 262
12:47:15
Segmentare.
Segmentarea poate fi considerată o extensie a adresării cu ajutorul registrelor de bază, care
evită problemele realocării acestor registre, atunci când este necesară schimbarea
segmentului. Fiecărui segment îi este asociat un descriptor, care conţine printre altele,
adresa sa de origine şi capacitatea; descriptorii sunt aranjaţi într-un tabel, desemnat de un
registru special. Calculul adresei fizice corespunzătoare adresei segmentate (s, d) este
următorul:

desc := tab_desc[s];
if d < desc.capacitate then
adr.fiz.:= desc.orig+d
else
<eroare> - deviere tratată de sistem
endif

Orice accesare a memoriei cere o accesare suplimentară pentru citirea descriptorului. Pentru
sporirea eficienţei acceselor este folosit un dispozitiv de accelerare, constituit dintr-o
memorie asociativă de capacitate mică (de obicei, cu 8 sau 16 intrări), în care sunt păstraţi
descriptorii segmentelor la care au fost făcute cele mai recente referinţe, numerele acestor
segmente servesc drept chei de referinţă. La o accesare a memoriei, descriptorul
segmentului este căutat mai întâi în memoria asociativă, tabelul segmentelor fiind
consultat doar în cazul unui eşec.

Memoria asociativă funcţionează ca o memorie cache pentru descriptori, proprietatea de


01.09.20
localizare asigurând o rată înaltă a succeselor. 20
12:47:15
263
Mecanismele de reamplasare dinamică, care vor fi descrise în continuare, permit amplasarea
unui segment într-o zonă oarecare a memoriei principale şi deplasarea lui la un preţ minim
de gestiune (actualizarea descriptorului sau a registrelor bază-limită). Segmentele pot fi,
deci, utilizate ca unităţi de alocare a memoriei principale, care, la rândul lor, pot fi
comandate de zone de capacitate variabilă. Prezentăm mai jos metodele principale de
alocare şi implementarea lor în cadrul unui sistem de operare.

8.4.2. Algoritmi de alocare

Specificarea unui algoritm de alocare dinamică a segmentelor trebuie să răspundă la întrebările


generale, puse în 8.1.3. Încărcarea se face de obicei la cerere din cauza costului ridicat al
spaţiului şi timpilor de execuţie, datorat unei preîncărcări eronate. Rămâne de rezolvat
problema amplasării (alegerii unei zone libere) şi cea a reamplasării (alegerea zonelor, care
vor fi eliberate, dacă nici una din zonele libere nu convin).

8.4.2.1. Amplasarea şi reamplasarea segmentelor

Algoritmii sunt clasificaţi conform modului de reprezentare a zonelor libere. Cel mai frecvent
sunt utilizate următoarele trei metode:
• Înlănţuirea zonelor libere într-o listă,
• Divizarea blocurilor (“buddy systems”),
• Zone de capacităţi predefinite.

01.09.20
20 264
12:47:15
Zone libere înlănţuite

Algoritmii cei mai frecvenţi utilizează înlănţuirea.


Fiecărei zone libere îi este asociat un descriptor,
care conţine adresa de origine, capacitatea şi
legăturile de înlănţuire. Acest descriptor este
plasat chiar în zona propriu-zisă (fig.8.7).

Fie că este necesar să se găsească o zonă de


capacitatea t. Va fi consultată lista zonelor libere;
dacă notăm prin z zona curentă, criteriile posibile
de alegere pot fi: capacitate legătură
Prima zonă liberă (“first fit”). Va fi aleasă prima
zonă z care verifică proprietate capacitate(z) ≥ t.
În acest caz se urmăreşte scopul accelerării căutării. Fig.8.7. Reprezentarea zonelor libere
Lista este circulară şi căutarea pleacă de la ultima
înlănţuite
zonă alocată, pentru a se evita concentrarea de zone foarte mici în topul listei.

Ajustarea cea mai bună (“best fit”). Se va alege zona z, care va minimiza valoarea reziduului
(zona care rămâne liberă după alocare); altfel, vom alege z pentru care capacitate(z) – t
este minimă, ceea ce impune parcurgerea întregii liste sau ordonarea listei conform
capacităţilor zonelor. Scopul urmărit în acest caz este ameliorarea utilizării globale a
memoriei, existând pericolul apariţiei unor zone mici, puţin utilizabile.
01.09.20
Reziduul cel mai mare (“worst fit”). Va fi aleasă zona z pentru care
20
12:47:15
capacitate(z)
265 – t este
maximă. Se încearcă în acest mod să se lupte cu problemele metodei precedente.
În toate cazurile, un bloc de capacitatea t este amplasat în zona z; reziduul, dacă
există, înlocuieşte zona iniţială şi descriptorii sunt actualizaţi. În scopul diminuării
numărului total de zone adesea este fixată o limită inferioară a capacităţii
reziduului.

Atunci când o zonă este eliberată, ea este reinserată în listă şi fuzionată, dacă există
spaţiu, cu zona sau zonele vecine. Această fuzionare este facilitată, dacă zonele
sunt dublu înlănţuite şi ordonate în ordinea de creştere a adreselor.

Cercetările numeroase, efectuate asupra acestor algoritmi arată, că alegerea între “first
fit” şi “best fit” depinde de caracteristicile cererii, “first fit” fiind mai rapid, dacă
dispersia capacităţilor cerute este mare, rata de utilizare a memoriei fiind
aproximativ aceeaşi.

Măsurările făcute pentru sistemele cu timp partajat au arătat, că o majoritate foarte


mare de cereri, sunt legate de un număr mic de capacităţi, în general, scăzute.
Această remarcă explică interesul pentru doi algoritmi, prezentaţi mai departe

01.09.20
20 266
12:47:15
Alocare prin divizare (“buddy systems”)

În metoda alocării prin divizare capacităţile zonelor sunt cuantificate: ele sunt exprimate în
multiplii unei oarecare unităţi de alocare şi capacităţile permise sunt definite de o relaţie
de recurenţă. De obicei sunt utilizate două sisteme:
sistemul binar (1, 2, 4, 8,...), Si+1 = 2Si,
Fibonacci (1, 2, 3, 5, 13,...) Si+1 = Si+ Si-1.

Atunci când lipsesc blocuri de capacitatea Si,


B1 B2 B3 B4
un bloc de capacitatea Si+1 este divizat,
conform relaţiei de recurenţă. De exemplu,
în sistemul binar divizarea unui bloc de
capacitatea 8 creează două blocuri de capacitate 4; B1 B3 B4
în caz general, divizarea unui bloc de capacitatea (după eliberarea lui B2
Si+1 creează două blocuri de capacitatea Si.
În sistemul Fibonacci, divizarea unui bloc de B1 B4
capacitatea Si+1 creează un bloc de capacitate (după eliberarea lui B3
Si şi unul Si-1. Algoritmul este aplicat în mod recursiv,
dacă nu există un bloc liber de capacitatea Si+1.
Fig.8.8. Alocarea memoriei prin divizarea binară a
Putem considera, că orice bloc de capacitatea s>1 este concatenarea ablocurilor
două blocuri în care el
poate fi divizat; aceste blocuri sunt numite “companioni” (în engleză “buddies”). Adresele
de origine a blocurilor sunt definite din momentul în care este cunoscută amplasarea zonei
libere iniţiale (fig.8.8). 01.09.20
20 267
12:47:15
Rezerve de blocuri de capacitate predefinită

Atunci când caracteristicile cererilor sunt bine cunoscute şi marea majoritate a cererilor vizează
o mulţime de capacitate bine definită, este recomandat un algoritm ad-hoc.

De exemplu, măsurările efectuate pentru sistemul IBM VM/370 au arătat că aproximativ 95%
din cereri aparţin unei mulţimi de 10 lungimi particulare. Alocatorul utilizează 10 zone,
fiecare având una din lungimi, evitându-se astfel parcurgerea înlănţuirilor pentru
majoritatea cazurilor.

Un algoritm “first fit” tratează cazul cererilor diferite de cele 10 cereri tip. Memoria este periodic
reorganizată pentru realimentarea zonelor.

Pentru orice algoritm, mai devreme sau mai târziu spaţiul liber poate deveni insuficient. Pot fi
recomandate mai multe remedii:

De ex. se va reorganiza în totalitate memoria prin defragmentare, deplasând blocurile ocupate


astfel ca ele să devină adiacente. Spaţiul liber obţinut devine de asemenea contiguu.
Deplasarea informaţiilor în memorie este o operaţie de lungă durată, costul fiind
proporţional volumului de informaţii deplasat.

Dacă unele din blocurile alocate au devenit inaccesibile, acestea vor fi recuperate prin tehnici
speciale de “înlăturare a fărămiturilor”.
01.09.20
20 268
12:47:15
8.4.2.2. Utilizarea algoritmilor de alocare

Într-un sistem de operare algoritmii liber liber


liber
de alocare a memoriei sunt utilizaţi
în două maniere: Liber
Liber
• De către sistemul de operare la liber
alocarea memoriei pentru lucrări, Bază Lungime
atunci când sunt create procese
sau când sunt formate zone-tampon Lucrări
Lucrări
de intrare-ieşire, etc. Sistem Sistem
rezident rezident
• De către utilizatori: sistemul pune Bază Limită
la dispoziţie, sub forma unui apel
după terminarea T2
supervizor, primitivele cerere memorie
şi eliberare memorie. Aceste primitive Fig.8.9. Alocarea memoriei
sunt utilizate, de exemplu, de compilatoare lucrărilor
pentru gestiunea variabilelor dinamice.

Într-un sistem cu partiţionare variabilă şi reamplasare dinamică, o zonă de memorie este


alocată de către sistem pentru a duce evidenţa fiecărei lucrări. În conformitate cu modul de
adresare utilizat, un cuplu de registre bază-limită sau o intrare a tabelului segmentelor
sunt asociate lucrării.

În cazul registrelor, valoarea lor va face parte din contextul01.09.20


lucrării şi serveşte la reîncărcarea
registrelor bază-limită atunci când lucrarea este activată (fig.8.9).
20
12:47:15
269
La unele calculatoare (de exemplu, DEC PDP-10), zonele cu programe (care nu pot fi modificate)
şi cu date erau separate pentru fiecare lucrare cu ajutorul unui registru de bază distinct
pentru fiecare zonă. Aceasta permitea să fie redusă lungimea zonelor alocate şi cantitatea
informaţiilor transferate (deoarece zonele cu programe nu trebuie salvate), şi dă
posibilitatea partajării programelor între mai multe lucrări.

Unele sisteme (de exemplu, CDC, Univac) la terminarea fiecărei lucrări efectuau o
defragmentare a memoriei pentru a păstra un spaţiu liber unic; imaginile registrelor bază-
limită sau tabelul segmentelor trebuie reînnoite pentru lucrările deplasate (fig.8.10).

liber

liber

Liber

Lucrări

Sistem Sistem
rezident rezident
Bază Limită

după terminarea T2

Fig.8.10. Alocarea memoriei lucrărilor cu


defragmentare 01.09.20
20 270
12:47:15
8.4.2.3. Concluzii

Concluzionând această scurtă trecere în revistă a metodelor de alocare a memoriei pe


zone insistăm asupra faptului, că nu există metode optimale, oricare ar fi criteriul
de optimalitate ales (utilizarea memoriei, timpi de execuţie, etc.), pentru toate
situaţiile şi este necesar să se cunoască, măcar în linii generale, caracteristicile
cererilor înaintea alegerii unui algoritm.

Limitele metodei alocării pe zone rezultă din restricţia contiguităţii zonelor alocate.
Drept rezultat, amplasamentele libere nu sunt resurse banalizate deoarece, un
segment logic nu poate fi încărcat în două zone libere, care nu sunt vecine chiar
dacă spaţiul total este suficient. Reorganizarea memoriei rămâne o operaţie prea
costisitoare pentru a putea fi practicată frecvent.

Ideea, care a condus la introducerea paginaţiei, este de a banaliza resursa memorie,


alocând-o prin unităţi de lungime fixă şi nu obligator contigue. Rămâne doar să
rezolvăm problema adresării (este necesar echivalentul registrului de bază pentru
fiecare unitate de alocare) şi să găsim un compromis în alegerea lungimii acestei
unităţi.

01.09.20
20 271
12:47:15
8.5. Principiile şi mecanismele de bază ale paginaţiei
O memorie virtuală paginată este divizată în blocuri de lungime fixă, sau pagini, care servesc
drept unităţi de alocare. Memoria fizică la fel este divizată în blocuri de aceeaşi lungime,
numite pagini de memorie fizică. Vom prezenta mai jos mecanismele de paginaţie a unei
memorii virtuale liniare şi a unei memorii virtuale segmentate.

8.5.1. Paginarea unei memorii liniare


8.5.1.1. Paginare simplă
npf
Figura 8.11 reprezintă schema generală a unei Funcţie de
paginare
memorii virtuale paginate. Rolul dreptunghiului
marcat “funcţie de paginare” este de a stabili o pagină lipsă
corespondenţă între adresele paginilor memoriei
virtuale npv şi adresele paginilor memoriei fizice
npf, astfel încât o pagină virtuală să fie pusă npv
într-o pagină fizică oarecare. Paginile fizice devin
Memorie virtuală Memorie fizică
resurse banalizate gestiunea cărora este mult mai
simplă decât gestiunea zonelor de lungime variabilă.
Fig.8.11. Memorie virtuală paginată
Fiind dat numărul unei pagini virtuale npv, funcţia
de paginare permite să se determine, dacă această pagină este deja în memoria fizică şi, dacă
da, să se găsească numărul paginii fizice npf, care o conţine. Pentru sporirea eficienţei
această funcţie poate fi realizată printr-un mecanism hardware.
01.09.20
20 272
12:47:15
1) Memorie asociativă. O memorie asociativă, care are câte o intrare pentru fiecare pagină
fizică, conţine pentru fiecare intrare numărul paginii virtuale, care este amplasată în pagina
fizică respectivă. Acest principiu a fost utilizat în primul calculator cu paginaţie (Atlas), care
avea 32 pagini fizice (fig.8.12, a). Preţul foarte mare al acestei metode a defavorizat
extinderea principiului pentru memorii de capacitate mai mare. Totuşi, ideea utilizării unor
mici memorii asociative a fost preluată în calitate de mecanism de accelerare.

2) Registre topografice. O memorie adresă virtuală adresă virtuală


topografică este un ansamblu de npv npv
registre, indexate cu numărul
bit de prezenţă
paginii. Fiecare registru conţine
prezent
un indicator de prezenţă (1 bit)
şi un număr de pagină fizică,
care este semnificativ doar dacă
bitul este pus în 1 (fig.8.12, b). npf dep
npv npf npf
Calculatorul XDS Sigma 7 npf npv
adresă fizică
adresă fizică
(cunoscut de asemenea sub
denumirea CII 10070) ilustrează Npf-1 Npv-1
această tehnică cu p=8 şi l=9 pagină lipsă (în pagină lipsă
(256 pagini de 512 cuvinte). caz de eşec) (dacă prezent=0)
Memoria topografică a îmbunătăţit (a) memorie asociativă (b) registre topografice
cu doar 10% timpul de acces la
memorie, dacă nu există pagini lipsă. Fig.8.12. Memorie virtuală paginată
01.09.20
20 273
12:47:15
1) Tabele de pagini în memorie. Necesitatea unei memorii virtuale de capacitate mare (cu 24
sau chiar 32 biţi de adresă) face memoria topografică prea scumpă. Realizarea cea mai
curentă pentru funcţia de paginare utilizează un tabel de pagini în memorie, indexat de un
număr de pagină virtuală (fig.8.13).
Intrarea cu numărul npv conţine adresă virtuală
următoarele informaţii: npv
un număr de pagină fizică npf
memorie asociativă
un indicator de prezenţă prezent (1 bit) Registrul bază al tabelului
un indicator de modificare modif (1 bit) npv npf
succes

modul autorizat de acces (protecţia) prot.


eşec
În timpul unei accesări a memoriei prezent
corespondenţa dintre adresa virtuală
şi cea fizică este stabilită astfel: prezent=1
adr.virt := (npv, dep); npv prot npf npf
adresă fizică
if prezent[npv]=1 then prez. în mem. prezent=0 Tabel de pagini
adr.fiz := (npf[npv], dep)
else pagina nu este în memorie pagină absentă

<tratarea evenimentului pagină lipsă> Fig.8.13. Organizarea unui tabel de pagini


endif

Dacă pagina este prezentă:


modif[np] indică dacă pagina a fost modificată în timpul cât s-a aflat în memorie; această
informaţie este utilizată de algoritmii de reamplasare,01.09.20
prot[np] indică drepturile de acces la pagină; această informaţie 20 este utilizată
12:47:15
274 de mecanismele
de protecţie: o accesare neautorizată provoacă o deviere de tip violarea drepturilor de
acces.
8.5.1.2. Paginare la două niveluri
Tendinţa sporirii capacităţii memoriei virtuale aduce la apariţia problemei creşterii volumului
tabelelor de pagini, păstrate în memoria fizică. Paginarea în două niveluri vizează
soluţionarea acestei probleme.
În această schemă,
adresă virtuală nhip
memoria virtuală este npv
memorie asociativă
divizată în hiperpagini,
care la rândul lor sunt Reg.bază
împărţite în pagini. O
nhip npv
adresă virtuală este de eroare de
Tabel de
forma (nhip, npv, dep).
adresare
hiperpagini
Numărul nhip al hiperpaginii
permite accesul la un tabel prezent

de hiperpagini, in care fiecare Tabel de hiperpagini npf


intrare conţine un pointer la
adresă fizică
tabelul de pagini ale hiperpaginii, (prezent=0)
pagină lipsă
care este limitat doar la paginile Tabelul paginilor
efectiv utilizate. Un câmp hiperpaginii nhip

“lungime” permite controlul Fig.8.14. Paginaţie la două nivele


acestei restricţii.
Tabelele de pagini sunt utilizate ca şi în paginaţia simplă (fig.8.14). O memorie asociativă, în
care sunt păstrate cele mai recente triplete (nhip, npv, npf) accelerează consultarea.

01.09.20 al hiperpaginii i-1 are drept


Notăm că memoria virtuală rămâne liniară: ultimul amplasament
succesor primul amplasament al hiperpaginii i. Din acest motiv,
20
12:47:15
prin
275abuz de limbaj,
această schemă este adesea numită “segmentare”.
Mecanismul de deviere “pagină lipsă”

În afara traducerii propriu-zise a adreselor (corespondenţa npv – npf), mecanismul de accesare a


unei memorii paginate realizează următoarele operaţii:
actualizarea bitului de scriere şi a bitului de utilizare, dacă aceştia există,
detectarea lipsei paginii necesare (prezent[npv] = 0), care provoacă o deviere.

Programul de tratare a devierii “pagină lipsă” trebuie:


a) să găsească în memoria secundară pagina lipsă,
b) să găsească în memoria principală o pagină fizică liberă; dacă aceasta nu există, va trebui
eliberată una, eliminând din memoria principală în cea secundară pagina virtuală pe care o
conţine,
c) să încarce pagina virtuală necesară în pagina fizică.

Etapa a) impune să avem pentru fiecare memorie virtuală o descriere a implantării. Forma cea
mai simplă a descrierii este un tabel care indică adresa în memoria secundară a fiecărei
pagini virtuale. O memorie segmentată conţine un astfel de tabel pentru fiecare segment.

O altă posibilitate de descriere combină memoria virtuală şi fişierele: unei zone a memoriei
virtuale i se asociază conţinutul unuia sau a mai multor fişiere. Localizarea unei pagini
virtuale în memoria secundară este, în acest caz determinată consultând tabelul de
implantare a fişierului.

Etapa b) implementează un algoritm de reamplasare. Ea implică


01.09.20
păstrarea unui tabel de ocupare
a memoriei fizice, care indică pentru fiecare pagină fizică20ocupată pagina virtuală, care o
276
conţine şi alte informaţii suplimentare (protecţia, partajarea, etc.).
12:47:15
Partajarea şi protecţia informaţiei

Partajarea informaţiilor între mai multe memorii virtuale generează apariţia următoarelor trei
probleme:
• notarea: cum vor fi adresate într-un mod uniform informaţiile partajate,
• partajarea fizică: cum să se garanteze că informaţiile partajate există într-un singur exemplar,
• protecţia: cum să se garanteze respectarea regulilor de acces la informaţiile partajate.

1) Notarea informaţiilor partajate


Vom face deosebire între o memorie virtuală liniară şi una segmentată. Segmentarea pare o
soluţie simplă pentru problema partajării: segmentul constituie unitatea de partajare,
numele segmentului partajat ar putea fi el însăşi partajat sau ales independent pentru
fiecare proces.

În cazul unei memorii virtuale liniare numele unui obiect este adresa sa virtuală. Pot fi două
cazuri distincte, în dependenţă de prezenţa sau lipsa unui mecanism de reamplasare în
memoria virtuală.
• Dacă da (cazul unei memorii virtuale cu registre de bază), un obiect partajat poate
fi amplasat la adrese diferite pentru fiecare memorie virtuală, deoarece registrele
de bază sunt proprii fiecărei memorii.
• Dacă nu (cazul cel mai frecvent), încărcarea unui obiect partajat fixează în mod
definitiv amplasarea sa, care trebuie să fie aceeaşi în toate memoriile virtuale. Este
necesar, deci, să fie rezervate în fiecare memorie virtuală adrese fixe, definite prin
convenţie pentru fiecare obiect partajat. Acesta 01.09.20
este cazul componentelor
sistemului de operare, partajate de către toţi utilizatorii.
20
12:47:15
277
Protecţia informaţiilor partajate

Dacă unitatea de partajare este pagina, unei pagini partajate îi pot fi atribuite drepturi de
acces distincte pentru fiecare memorie virtuală în care aceasta figurează. Aceste
drepturi sunt specificate la intrarea respectivă a fiecărui tabel de pagini.

Dacă unitatea de partajare este segmentul, protecţia selectivă este aplicată întregului
segment. Drepturile de accesare a unui segment de către un proces figurează în tabelul
de segmente ale procesului.

Dacă sunt specificate drepturi individuale de accesare a paginilor segmentului, acestea sunt
prezente în tabelul de pagini partajate de către procesele utilizatoare şi sunt, deci,
partajate de către toate aceste procese. Ele trebuie să fie în acest caz compatibile cu
drepturile globale, asociate segmentului.

Cazul hiperpaginilor este identic cazului segmentelor.

01.09.20
20 278
12:47:15
Gestiunea memoriei virtuale paginate
Parametrii unei discipline de alocare

Disciplinele de alocare a unei memorii paginate pot fi clasificate în conformitate cu mai multe
criterii. Vom presupune că sistemul este multiprogramat, fiecare dintre procese
posedând memorie virtuală proprie.

1) Partiţie fixă sau variabilă


În cazul disciplinei de alocare cu partiţie fixă un număr fix de pagini fizice sunt atribuite fiecărui proces;
notăm că acest număr este constant doar pentru perioadele în care numărul proceselor
multiprogramate este el însuşi constant. Pentru o disciplină cu partiţie variabilă, numărul de pagini
fizice, atribuite fiecărui proces variază în timp. Paginile fizice fiind banalizate, anume numărul lor (şi
nu identitatea) este un parametru semnificativ.

2) Paginare la cerere sau preîncărcare


Paginaţia la cerere a fost definită în 8.2.1.2: o pagină este încărcată în memorie drept rezultat a unei
referinţe, care conduce la evenimentul pagină lipsă. Dacă o pagină este încărcată în avans, înainte de
orice referire la o informaţie, care se conţine aici, se spune că are loc o preîncărcare.

3) Reacoperire locală sau globală


Dacă o pagină virtuală este încărcată într-o pagină fizică ocupată are loc o înlocuire a paginii (pagina
înlocuită este numită “victima”). Algoritmul de reacoperire este zis local sau global conform
principiului de alegere a victimei – dintre paginile alocate procesului care provoacă înlocuirea sau din
mulţimea tuturor paginilor, prezente în memorie. 01.09.20
20 279
12:47:15
Criterii pentru compararea algoritmilor de reacoperire a paginilor

1) Pagini “curate” sau “murdare”

Este mai puţin costisitor să fie reamplasată o pagină, care nu a fost modificată în toată
perioada încărcării sale (pagină “curată”), decât una care a suferit modificări (pagină
“murdară”). O pagină curată posedă o copie în memoria secundară şi nu este necesar să
fie salvată. Indicatorul modif[p], întreţinut în mod automat, permite aplicarea acestui
criteriu.

2) Pagini partajate

Este preferabil ca o pagină, utilizată de un singur utilizator să fie înlocuită cu o pagină


partajată între mai multe procese.

3) Pagini cu statut special

În unele cazuri este de dorit să se acorde temporar unei pagini un statut special, care ar
proteja-o de înlocuire. Acesta este cazul paginilor utilizate ca bufere de intrare-ieşire pe
durata transferului.

01.09.20
20 280
12:47:15
Descrierea algoritmilor de reamplasare

Doi algoritmi, care descriu două cazuri extreme: algoritmul optimal, care presupune
cunoaşterea totală a viitorului comportament al programului şi algoritmul „neutru”, care
nu utilizează nici un fel de informaţii iniţiale.

• Algoritmul optimal (MIN)

Pentru un lanţ de referinţe dat poate fi arătat, că algoritmul următor minimizează numărul
total de pagini lipsă: atunci când o pagină este lipsă drept victimă va fi aleasă o pagină,
care nu va fi obiectul unei referinţe ulterioare sau, dacă nu este posibil, pagina care va fi
obiectul celei mai târzii referinţe. Acest algoritm presupune cunoaşterea mulţimii, care
formează lanţul de referinţe, din care motiv este irealizabil în timp real. Permite
evaluarea la limită a algoritmilor (cazul cel mai favorabil, strategia optimistă).

2) Alegere aleatoare

Victima este aleasă la întâmplare (repartiţie uniformă) dintre mulţimea paginilor, prezente în
memorie. Acest algoritm nu ţine cont de comportamentul observat sau previzibil al
programului (cazul cel mai puţin favorabil, strategia pesimistă).

01.09.20
20 281
12:47:15
Descrierea algoritmilor de reamplasare

Alţi doi algoritmi situaţi undeva la mijloc:

3) Ordine cronologică de încărcare (FIFO - PSPS)

Victimă este pagina care a fost încărcată cu cel mai mult timp în urmă. Principalul avantaj
este simplicitatea realizării: este suficient să se păstreze într-un fir „prim sosit – prim servit”
numerele paginilor fizice în care sunt încărcate paginile logice succesive.

4) Ordine cronologică de utilizare (LRU sau „Least recently Used”)

Acest algoritm încearcă să aproximeze algoritmul optimal, utilizând proprietatea de


localizare. Principiul folosit poate fi explicat în felul următor: deoarece paginile utilizate
recent posedă o probabilitate mai mare de a fi utilizate într-un viitor apropiat, o pagină
neutilizată timp îndelungat are o probabilitate mică de a fi folosită. Reieşind din acest
considerent, algoritmul alege drept victimă pagina, care a fost obiectul unei referiri cu cel mai
mult timp în urmă.

Realizarea algoritmului impune ordonarea paginilor fizice conform timpului ultimei referiri a paginii pe care
le conţin. Pentru aceasta, fiecărei pagini fizice i se va asocia o informaţie, care va fi pusă la zi la fiecare
referire. Aceasta poate fi timpul când a avut loc referirea. Mai puţin costisitor poate fi utlizarea unui contor
al referirilor. Necesitatea de a pune periodic contoarele în zero (atunci când acestea ating capacitatea
01.09.20
maximă) a condus la faptul că această soluţie a fost utilizată doar pentru 20 instalaţii
282experimentale.
12:47:15
„Algoritmul celei de-a doua şanse” sau FINUFO („First In Not Used, First Out”)

Este o aproximare (foarte „brutală”) a LRU.


Fiecărei pagini fizice este asociat un bit de utilizare U, pus în 1 atunci când are loc o referire a
paginii logice pe care o conţine.

Paginile fizice sunt ordonate într-un fir circular şi un pointer ptr indică ultima pagină fizică
încărcată. Algoritmul poate fi descris după cum urmează:
ptr := următorul(ptr);
while U[ptr]  0 do
U[ptr] = 0;
ptr := următorul(ptr);
endwhile;
victima := ptr;

Pointerul se deplasează până la prima pagină fizică cu bitul U zero, iar bitul U egal cu 1 al
paginilor întâlnite în drum este pus în 0.

Acest algoritm mai este numit algoritmul „ceasului” („Clock”), deplasarea pointerului fiind
asemănată cu cea a acelor de ceasornic.

Punerea în 1 a bitului U atunci când are loc o referire poate fi realizată cu ajutorul unui
mecanism hardware sau software. 01.09.20
20 283
12:47:15
Algoritmi cu partiţie variabilă. Reglarea şarjei
Rezultatele prezentate în continuare arată, că pare a fi preferabil să
se încerce alocarea unui volum de memorie bine adaptat
comportamentului fiecărui program.

Aceasta poate fi realizat în două moduri:


utilizând un algoritm cu partiţie variabilă,
utilizând un algoritm de reamplasare globală, ceea ce ar însemna să
aplicăm mulţimii programelor prezente unul dintre algoritmii studiaţi
pentru partiţiile fixe.

În ambele cazuri trebuie să se definească politica, care va fi aplicată


în caz de suprasolicitare, adică atunci când cererea de memorie
devine excesivă şi conduce la o degradare a performanţelor. Anume
din această cauză vom începe cu studierea comportamentului unui
sistem în condiţii extreme. Vom prezenta în continuare algoritmii cu
partiţie variabilă bazaţi pe măsurări locale a comportamentului
programelor, apoi algoritmii de reglare, care01.09.20
utilizează criterii
globale. 20
12:47:15
284
Instabilitatea şi thrashing-ul unui sistem cu multiprogramare
Pornind de la un anumit număr de utilizatori interactivi poate apărea o
degradare brutală a performanţelor: thrashing - căderea bruscă a ratei de
utilizare a procesorului şi o creştere puternică a schimbului de pagini.
Timpul de răspuns atinge valori inacceptabile.
Explicaţie. Considerăm un sistem cu memorie paginată, multiprogramat pentru o
mulţime de procese fiecare dintre care corespunde unui utilizator interactiv.
Memoria fizică este partajată în mod echitabil între procese cu comportament în
medie identic. Această partajare este realizată de un algoritm cu reamplasare
globală. Începând cu un anumit număr de procese numărul mediu de pagini fizice
alocate fiecărui proces cade până sub nivelul corespunzător „duratei de viaţă”.
Probabilitatea globală a evenimentului pagină lipsă, invers proporţională duratei de
viaţă, creşte extrem de rapid odată cu creşterea numărului de procese. Dacă
caracteristicile resurselor tehnice şi ale şarjei sunt fixate, gradul de multiprogramare
al sistemului devine un parametru determinant.
Două posibilităţi de ajustare dinamică a acestui parametru pentru evitarea thrashing-ului:
implicit, asigurând fiecărui proces prezent în memorie un număr anume de pagini fizice,
determinat de comportamentul observat al procesului: acesta este obiectul algoritmilor
de reamplasare cu partiţii variabile,
explicit, intervenind direct asupra gradului de multiprogramare
01.09.20 pornind de la observaţii
globale asupra comportamentului sistemului: aceasta este reglarea şarjei.
20
12:47:15
285
Reglarea şarjei şi echilibrarea unei configuraţii
Reglarea globală a şarjei presupune modificarea gradului de multiprogramare
pentru menţinerea performanţelor sistemului în limite acceptabile. La şarjă joasă
sau moderată multiprogramarea sporeşte rata de utilizare a procesorului folosind
timpul mort, datorat unor blocaje sau aşteptări de pagini; la şarjă înaltă – invers.
Acest comportament sugerează existenţa unei valori optimale a gradului de
multiprogramare, care maximizează rata utilizării procesorului pentru o
configuraţie dată a resurselor tehnice şi un tip concret de şarjă. Un algoritm ideal
de reglare a şarjei trebuie să menţină gradul de multiprogramare în vecinătatea
acestei valori.

Au fost propuse două formulări echivalente pentru criteriul de optimalitate:


regula „celor 50%”: rata de utilizare a canalului de paginaţie este aproape de
0.5,
regula „genunchiului”: valoarea medie a duratei globale de viaţă este cea care
corespunde genunchiului curbei duratei de viaţă.

În practică, numărul de evenimente pagină lipsă este periodic măsurat şi această


valoare este comparată cu valori stabilite empiric. Atunci când valoarea maxim
admisibilă este depăşită, gradul de multiprogramare este diminuat cu 1.
01.09.20
20 286
12:47:15
Resurse tehnice de administrare a memoriei în procesoarele Intel

Memoria virtuală dă posibilitatea să considerăm lungimea maximă


admisibilă a unui program dependentă doar de capacitatea memoriei
secundare.
Flexibilitatea introdusă de memoria virtuală este convenabilă:
• producătorilor de memorii - pot propune dispozitive, care diferă doar prin configurarea
memoriei şi nivelul productivităţii,
• programatorilor - pot pune în şarja sistemului de operare manipularea şi păstrarea
componentelor programelor evitând scrierea programelor cu structuri sofisticate,
• utilizatorilor finali - pot utiliza şi elabora aplicaţii mari, fără a-şi face probleme, legate de
capacitatea memoriei centrale.
Memoria virtuală este realizată de SO, adesea o parte a funcţiilor acestuia
fiind realizate hard. Procesoarele Intel 80386, 80486 şi Pentium din
punct de vedere al administrării memoriei posedă mecanisme hard de
acelaşi tip, din care cauză mai departe se va utiliza termenul
“procesorul i386”; informaţia din paragraful dat este în egală măsură
valabilă pentru toate procesoarele Intel indicate mai sus.

01.09.20
20 287
12:47:15
Despre procesoarele i386
Procesorul i386 are două moduri de lucru:
• real - procesor 8086 accelerat, având un set de instrucţiuni de bază mai extins,
• protejat - poate utiliza toate mecanismele de organizare a memoriei pe 32 biţi, inclusiv mecanismele
de susţinere a memoriei virtuale şi mecanismele de comutare a lucrărilor. În afară de aceasta, în modul
protejat pentru fiecare lucrare procesorul i386 poate emula procesoarele 8086 şi 286, care se vor numi
în acest caz procesoare virtuale. În aşa fel, în regimul multitasking modul protejat procesorul i386
lucrează ca un set de procesoare virtuale cu memorie comună.

Regimul procesorului virtual i86, care este numit V86, susţine organizarea paginată a
memoriei şi multitaskingul. Din această cauză lucrările, care sunt executate în
modul V86 folosesc aceleaşi mijloace de protecţie reciprocă a lucrărilor şi a SO
de lucrările utilizatorului, ca şi lucrările, executate în mod protejat i386.

Comutarea procesorului i386 din modul real în protejat şi invers are loc prin simpla
executare a instrucţiunii MOV, care modifică bitul de mod în unul din registrele de
control ale procesorului.
Comutarea în modul V86 are loc analogic modificând valoarea unui indicator anume
într-un alt registru.
01.09.20
20 288
12:47:15
Despre procesoarele i386
Productivitate suficientă pentru elaborarea şi implementarea unor sisteme de calcul sofisticate.
În aceste sisteme problema principală constă în depistarea şi eliminarea în timp minim a
erorilor posibile, iar în cel mai pesimist caz – să se stabilească modalitatea de minimizare a
consecinţelor acestor erori. Sistemele de acest gen pot fi depanate în timp mai scurt, iar
fiabilitatea poate fi mai mare, atunci când sunt produse în serie şi procesorul impus să
controleze fiecare instrucţiune dacă respectă criteriului de protecţie.
Criteriul de protecţie utilizat depinde de aplicaţia concretă. Sistemele mai simple, de timp real,
de exemplu, în care toate momentele pot fi cercetate la etapa de elaborare şi
implementare, au un comportament relativ corect şi fără utilizarea mecanismelor speciale
de protecţie. Însă în condiţii de incertitudine, în lipsa unor informaţii preliminare, datorate
contextului aleator al domeniului, utilizarea mecanismelor speciale de protecţie este
obligatorie.
Procesoarele i386 permit soluţionarea acestor probleme prin:
• Partiţionarea spaţiilor de adrese ale aplicaţiilor,
• Utilizarea unor nivele de priorităţi (inele de protecţie, de la 0 la 3),
• Utilizarea unor instrucţiuni privilegiate,
• Clasificarea segmentelor pe tipuri (de exemplu, segmente de cod, segmente de date),
• Folosirea noţiunii de drepturi de acces la segmente şi pagini (RO, EO),
• Controlul graniţei unui segment.
Pentru păstrarea productivităţii maxime toate controalele protecţiei
01.09.20 sunt îndeplinite la executarea
20 289
unei instrucţiuni. 12:47:15
Mijloacele de susţinere a segmentării memoriei
Spaţiul fizic de adrese a procesorului i386 este de 4 Go (magistrala de adrese pe 32 de biţi).
Memoria fizică este liniară cu adrese de la 00000000 până la FFFFFFFF în cod hexazecimal.
Adresa virtuală, utilizată în program este reprezentată de perechea (nr. seg., depl). Deplasarea
este dată de câmpul respectiv al instrucţiunii, iar numărul segmentului – în unul din cele 6
registre de segment ale procesorului (CS, SS, DS, ES, FS şi GS), fiecare fiind de 16 biţi.
Mijloacele de segmentare formează nivelul superior al dispozitivului de administrare a memoriei
virtuale, iar dispozitivele de organizare a paginaţiei – nivelul inferior. Mijloacele de paginaţie
pot fi active sau dezactivate şi în dependenţă de aceasta se modifică sensul transformării
adresei virtuale, executate de mijloacele de segmentaţie.
Memoria virtuală segmentată este recomandată pentru sisteme nu prea mari pe 16 biţi în care
capacitatea segmentului nu este mai mare de 64 Ko. Pot fi utilizate segmente de 4 Go,
ceea ce dă posibilitatea organizării paginării acestora. Productivitatea înaltă în
administrarea memoriei virtuale este asigurată de folosirea unei memorii cash interne
pentru păstrarea informaţiilor virtual-fizic - tamponul de localizare a translatării, TLB -
conţine informaţii despre adresele a 32 de pagini, cel mai recent utilizate. Paginile memoriei
virtuale au capacitatea de 4 Ko, ceea ce înseamnă că TLB conţine la fiecare moment de
timp informaţii despre 128 Ko, permiţând cristalului transformarea adresei virtuale în
adresa fizică fără accesarea tabelului de pagini (98 - 99% cazuri de succes).
01.09.20
20 290
12:47:15
Dispozitivele de segmentare cu mijloacele de paginaţie dezactivate

Deplasarea pe 32 biţi determină


capacitatea unui segment virtual de
232 = 4 Go, iar numărul de segmente
este determinat de lungimea
câmpului, rezervat în registrul
segmentelor pentru numărul
segmentului.
Procesorul i386 susţine două tabele
de descriptori – global (Global
Descriptor Table, GDT) şi local (Local
Descriptor Table, LDT). Tabelul global
este destinat descrierii segmentelor
sistemului de operare şi segmentelor
interacţiunilor între lucrări, adică
segmentelor, care pot fi, în principiu,
folosite de toate procesele, iar tabelul
local este pentru segmentele unor
lucrări separate. Tabelul GDT este
unic, iar LDT trebuie să fie tot atâtea
câte lucrări sunt în sistem. Doar unul
din tabelele locale va fi activ la un
moment de timp dat. 01.09.20
20 291
12:47:15
În figura 8.22, a este
prezentată structura datelor în
registrul segmentelor. Această
structură se numeşte selector
deoarece este destinată pentru
alegerea descriptorului unui
segment din tabelul descriptorilor
segmentelor. Descriptorul
segmentului descrie toate
caracteristicile segmentului,
necesare pentru verificarea
corectitudinii accesării lui şi
localizării în spaţiul fizic de
adrese.
Selectorul conţine trei câmpuri
– câmpul pe 13 biţi al indicelui
(numărul segmentului) în tabelul
GDT şi tabelele LDT, câmpul pe 1
bit al indicatorului tipului tabelului
utilizat al descriptorilor şi câmpul
pe 2 biţi al drepturilor curente de
acces ale lucrării – CPL. Numărul
maximal de segmente globale şi
locale ale lucrării – câte 8K (213)
segmente de fiecare tip, în total
16 K. Luând în consideraţie
lungimea maximă a unui segment
– 4 Go – fiecare lucrare este
executată într-un spaţiu virtual de 01.09.20
20 292
adrese de 64 To (memoria 12:47:15
virtuală este organizată pe
segmente fără paginaţie).
Proiectarea spaţiului virtual pe spaţiul fizic de 4 Go
În momentul în care o lucrare trebuie să acceseze o locaţiune a memoriei fizice, pentru alegerea
descriptorului segmentului virtual este folosit selectorul, care se află în registrul respectiv al
segmentelor. Valoarea câmpului tipului tabelului indică care tabel trebuie utilizat – GDT sau LDT.
Pentru păstrarea tabelelor GDT şi LDT este folosită memoria operativă. Pentru ca procesorul să
poată găsi în memoria fizică tabelul GDT, adresa completă pe 32 biţi a acestuia plus lungimea lui
(câmp pe 16 biţi) sunt păstrate într-un registru special al procesorului GDTR. Fiecare descriptor
din tabelele GDT şi LDT are lungimea de 8 octeţi.
Pentru extragerea descriptorului din tabel, procesorul adună la adresa bază a tabelului GDT din
registrul GDTR valoarea din câmpul indicelui din registrul segmentelor, deplasată în stânga cu
trei ranguri, obţinând adresa liniară fizică a descriptorului necesar din memoria fizică.
Tabelul GDT este tot timpul prezent în memoria operativă, procesorul extrage descriptorul
necesar al segmentului de la această adresă şi-l pune într-un registru intern al procesorului.
Descriptorul segmentului virtual conţine câteva câmpuri, principalele fiind câmpul bazei – adresa
fizică bază pe 32 biţi a începutului segmentului, câmpul lungimii segmentului şi câmpul
drepturilor de acces la segment – DPL (Descriptor Privilege Level). Procesorul determină mai
întâi corectitudinea adresei, comparând deplasarea cu lungimea segmentului. Apoi sunt
controlate drepturile de acces ale lucrării la acest segment, comparând valorile câmpurilor CPL
ale selectorului şi DPL ale descriptorului segmentului.
În procesorul i386 este implementată metoda cunoscută şi sub denumirea inele de protecţie. Aici există patru
nivele a drepturilor de acces, iar obiectele unui nivel oarecare au acces
01.09.20la toate obiectele de acelaşi nivel sau
de nivele mai joase, dar nu pot accesa obiecte de nivele superioare. SO 20 poate utiliza
293 mecanismul nivelelor de
12:47:15
protecţie cum doreşte. Se presupune, că 0 va fi utilizat pentru nucleul sistemului de operare, 3 – pentru
aplicaţii, iar nivelele intermediare pentru utilitare şi subsistemele SO, cu priorităţi mai mici decât nucleul.
9. Elaborarea unui sistem de operare
9.1. Decompoziţia ierarhică şi maşini abstracte
9.1.1. Conceptul de descendenţă şi structuri cu nivele
9.1.2. Noţiunea de obiect
9.1.3. Interfeţe şi specificări
9.2. Organizarea unui sistem mono-utilizator
9.2.1. Specificările şi organizarea generală
9.2.1.1. Funcţiile sistemului. Limbajul de comandă
9.2.1.2. Decompoziţia sistemului. Interfeţe interne
9.2.2. Primitive de intrare-ieşire
9.2.2.1. Intrări-ieşiri pentru unitatea de disc
9.2.2.2. Introducere – extragere caractere
9.2.3. Sistemul de gestionare a fişierelor
9.2.3.1. Organizarea logică
9.2.3.2. Organizarea fizică
9.2.3.3. Operaţii cu fişierele
9.2.3.4. Intrări-ieşiri logice şi gestiunea fluxurilor
9.2.4. Interpretorul limbajului de comandă
9.2.4.1. Schema generală
9.2.4.2. Mediul de execuţie
9.2.4.3. Încărcarea unui program
9.2.4.4. Tratarea erorilor de execuţie
01.09.20
9.3. Partajarea unei maşini: maşini virtuale 20 294
12:47:15
9.4. Exemplu de elaborare a unui sistem de operare multitasking
Obiective:

1) Introducerea unor principii de structurare a sistemelor soft:


• decompoziţia ierarhică,
• nivele de abstractizare,
• obiecte şi interfeţe.
Interesul pentru aceste noţiuni depăşeşte cadrul strict al
softului de sistem. Totuşi, aceste concepte au o
importanţă particulară pentru SO dat fiind complexitatea
acestora, dimensiunile adesea foarte mari şi interacţiunile
caracteristice dintre software şi hardware.
2) Aplicarea acestor noţiuni la descrierea schemelor de
organizare şi funcţionare a unui SO foarte simplu
01.09.20
20 295
12:47:15
9.1. Decompoziţia ierarhică şi maşini abstracte
9.1.1. Conceptul de descendenţă şi structuri cu nivele
Abstractizare: reducerea unei probleme la aspectele sale esenţiale, concretizate prin
specificările unei maşini; alte aspecte fiind luate în consideraţie doar la momentul
realizării maşinii specificate. Specificarea unei maşini, din punctul de vedere al
utilizatorului, se reduce la specificarea interfeţei maşinii, adică a obiectelor şi
operaţiilor furnizate de această maşină.
Se va spune că maşina Mi utilizează maşina Mj sau că Mi depinde de Mj, dacă la
realizarea maşinii Mi este utilizată interfaţa furnizată de maşina Mj. Afirmând că Mi
depinde de Mj vom subînţelege că Mi depinde doar de interfaţa lui Mj şi nu de
detaliile realizării interne ale acesteia.

01.09.20
20 296
12:47:15
Această schemă poate fi generalizată: dacă vom admite că o maşină poate utiliza
primitive furnizate de orice maşină de nivel inferior vom obţine schema (b), iar dacă
unica restricţie impusă grafului de dependenţă este lipsa circuitelor - schema (c).
În practică, metoda conceptului de descendenţă nu este niciodată utilizată în mod
absolut: procesele conţin iteraţii, iar la definiţia unor maşini noi se va ţine cont de
experienţa celui care o elaborează ca şi de existenţa maşinilor deja realizate.
Rezultat: este imposibil de propus apriori specificaţii detaliate ale interfeţei:
elaborarea specificaţiilor finale se bazează pe experimentări cu prototipurile lor.
Indiferent de maniera prin care se ajunge la noţiunea de structură ierarhică,
aceasta prezintă o serie de avantaje:
•Independenţa conceperii: comportamentul unei maşini, pentru utilizatorii săi, este
totalmente descris de specificările interfeţei sale.
•Independenţa modificării: modificările unei maşini nu generează modificări pentru
maşinile care o utilizează, dacă specificările interfeţei rămân neschimbate.
•Independenţa realizării: interfaţa odată specificată, o maşină M poate fi realizată
independent de cele care o utilizează şi invers, interfaţa lui M fiind corect realizată,
maşinile care utilizează maşina M pot fi puse la punct independent
01.09.20
20 297
de M.
12:47:15
Noţiunea de obiect
Decompoziţia ierarhică în maşini abstracte nu acoperă toate aspectele structurării
sistemelor. În particular, pot apărea probleme atunci când unele situaţii sau
elemente trebuiesc create ori distruse în mod dinamic, sau când vrem să descriem
elemente, care posedă proprietăţi comune.
Pentru a facilita luarea în consideraţie a acestor aspecte este introdus instrumentul
de structurare obiect.
Un obiect este definit cu ajutorul următoarelor atribute:
• un nume, care permite desemnarea obiectului şi deosebirea lui de alte obiecte,
• o stare, care este definită în orice moment de timp şi poate evolua pe parcursul
timpului,
• o mulţime de operaţii, funcţii de acces sau metode, care permit:
- crearea şi distrugerea obiectelor,
- consultarea şi modificarea stării unui obiect,
- combinarea obiectelor.
Clasa permite gruparea obiectelor cu proprietăţi comune, fiind un instrument al
abstractizării. Unei clase îi sunt ataşate o mulţime de funcţii de acces (metode),
aplicabile tuturor reprezentanţilor clasei; fiecare obiect al clasei posedă un nume şi
o stare proprie. Orice obiect aparţine unei clase; atunci când un obiect este creat,
se va specifica numele şi starea sa iniţială; metodele asociate clasei sale sunt în
mod automat moştenite. Un obiect, odată creat, poate fi accesat cu ajutorul
01.09.20
funcţiilor de acces specificate de clasă. Programele acestor 20 funcţii
298 sunt, de obicei,
12:47:15
partajate între toate obiectele clasei, însă fiecare obiect mai conţine şi date proprii.
Interfeţe şi specificări

O interfaţă este asociată unei maşini abstracte sau unei clase de obiecte. Ea
conţine doar trei tipuri de informaţii, accesibile utilizatorului maşinii sau obiectului:
- structuri de date,
- proceduri (metode),
- o mulţime de reguli de utilizare a datelor şi a procedurilor.
Regulile de utilizare constituie un mod de întrebuinţare a structurilor de date şi
procedurilor. Ele exprimă restricţiile utilizării lor, şi pot lua diverse forme:
- restricţii de accesare a datelor (numai citire, de exemplu),
- restricţii, legate de ordinea de execuţie a procedurilor,
- restricţii, care afectează execuţia simultană a procedurilor sau accesarea
simultană a datelor.
Problema formulării specificărilor unei interfeţe nu are încă o soluţie generală
satisfăcătoare. Doar o parte a specificărilor poate fi exprimată in mod formal şi
există posibilitatea unor validări automate: acestea sunt specificările tipurilor
variabilelor şi a parametrilor procedurilor.

01.09.2020 12:47:15 299


9.2. Organizarea unui sistem mono-utilizator
Pentru a ilustra folosirea conceptului maşină ierarhică abstractă vom elabora un
sistem de operare redus la forma cea mai primitivă.
Trebuie proiectat un sistem minim, destinat să administreze un microcalculator
individual, folosit de un singur utilizator (CP/M de la Digital Research).

9.2.1. Specificările şi organizarea generală


Calculatorul administrat de sistemul nostru de operare constă din:
- un procesor,
- o memorie operativă
- echipamente periferice:
un terminal (display şi tastatură),
una sau două unităţi de dischetă,
o imprimantă.
Gestionarea perifericelor este asigurată de procesor (posibilitatea administrării prin
ADM este propusă ca exerciţiu).

300
01.09.2020 12:47:15
Limbajul de comandă
Sistemul trebuie să permită:
- salvarea şi păstrarea informaţiilor în fişiere pe dischetă,
- transferarea informaţiilor între fişiere şi periferice,
- elaborarea, depanarea, salvarea şi executarea programelor.
Structura SO va permite adaptarea simplă la diferite configuraţii de calculatoare,
în special, la diferite tipuri de memorie secundară şi echipamente periferice.
Interfaţa utilizatorului, oferită de către sistemul de operare, este definită de un
limbaj de comandă specificat astfel:
<comandă> ::=<nume comandă><listă parametri>
<listă parametri> ::=spaţiu|<listă parametri><parametru>
<parametru> ::=<nume fişier>
O comandă este introdusă de la tastatură şi executată imediat.
Un fişier este un set de informaţii desemnate printr-un nume şi manipulate cu
ajutorul unor funcţii de acces. Fişierele sunt păstrate în memoria secundară.
Programele şi datele utilizatorului se află în fişiere.
01.09.20
20 301
12:47:15
Comenzi predefinite

Un oarecare număr de comenzi de bază sunt predefinite în sistem. Orice program executabil,
creat de utilizator sub formă de fişier poate fi executat ca şi o comandă:
<nume comandă>::=<nume comandă predefinită>|<nume fişier executabil>
Cu titlu de exemplu, o listă de comenzi pentru crearea şi depanarea în limbajul de asamblare:
1) editare fsursă -- editarea programului sursă
să se asigure posibilitatea modificării unui fişier fsursă care conţine textul programului (sau să
se asigure posibilitatea creării lui, dacă acesta nu există) cu ajutorul unor comenzi interne,
definite de un editor interactiv, furnizat de sistem, detaliile de funcţionare ale căruia nu sunt
specificate aici.
2) asamblare fsursă fobiect -- asamblare
să se asambleze programul din fsursă şi să se plaseze codul obiect în fobiect.
3) fobiect fdate frezultat -- executare
să se execute programul conţinut în fişierul fobiect citind datele din fişierul fdate pasând
rezultatele în fişierul frezultat.
4) depanare -- depanare interactivă

01.09.20
20 302
12:47:15
9.2.1.2. Decompoziţia sistemului. Interfeţe interne

O primă versiune a SO poate fi realizată utilizând direct interfaţa definită de maşina fizică.
Vom arăta mai jos modul în care un sistem fizic monolit poate fi pas cu pas descompus
pentru a ajunge la subansambluri logic coerente.
Gestionarea fişierelor şi a fluxurilor
Izolăm componenta sistemului responsabilă de administrarea fişierelor. Pentru aceasta trebuie
să precizăm structura fişierelor şi să specificăm funcţiile de acces.
Presupunem că un fişier este organizat sub forma unei secvenţe de înregistrări de lungime
fixă. Citirea şi scrierea se va face în mod secvenţial: pentru fiecare fişier f este definit un
pointer ptr(f) de citire/scriere, o variabilă booleană sfr(f) şi un mod de acces (numai citire sau
citire/scriere). Funcţiile de acces sunt definite după cum urmează:

Deschiderea unui fişier permite să-l declarăm utilizabil şi să iniţializăm indicatorii.


deschide(f):
if vid(f) then
sfr(f):=true
else
ptr(f):=<pointer la prima înregistrare>;
sfr(f):=false
endif
01.09.20
Primitiva schimbare_mod permite fixarea modului de accesare
20 a fişierului (este
303
12:47:15
adesea inclusă în deschiderea fişierului).
Accesul la înregistrări
Se face prin intermediul a două primitive citire_secv şi sriere_secv:
citire_secv(f, dest): -- dest semnifică tamponul destinaţie
if sfr(f) then
<eroare> -- nu avem ce citi
else
dest:=<înregistrare desemnată de ptr(f)>
deplasare(f)
endif
deplasare(f) obligă ptr(f) să puncteze pe înregistrarea următoare a fişierului. Dacă ptr(f)
desemna ultima înregistrare el va rămâne neschimbat şi sfr(f) este pus în true.
scriere_secv(f, orig): -- orig semnifică zona-tampon origine
if mod(f) = numai citire then <eroare>
else
if sfr(f) then
<adaugă un amplsament la sfârşitul fişierului pentru o înregistrare>
deplasare(f)
endif;
<amplasamentul desemnat de ptr(f)>:=orig;
deplasare(f)
endif
Citirea şi scrierea se produc plecând de la poziţia curentă a lui ptr(f), actualizându-l.
închide(f) închide fişierul f presupus deschis, procedurile de citire sau scriere nu-i mai pot fi aplicate.
01.09.20
crează(f) permite crearea unui fişier cu numele f, care este iniţial vid şi20închis, 304
distruge(f) fişierul f este distrus, el nu mai poate fi identificat, informaţiile
12:47:15
pe care le conţine sunt pierdute.
SO pe două nivele

SO poate fi acuma descompus în două nivele: SGF, construit pe


maşina fizică MF şi interpretorul limbajului de comandă (maşina ILC),
care foloseşte funcţiile furnizate de interfaţa SGF.
Maşina ILC de asemenea utilizează direct maşina MF pentru citirea comenzilor de la tastatură,
administrarea display-ului şi imprimarea fişierelor. Daca se va solicita o structură strictă pe
nivele va fi necesar să includem administrarea operaţiilor de I-E în SGF.
Specificăm mai jos funcţiile care trebuiesc realizate.
Noţiunea de fişier este o realizare abstractă a schimburilor de informaţii cu memoria
secundară. Introducem un nivel echivalent de abstractizare pentru specificarea schimburilor de
informaţii cu alte periferice.
Definim pentru aceasta două "periferice logice" cu următoarele specificaţii ale interfeţei:
a) "terminalul logic", care constă dintr-un display şi o tastatură şi care oferă:
citire_linie(tampon)
O linie de simboluri de la tastatură va fi introdusă în tampon din memorie. Se presupune că
funcţii elementare de editare, cum ar fi vizualizarea unui simbol sau a unei linii, sunt furnizate.
afişare_linie(tampon)
Afişează pe ecran conţinutul unei linii de simboluri, plasată într-un tampon de memorie.
01.09.20
20 305
12:47:15
Imprimanta logică

b) "imprimanta logică", care oferă funcţia


imprimare_linie(tampon)
adică, să se imprime conţinutul unei linii plasate într-un tampon de memorie.

Primul octet al parametrului tampon al funcţiilor de mai sus specifică numărul de caractere din linia origine
sau destinaţie, care vor fi transferate.

Introducerea conceptului de periferice logice prezintă un dublu interes:


- în primul rând, este posibil să se pună la dispoziţia utilizatorului funcţii mai sofisticate şi mai
aproape de necesităţi, decât cele ale organelor fizice de intrare-ieşire,
- în al doilea rând, se permite înlocuirea unui periferic fizic cu altul, păstrând interfaţa utilizării.

Pentru a realiza ultima posibilitate vom specifica o funcţie


asociere(periferic_logic, periferic_fizic)
care permite modificarea asocierii, definită iniţial în mod implicit, perifericelor logice şi fizice, respectând
compatibilitatea funcţiilor (imprimanta logică va fi asociată unui dispozitiv care permite extragerea
caracterelor, etc.).

Noţiunea de periferic logic mai este întâlnită sub denumirea de flux de intrare-ieşire.

01.09.20
20 306
12:47:15
2) Realizarea operaţiilor de intrare-ieşire

Realizarea maşinii SGF, care administrează fişierele şi fluxurile, poate de asemenea fi simplificată dacă
avem la dispoziţie primitive de intrare-ieşire mai evoluate decât cele furnizate direct de maşina fizică.

Vom defini o nouă maşină, numită PIE (primitive intrări-ieşiri), cu următoarea interfaţă:
a) Schimburi cu discul. Un disc este organizat în piste şi sectoare, sectorul este unitatea de transfer,
iar o adresă de disc are forma (nr. suport, nr. pistă, nr. sector).

Interfaţa are trei funcţii:


alegere_suport(nr. suport): specifică suportul curent;
citire_sector(nr_pistă,nr_sect,destinaţie): transferă un sector de disc în memorie
scriere_sector(nr_pistă,nr_sect,origine): transferă un sector de memorie pe disc cu nr_pistă, nr_sect
semnificând numărul pistei şi a sectorului, iar destinaţie şi origine desemnează tampoane de
memorie de lungimea unui sector.

b) Schimburi cu alte periferice. Unitatea de transfer este un caracter. Vor fi definite trei funcţii:
citire_car(c) : citeşte un caracter de la tastatură (rezultatul c)
afişare_car(c) : afişază un caracter pe display (originea c)
imprimare_car(c) : imprimă un caracter la imprimantă (originea c)

Pentru a permite utilizarea asistată de SGF a acestor funcţii, ele sunt definite pentru periferice logice.
Accesarea perifericelor fizice este realizată printr-o simplă redirecţionare via un tabel de corespondenţă.
01.09.20
20 307
12:47:15
SO pe trei nivele

Realizarea sistemului de gestionare a fişierelor


este astfel descompusă în două probleme
mai simple:
- să se realizeze maşina SGF, care pune la
dispoziţie interfaţa descrisă în p. 1, folosind
funcţiile furnizate de interfaţa maşinii PIE,
descrise în p. 2,
- să se realizeze maşina PIE care foloseşte
doar maşina fizică MF.

Decompoziţia de mai sus permite constatarea avantajului principal al structurării pe nivele:


o modificare, chiar şi esenţială, a organizării interne a maşinilor PIE sau SGF nu antrenează nici un
fel de modificări ale nivelelor superioare, dacă interfaţa corespunzătoare rămâne neschimbată.

Această remarcă evidenţiază importanţa alegerii interfeţelor în cauză. De exemplu, interfaţa PIE trebuie să
permită simplificarea realizării maşinilor care o utilizează, rămânând ea însăşi relativ simplu de
realizat, ceea ce poate fi obţinut doar în mod iterativ, făcând în egală măsură apel la experienţă. În
cursul acestui proces iterativ interfeţele principale sunt elaborate progresiv până la varianta stabilă.
Costul modificaţiei unei interfeţe creşte odată cu creşterea numărului componentelor care o utilizează
şi este, ca rezultat, mai ridicat pentru interfeţele principale ale sistemului.
01.09.20
Interfaţa externă a sistemului, care este cea a ILC, este definită de limbajul
20 de 308
comandă. Interfeţele
interne (ale PIE şi SGF) sunt realizate prin apelări ale supervizorului.
12:47:15
9.2.2. Primitive de intrare-ieşire

Driverele dispozitivelor periferice urmează schema sincronă (v. 2.4.2.1). Vom descrie mai întâi
administrarea unei unităţi de disc, apoi intrările-ieşirile în mod caracter.

9.2.2.1. Intrări-ieşiri pentru unitatea de disc

Exemplul care urmează este pentru un disc cu un format particular, dischetă simplă densitate cu o singură
suprafaţă de lucru. Parametrizarea pentru formatare va fi examinată mai târziu. Discheta are 77 piste
de 27 sectoare; lungimea sectorului - 128 octeţi. Sectorul este unitatea de transfer a informaţiei.

Pentru accelerarea transferurilor secvenţiale acestea sunt realizate printr-o zonă de memorie-tampon. La o
operaţie de citire este recomandat să se citească o pistă întreagă, deoarece întârzierea introdusă de
căutarea pistei intervine o singură dată pentru toată mulţimea sectoarelor. Din această cauză vor fi
rezervate în permanenţă n zone-tampon de lungimea unei piste (27 sectoare de 128 caractere).
Valoarea lui n de ordinul câtorva unităţi va fi fixată la generarea sistemului.

Fie că este necesar să se citească un sector cu numărul nsect de pe pista np. Dacă unul din tampoane
conţine pista np, citirea se va face fără a accesa discheta, din sectorul respectiv al zonei-tampon. În
caz contrar, conţinutul pistei np va trebui încărcat în prealabil de pe dischetă în una din zonele-
tampon. Alegerea zonei-tampon va fi tratată mai departe.

01.09.20
20 309
12:47:15
Operaţia de scriere

Este mai complicată. Pentru a minimiza numărul de transferuri, un tampon este recopiat pe dischetă cât
mai târziu posibil. Atâta timp cât el este în memoria operativă, tamponul reflectă starea curentă a
sectoarelor pistei şi accesările succesive ale unui sector nu antrenează vre-o accesare a dischetei. Fie
că este necesar să scriem în sectorul nsect al pistei np:
- dacă pista np este prezentă într-un tampon, sectorul corespunzător este modificat şi operaţia se
termină aici, cu excepţia cazului "scriere imediată"**,
- dacă pista np nu este prezentă, ea trebuie în prealabil adusă într-un tampon pentru a ajunge la
situaţia din cazul precedent, cu excepţia situaţiei primei scrieri.

Un sector este copiat pe disc, în afara cazului de scriere imediată, în două situaţii:
- dacă tamponul este realocat pentru a încărca o nouă pistă în memorie, conform algoritmului de
realocare, care va fi prezentat mai jos,
- dacă tamponul este vidat în mod forţat din cauza închiderii unui fişier sau la cererea de eliminare a
unui volum.

Algoritmul de realocare a tampoanelor se bazează pe proprietatea localităţii de referinţe (localizare): cu cât


mai recent o informaţie a fost utilizată cu atât mai mare este probabilitatea unei noi cereri de
accesare. Din acest motiv tampoanele vor fi ordonate în ordine cronologică a referirilor lor.
Atunci când un tampon este necesar, el va fi căutat :
1) un tampon liber (care nu a fost încă utilizat),
2) un tampon ocupat, dar nemodificat pe parcursul încărcării sale,
3) dintre ocupate, alegând cel pentru care ultima referinţă este cea mai veche cronologic.
01.09.20
20 310
12:47:15
În cazurile 1 şi 2 tamponul este utilizat imediat. În 3 conţinutul său va fi în prealabil copiat pe dischetei.
Principiul programelor de gestionare a dischetelor

Vom avea un singur tampon (n=1) de lungimea unei piste, căruia îi sunt asociaţi doi indicatori:
pistă_prezentă : numărul pistei încărcate în tampon (nil dacă este vid)
modif: are valoarea TRUE dacă conţinutul zonei-tampon a fost modificat.

Interfaţa controlerului furnizează următoarele funcţii:


ALEGERE_SUPORT(sup) : alege suportul sup în calitate de suport curent
CĂUTARE_PISTA(np) : deplasează dispozitivul de citire-scriere la pista np
CITIRE_SECTOR(adr,nsect) : citeşte în 128 octeţi începând cu adresa adr conţinutul sectorului nsect
al pistei curente
SCRIERE_SECTOR(adr,nsect): scrie în nsect al pistei curente 128 octeţi, care încep de la adresa adr
TEST : permite consultarea indicatorilor preg, term, err din cuvântul de stare a controlerului.

Interfaţa furnizată de PIE pentru gestionarea dischetelor este compusă din procedurile
ALEGERE_SUPORT(sup), CITIRE_SECTOR(adr,nsect) şi SCRIERE_SECTOR(adr,nsect). Ultima procedură,
SCRIERE_SECTOR(adr,nsect), conţine parametrul mod, care poate lua valorile scriere_normală,
scriere_imediată şi scriere_prima.

Nu vom descrie aici procedura ALEGERE_SUPORT(sup), care este realizată de o funcţie a controlerului.

01.09.20
20 311
12:47:15
Schemele programelor

citire_sector(np,nsect,dest) scriere_sector(np,nsect,orig,mod)
if np <> p_p then if np<> p_p then
if modif then if modif then
transferare_pistă(p_p,tampon,scriere) transferare_pistă(p_p,tampon,scriere)
endif; endif;
transferare_pistă(np,tampon,citire) if mod=scriere_prima şi liber(np) then
endif; p_p=np
dest:=tampon[nsect] else
transferare_pistă(np,tampon,citire)
endif
endif
tampon[nsect]:=orig;
if mod=scriere_imediată then
transferare_sector(orig,np,nsect,scriere)
else
modif:=TRUE
endif
În cazul unei prime scrieri se presupune că este posibil să se determine cu ajutorul indicatorului liber(np), că
întreaga pistă np este alocată pentru prima dată.

Procedurile de mai sus utilizează două proceduri interne ale PIE: transferare_pistă şi transferare_sector, care
constituie driver-ul dischetei. 01.09.20
20 312
12:47:15
Transferare pistă

procedura transferare_pistă(np, tampon, sens); procedura transferare_sector(adr,nsect,sens);


CĂUTARE_PISTĂ(np) -- deplasarea braţului nsect:=convertire(nsect); -- numărul sectorului fizic
test: TEST nr_încercări:=0;
if nonterm then go to test repetare: case sens of
endif; citire: CITIRE_SECTOR(adr,nsect);
for nsect:=0 to nbsect-1 do -- nbsect = 27 scriere: SCRIERE_SECTOR(adr,nsect);
transferare_sector(tampon[nsect],nsect,sens) endcase
endfor; test: TEST -- control corectitudine transfer
modif:=false; if err then
if sens=citire then nr_încercări:= nr_încercări+1;
pistă_prezentă:=np if nr_încercări<nmax then
endif go to repetare
else
cauza:=eroare_fatală -- eşec după nmax încercări
<provocare deviere>
endif;
endif;
if nonterm then
go to test -- aşteptare activă
endif;

01.09.20
20 313
12:47:15
9.2.2.2. Introducere – extragere caractere

Schema sincronă de comandă, pe care o vom relua pentru cazul scrierii unui simbol. Pentru a permite
reasocierea perifericelor, adresa controlerului va fi specificată ca un parametru al driverului.
procedura ieşire_car(c,p); transmite caracterul c controlerului p
TEST(p);
if nonpreg then
<tratare eroare>
endif;
EXTRAGE(c,p);
test: TEST(p);
if err then
<tratare eroare>
endif;
if nonterm then
go to test
endif;
O procedură analogică intrare_car(c,p) este definită pentru citire.
Pentru realizarea schimburilor cu perifericele logice este definit un tabel de asociere cu trei intrări:
tabel_perif[tastatură]=adresa controlerului asociat tastaturii logice
tabel_perif[display]=adresa controlerului asociat ecranului logic
tabel_perif[imprimantă]=adresa controlerului asociat imprimantei logice.
Operaţiile pe perifericele logice vor fi realizate astfel:
afişare_car(c) =>ieşire_car(c,tabel_perif[display]) 01.09.20
imprimare_car(c) =>ieşire_car(c,tabel_perif[imprimantă]) 20 314
citire_car(c) =>intrare_car(c,tabel_perif[tastatură]) 12:47:15
9.2.3. Sistemul de gestiune a fişierelor
9.2.3.1. Organizarea logică

Pentru notarea unui fişier este utilizată o schemă pe două nivele, adică numele unui fişier este de forma
<nume suport>:<identificator>.<tip>

Numele suportului identifică suportul fizic al fişierului, adică unitatea de disc utilizată şi este definit, de
obicei, în mod implicit.

În interiorul unei dischete schema de desemnare este “plată”; identificatorul tipului specifică natura
fişierului (program translatabil, absolut, instrucţiuni, date, etc.).

Fişierele sunt organizate secvenţial, sub forma unei suite de înregistări de lungime fixă (128 octeţi).

Sistemul furnizează primitive de accesare secvenţială a înregistrărilor. Orice funcţie de acces trebuie să fie
construită plecând de le aceste primitive.

01.09.20
20 315
12:47:15
9.2.3.2. Organizarea fizică

În calitate de unitate de alocare sau bloc vom considera un set de 8 sectoare consecutive. Starea de
alocare a dischetei este descrisă cu ajutorul unui tabel de ocupare, care conţine câte un bit pentru
fiecare bloc (fie 250 biţi; în realitate un pic mai puţin, fiindcă primele două piste ale dischetei sunt
rezervate în permanenţă). Găsirea unui bloc liber se reduce la găsirea primului bit egal cu 0 în acest
tabel: numărul bitului este numărul blocului căutat.

Datele despre un fişier sunt grupate într-un descriptor care conţine următoarele informaţii:
- numele fişierului (<identificator>.<tip>),
- lungimea fişierului (numărul de înregistrări),
- numărul înregistrării viitoare la citire sau scriere,
- tabelul implantării fişierului.
Tabelul implantării fişierului constă din 16 octeţi, care conţin numerele blocurilor succesive în care fişierul
este implantat. Deci, pot fi utilizate pentru implantarea unui fişier 128 de sectoare, adică 16 Ko.
Fişierele de lungime mai mare, numite multisecţionate, pot fi implantate prin înlănţuirea a mai multor
descriptori, fiecare descriind un set de 16 unităţi de alocare, numit secţiune a fişierului. Numărul
maxim de secţiuni este 16, adică 256 Ko în total.
Pistele 0 şi 1, rezervate sistemului de operare, conţin, în particular, tabelul de ocupare a dischetei şi
programul de încărcare. Descriptorii tuturor fişierelor dischetei sunt ordonaţi într-o zonă rezervată,
începând cu pista cu numărul 2. Mulţimea acestor descriptori formează catalogul dischetei.

Pentru a facilita adaptarea sistemului la diferite tipuri de discuri, caracteristicile discurilor sunt grupate într-
un tabel, creat la generarea sistemului de operare şi descris 01.09.20
în 9.2.3.4; acest tabel este utilizat de
toate programele care trebuie să cunoască organizarea fizică a discurilor.
20 316
12:47:15
9.2.3.3. Operaţii cu fişierele

Deschiderea unui fişier cere încărcarea descriptorului acestuia într-o zonă a memoriei centrale, rezervată în
prealabil. Adresa acestui descriptor este transmisă ca parametru tuturor operaţiilor ulterioare asupra
fişierului.
La închiderea unui fişier deschis, descriptorul din memorie este recopiat pe disc şi locul lui este eliberat ca
şi zona de memorie, ocupată de fişierul propriu-zis. Dacă rămân înregistrări modificate ale fişierului
într-o zonă-tampon de I-E, ele la fel vor fi recopiate pe disc. Scrierea se face în mod imediat.

Crearea unui fişier constă în alocarea unui descriptor (pe disc) acestui fişier; iniţial fişierul este vid şi
tabelul său de implantare conţine doar zerouri.
La distrugerea unui fişier vor fi eliberate toate unităţile de alocare ocupate de fişier, ca şi amplasamentul
ocupat de către descriptorul acestuia. Catalogul şi tabelul de ocupare a discului sunt puşi la zi.

Vom descrie principiile de organizare a programelor de citire şi scriere secvenţială a unei înregistrări.
Programele de creare, distrugere, deschidere şi închidere a unui fişier sunt propuse ca exerciţii.

Presupunem că un fişier f este deschis. Notăm descriptorul în memorie a acestui fişier prin descr, care are
următoarele câmpuri:
- descr(f).ptr pointer de citire/scriere
- descr(f).sfr indicator de sfârşit de fişier
- descr(f).lng numărul de înregistrări ale fişierului
- descr(f).imp tabelul de implantare a fişierului
01.09.20
Admitem, pentru simplitate, că lungimea unui fişier este limitată la o singură
20 secţiune.
317
12:47:15
Schemele programelor de accesare

procedura avansare(f);
if descr(f).ptr=descr(f).lng-1 then
descr(f).sfr:=TRUE
else
descr(f).ptr:=descr(f).ptr+1
endif

procedura citire_secv(f,dest);
if descr(f).sfr then
<eroare> -- citire imposibilă, ne aflăm la sfârşitul fişierului
else
calculare(f,np,nsect); -- calcularea adresei pistă-sector
citire_sector(np,nsect,dest);
avansare(f);
endif

const l_unit_aloc=8; -- lungimea unităţii de alocare este de 8 sectoare


max_unit_aloc=16 -- numărul maxim de unităţi de alocare într-o secţiune

01.09.20
20 318
12:47:15
9.2.4. Interpretorul limbajului de comandă
9.2.4.1. Schema generală
Schema generală a interpretorului limbajului de comandă poate fi reprezentată printr-o buclă infinită:
iniţializare_sistem
ciclu
iniţializare_comandă
citire comandă
analizare comandă
if comandă corectă then
interpretare comandă:
preparare mediu de execuţie
lansare execuţie
else
diagnosticare eroare
endif
endciclu
Comanda este citită într-un tampon de memorie cu ajutorul terminalului logic: procedura cititre_linie.
Analiza comenzii: Primul câmp este numele comenzii, urmează parametrii transmişi programului
responsabil de interpretare. Dacă numele este unul din cele rezervate comenzilor de sistem
programul căreia este rezident, poate începe interpretarea. În caz contrar, fişierul care conţine
comanda trebuie în prealabil încărcat în memorie. Dacă este cazul unui program executabil al
utilizatorului, pregătit într-un fişier şi un astfel de fişier nu poate fi găsit, interpretorul va afişa un
mesaj de eroare şi va aştepta comanda următoare.
Secvenţa iniţializare_sistem reprezintă încărcarea iniţială şi poate fi01.09.20
declanşată de un buton de pornire sau
printr-un apel al supervizorului. 20 319
Secvenţa iniţializare_comandă pune sistemul în stare stabilă: toate tampoanele modificate sunt vidate pe
12:47:15

disc, toate fişierele sunt închise; interpretorul afişează un mesaj de invitaţie şi aşteaptă comanda.
9.2.4. Interpretorul limbajului de comandă
9.2.4.1. Schema generală
Schema generală a interpretorului limbajului de comandă poate fi reprezentată printr-o buclă infinită:
iniţializare_sistem
ciclu
iniţializare_comandă
citire comandă
analizare comandă
if comandă corectă then
interpretare comandă:
preparare mediu de execuţie
lansare execuţie
else
diagnosticare eroare
endif
endciclu
Comanda este citită într-un tampon de memorie cu ajutorul terminalului logic: procedura cititre_linie.
Analiza comenzii: Primul câmp este numele comenzii, urmează parametrii transmişi programului
responsabil de interpretare. Dacă numele este unul din cele rezervate comenzilor de sistem
programul căreia este rezident, poate începe interpretarea. În caz contrar, fişierul care conţine
comanda trebuie în prealabil încărcat în memorie. Dacă este cazul unui program executabil al
utilizatorului, pregătit într-un fişier şi un astfel de fişier nu poate fi găsit, interpretorul va afişa un
mesaj de eroare şi va aştepta comanda următoare.
Secvenţa iniţializare_sistem reprezintă încărcarea iniţială şi poate fi01.09.20
declanşată de un buton de pornire sau
printr-un apel al supervizorului. 20 320
Secvenţa iniţializare_comandă pune sistemul în stare stabilă: toate tampoanele modificate sunt vidate pe
12:47:15

disc, toate fişierele sunt închise; interpretorul afişează un mesaj de invitaţie şi aşteaptă comanda.
9.2.4.2. Mediul de execuţie

Prima sarcină a unui interpretor, înainte de lansarea execuţiei sistem rezident


unei comenzi, este de a pregăti mediul său, adică mulţimea
obiectelor, care vor fi utilizate şi informaţiile, care vor permite stiva
accesarea obiectelor.
liber tampon
În cazul executării unui program al utilizatorului acest mediu intrare-ieşire
conţine (v. fig. 9.3): segment date iniţializate
- segmentele cu programul care trebuie executat şi date, descriptor 1
descriptor 2
- stiva de execuţie, segment date
- o zonă de lucru, numită “pagină de gardă”, care conţine: pointeri
• pointeri, care punctează segmentele program şi segment procedură
date, precum şi zona liberă,
• descriptorii fişierelor, specificate în comandă, pagină de gardă
(pagină de
• un tampon destinat schimburilor cu fişierele. gardă)
sistem rezident

Fig.9.3. Mediul de execuţie

01.09.20
20 321
12:47:15
9.2.4.3. Încărcarea unui program

Operaţia de încărcare are drept efect pregătirea mediului. Ea urmează imediat operaţiei de analiză a
comenzii. Vom descrie această operaţie în cazul în care <nume comandă> este numele unui fişier,
care conţine un program executabil. Antetul unui asemenea fişier descrie conţinutul său: lungimea şi
poziţia în cadrul fişierului a segmentelor de cod şi de date, adresa de debut a execuţiei, adresele de
implantare a acestor segmente pentru un program absolut, informaţii de reimplantare pentru un
program translatabil. Încărcarea presupune următoarele:
1) Deschiderea fişierului <nume comandă> şi citirea antetului acestuia într-un tampon intern.
2) Determinarea dacă capacitatea memoriei disponibile permite încărcarea.
3) Crearea paginii de gardă în amplasamentul rezervat acestui efect.
4) Încărcarea segmentelor de cod şi de date în zonele indicate în antet; dacă are loc reimplantarea să se
adauge adreselor realocate deplasarea necesară; să se pună la zi informaţiile, care descriu memoria
disponibilă.
5) Iniţializarea stivei de execuţie şi plasarea în topul ei a unei adrese de retur în interpretorul limbajului
de comandă.
6) Punerea la zi a pointerilor paginii de gardă; ordonarea în tamponul situat în această pagină a “cozii
de comenzi”.
7) Deschiderea fişierelor (dacă există) numele cărora sunt specificate în comandă şi plasarea
descriptorilor acestora în pagina de gardă.
8) Executarea unei ramificaţii spre punctul de intrare a segmentului de cod.
Aceste operaţii sunt executate în mod slave, returul normal din programul executat în interpretorul
limbajului de comandă utilizează returul procedurii. Acest retur poate fi făcut şi prin apelarea
supervizorului sau ca şi consecinţă a unei devieri provocate de o eroare.
01.09.20
20 322
12:47:15
9.2.4.4. Tratarea erorilor de execuţie

Detectarea unei erori în cursul execuţiei provoacă un cod de eroare sau o deviere, chiar dacă ea a survenit
sau nu în cursul executării unei primitive realizate prin intermediul unui apel al supervizorului.
Pot fi evidenţiate două cazuri în dependenţă de gravitatea erorii:
- Eroare într-un program utilizator sau într-o componentă necritică a unui program de sistem, cum ar
fi interpretorul limbajului de comandă. Exemplu: operaţie aritmetică care nu poate fi executată,
memorie insuficientă pentru încărcarea unui program.
- Eroare în cursul unei operaţii critice, adică care pune în pericol integritatea datelor. Exemplu: eroare
irecuperabilă la un transfer pe disc.
Pentru oricare caz, principiul tratării unei erori constă în revenirea la o stare stabilă a sistemului din care
executarea poate reîncepe normal, reducând la minimum cantitatea de informaţii pierdute. O
clasificare conform acestui criteriu evidenţiază următoarele stări stabile:
1) Stare predecesoare executării instrucţiunii eronate,
2) Aşteptarea de către interpretor a unei comenzi,
3) Starea iniţială a sistemului.
Returul în starea 1) sau 2) corespunde tratării unei devieri într-un program utilizator. Această tratare poate
fi realizată într-un mod standard de sistem sau de un program de tratare, elaborat de utilizator.
Returul la starea 2), adesea numit “restartare la cald” (fr. reprise à chaud, eng. warm start), este
realizat de secvenţa iniţializare_comandă. Lucrul efectuat în cursul ultimei comenzi este, in genere,
pierdut, însă datele permanente (fişierele) sunt păstrate.
Revenirea la starea 3), adesea numită restartare rece (fr. reprise à froid, eng. cold start), este rezultatul
unei erori grave, care provoacă alterarea tabelelor interne ale sistemului sau a fişierelor pe disc.
Returul este realizat de secvenţa iniţializare_sistem. Pierderea01.09.20
de informaţii poate fi importantă (stare
incoerentă a unei dischete); există totuşi programe, care permit, în cazul unei
20
12:47:15
323 atare erori, restabilirea
totală sau parţială a conţinutului unui disc, folosind redundanţa informaţiilor.
5. Gestiunea informaţiei ..................................................................................................................................................... 2
5.1. Principiile gestiunii informaţiei ............................................................................................................................... 2
5.1.1. Definiţii generale .............................................................................................................................................. 2
5.1.2. Interpretarea numelor ....................................................................................................................................... 3
5.1.2.1. Construirea căii de acces ........................................................................................................................... 4
5.1.2.2. Structura reprezentărilor. Descriptori ........................................................................................................ 4
5.1.2.3. Contexte şi medii ....................................................................................................................................... 5
5.1.3. Legarea ............................................................................................................................................................. 6
5.1.4. Protecţia ............................................................................................................................................................ 7
5.1.4.1. Domenii şi drepturi de acces...................................................................................................................... 7
5.1.4.3. Problemele protecţiei ................................................................................................................................. 8
5.2. Desemnarea şi legarea fişierelor şi intrărilor-ieşirilor ............................................................................................. 9
5.2.1. Căi de acces la un fişier .................................................................................................................................... 9
5.2.2. Desemnarea externă a fişierelor. Cataloage .................................................................................................... 10
5.2.2.1. Introducere ............................................................................................................................................... 10
5.2.2.2. Organizarea arborescentă......................................................................................................................... 10
5.2.3. Legarea fişierelor cu fluxurile de intrare-ieşire .............................................................................................. 11
5.3. Legarea programelor şi datelor .............................................................................................................................. 12
5.3.1. Etapele de viaţă a unui program ..................................................................................................................... 12
5.3.2. Funcţionarea unui încărcător .......................................................................................................................... 13
5.3.3. Funcţionarea unui editor de legături ............................................................................................................... 14
5.3.3.1. Legarea prin substituţie ........................................................................................................................... 14
5.3.3.2. Legarea prin înlănţuire ............................................................................................................................. 17
5.4. Mecanisme de gestiune a obiectelor ...................................................................................................................... 17
5.4.1. Segmentarea ................................................................................................................................................... 17
5.5. Exerciţii la capitolul 5.................................................................................................................................... 19

Victor Beşliu p.1 din 20


5. Gestiunea informaţiei
Acest capitol este consacrat studierii principiilor de gestiune a informaţiei într-un sistem de operare. Noţiunea de
obiect formează suportul director al studiului dat. Vom începe cu prezentarea unor concepte de bază, care permit o mai
bună înţelegere a mecanismelor de administrare a informaţiei într-un sistem: nume sau identificator, cale de acces,
legare, protecţia obiectelor ș.a.. Aceste noţiuni vor fi utilizate în două domenii importante: desemnarea şi legarea
fişierelor (5.2) şi legarea programelor şi a datelor (5.3). Vom mai prezenta în 5.4 mecanismele fizice şi logice de bază,
care facilitează administrarea obiectelor (segmente, capacităţi) şi exemple de implementare a acestora în cadrul
sistemelor de operare.
Se consideră că informaţia, care circulă într-un sistem de calcul constă din obiecte; obiectele sunt entităţile asupra
cărora sunt efectuate anumite operaţii. Toate operaţiile pot fi clasificate în patru categorii:
 de creare,
 de modificare,
 de căutare,
 de distrugere a obiectelor.
Fiecare obiect are o reprezentare externă (în afara calculatorului) şi una internă, determinată de suportul fizic. Un
obiect poate fi accesat cu ajutorul funcţiilor de acces.
Problema centrală a administrării informaţiei constă în conversia reprezentării externe şi a funcţiilor de
acces asociate în reprezentarea internă şi funcţiile de acces corespunzătoare fiecărui obiect al sistemului.

5.1. Principiile gestiunii informaţiei


Noţiunile de identificator, valoare, tip, desemnare, reprezentare sunt utilizate în informatică în forme extrem de
diverse. Elaborarea unui model general pentru aceste noţiuni mai este încă o problemă deschisă. Ne vom limita aici la
prezentarea unui model simplificat, care se conturează în cadrul limbajelor de programare şi care permite să ţinem cont
de cele mai frecvente situaţii.
5.1.1. Definiţii generale
Programul unui sistem informatic descrie acest sistem ca o mulţime de obiecte. Obiectele sistemului şi operaţiile
asociate sunt cele specificate de limbajul utilizat. Pentru implementarea sistemului descris de un sistem informatic va
trebui să definim pentru fiecare obiect o reprezentare concretă, care are forma unei mulţimi de informaţii în memorie,
pentru unităţile periferice, etc. Implementarea sistemului se traduce prin acţiuni, care modifică starea acestor
reprezentări.
Procesul de reprezentare utilizează două scheme de bază. În schema compilării obiectele abstracte, specificate de
program, sunt înlocuite, în faza preliminară de translatare, prin reprezentările lor. Aceste reprezentări sunt obiecte
executabile direct interpretate de un dispozitiv fizic. În schema interpretării un sistem logic (interpretorul) este
alimentat direct din program; el asociază (în mod static sau dinamic) o reprezentare internă fiecărui obiect şi stabileşte
corespondenţa între obiectul abstract şi reprezentarea la fiecare accesare. Schema interpretării este de regulă mai puţin
eficace în comparaţie cu schema compilării, deoarece corespondenţa obiectelor trebuie realizată la fiecare accesare, însă
ea convine mai mult în cazul unei gestionări dinamice a obiectelor (înlocuirea unui obiect prin altul, modificarea
reprezentării unui obiect). În practică, este bine de combinat aceste două scheme în funcţie de restricţiile concrete.
Programul unui sistem utilizează nume pentru a desemna obiectele acestui sistem. Numele unui obiect este o
informaţie cu funcţie dublă: pe de o parte permite să se facă distincţia obiectului dat de alte obiecte; pe de altă parte, el
serveşte ca şi cale de acces la obiect, adică el poate fi interpretat în scopul efectuării unor acţiuni asupra obiectului.
Numele respectă anumite reguli proprii limbajului de programare. Nume sunt identificatorii, care desemnează
variabilele şi procedurile într-un limbaj de programare sau fişierele într-un limbaj de comandă.
În cazul reprezentării externe un identificator desemnează un anumit obiect, care poate fi o constantă sau o
informaţie ce permite accesul la un alt obiect (obiectul permite referirea unui alt obiect, fig. 5.1).
Program
..
. D obiect/ Ri
identificator
.. reper
.
obiect

Fig. 5.1. Relaţia identificator - obiect

Trecerea de la identificator la obiectul propriu-zis se realizează prin compunerea funcţiilor de acces D şi Ri, obţinând
calea de acces la un obiect.

Victor Beşliu p.2 din 20


Suportul fizic al informaţiei este memoria. La acest nivel memoria poate fi considerată un şir de amplasamente
caracterizate printr-un conţinut. Un proces desemnează un amplasament printr-un nume folosit de unitatea centrală
pentru a citi şi la necesitate a modifica conţinutul acestui amplasament. Conţinutul unui amplasament poate fi interpretat
ca un întreg, o instrucţiune sau ca un nume care desemnează alt amplasament.
Reprezentarea externă este convertită în cuplul (amplasament, conţinut), numele amplasamentului devenind numele
obiectului. De exemplu, o constantă devine un cuplu (amplasament, conţinut invariabil), iar un obiect care reperează
altul - (amplasament, conţinut variabil): amplasamentul conţine reprezentarea unui obiect care este fie reprezentarea
internă a unei constante, fie un nume.
Vom face o deosebire între celulele memoriei fizice şi amplasamente prin utilizarea noţiunii de adresă pentru
primele şi nume pentru amplasamente. Obiectele definite de perechea (amplasament, conţinut) pot fi deplasate în
memoria fizică, schimbarea adresei fizice a unui amplasament nu afectează, în general, numele lui.
Acestea au fost obiecte simple. Obiectele constituite din mai multe obiecte de acelaşi tip sau de tip diferit (masive,
fişiere, structuri) se numesc obiecte compuse. Numele obiectului compus se află într-un amplasament al cărui conţinut
este descriptorul obiectului. Descriptorul, fiind reprezentarea internă a unui obiect compus, defineşte tipul, numărul
componentelor obiectului, o eventuală ordine a acestora, precum şi amplasamentele în care se află aceste componente.
Funcţia de acces asociată descriptorului are parametri şi furnizează un conţinut sau un nume de amplasament.
Numim obiect accesibil un obiect căruia i s-a asociat o cale de acces. Numim obiect partajat orice obiect care este
accesibil mai multor utilizatori (eventual cu drepturi de acces diferite). Folosirea numelor care iniţiază calea de acces la
un obiect partajat poate fi imaginată în mai multe feluri: fie utilizarea aceluiaşi nume sau a unor nume diferite pentru a
avea acces la acelaşi obiect, fie folosirea aceluiaşi nume pentru a desemna reprezentări diferite.
Partajarea obiectelor la nivelul aceluiaşi nume (fig. 5.2, a) presupune rezervarea numelor tuturor obiectelor
partajabile în mod potenţial. Rezervarea acestor nume rămâne efectivă chiar dacă obiectele în cauză nu mai sunt
folosite, ansamblul obiectelor accesibile unui proces împărţindu-se în două părţi disjuncte: obiectele private ale
procesului şi cele potenţial partajabile.
În cazul partajării unui obiect folosind nume diferite (fig. 5.2, b), fiecare proces posedă un nume care după stabilirea
căii de acces îi permite accesul la o reprezentare unică.
În unele situaţii acelaşi nume permite accesul la reprezentări diferite; este cazul procedurilor reenterabile în care un
nume fixat la compilare conduce în timpul execuţiei la reprezentări diferite, proprii proceselor care utilizează această
procedură (fig. 5.2, c).
proces i proces j

a) nume nume

b) nume i nume j

c)
..
obiect i nume obiect j
..
.

Fig. 5.2. Accesarea obiectelor partajate


Numim durată de existenţă sau de viaţă a unui obiect perioada de timp în care acesta este accesibil. Sistemul de
operare şi tipul obiectului determină durata de existenţă a obiectului. Un masiv creat de un program într-un limbaj de
programare este distrus la terminarea execuţiei programului, amplasamentele pe care le ocupă putând fi reutilizate
pentru reprezentarea altor obiecte, în timp ce un fişier poate supravieţui programul care l-a creat.
5.1.2. Interpretarea numelor
La nivelul sistemului de operare obiectele sunt memorate în amplasamente, iar procesele le pot accesa prin nume.
Stabilirea căii de acces la un obiect prin compunerea funcţiilor de acces asociate se numeşte legare. Se spune că un
obiect este legat atunci când pentru el este stabilită calea de acces. În cazul operaţiilor aritmetice calea de acces asociată


În calculatoarele care permit adresarea imediată, o constantă poate fi reprezentată în instrucţiune.

Victor Beşliu p.3 din 20


unui obiect conduce la o constantă; în cazul listelor sau parametrilor - la un nume. Legarea se traduce, în ultimă
instanţă, prin stabilirea corespondenţei între identificatori şi adrese. Această corespondenţă este stabilită parcurgând un
şir de etape consecutive: se trece de la identificator la adresă conform unui set de relaţii, care se numeşte cale de acces
(avem, deci, încă o definiţie a noţiunii cale de acces, care este echivalentă celei introduse anterior).
5.1.2.1. Construirea căii de acces
Fie F1 şi F2 doua funcţii de acces, F1 permiţând accesul de la O1 la O2, iar F2 - de la O2 la O3: O1F1O2 şi O2F2O3,
accesul de la O1 la Oo3 fiind realizat prin compunerea acestor funcţii. Calea de acces de la O1 la O3 poate fi construită
prin metoda substituţiei sau prin metoda înlănţuirii.
Metoda substituţiei stabileşte o nouă funcţie de acces F3, obiectul O3 fiind accesat direct de la O1: O1F3O3. Metoda
are avantajul că accesul este rapid, dar şi dezavantajul că O2 este iremediabil pierdut.
Metoda înlănţuirii cere ca la fiecare accesare a obiectului O3 pornind de la O1 să fie parcursă calea O1F1O2F2O3. Nu
se pierde nici o informaţie, dar accesul este mai lent.
Unele obiecte pot fi legate la faza de compilare (de exemplu, obiectele private ale unui program), pentru altele calea
de acces este stabilită într-o fază ulterioară (obiectele externe şi parametrii sunt obiecte libere după compilare). Pentru
un obiect extern compilatorul creează un obiect legătură al cărui conţinut este un şir de caractere ce alcătuiesc
identificatorul plus o informaţie care permite regăsirea tuturor numelor ce desemnează această legătură. Operaţia de
legare a externilor se numeşte editare de legături. Ea poate fi realizată într-o fază distinctă, premergătoare fazei de
execuţie (static), sau în faza de execuţie (dinamic), când se face prima referinţă la obiectul extern. Editarea legăturilor se
face prin înlănţuire sau prin metoda substituţiei. În primul caz numele externului este la legătura prevăzută de
compilator şi această legătură este păstrată în continuare, iar în cel de-al doilea - numele externului este plasat în toate
amplasamentele indicate de legătură, după care aceasta este distrusă.
La acest nivel prin segment subînţelegem un ansamblu de amplasamente consecutive în care sunt reprezentate
obiecte de acelaşi tip, cu aceeaşi durată de existenţă şi cu acelaşi grad de protecţie. Segmentul este cea mai mică unitate
care poate fi partajată şi poate conţine obiecte compuse - un masiv, un fişier, o stivă sau o procedură - accesibile unui
proces la un anumit moment. Un descriptor, reprezentat într-un amplasament al segmentului, defineşte segmentul, iar
numele amplasamentului care conţine descriptorul este chiar numele segmentului.
Obiectului procedură îi sunt asociate mai multe noţiuni: modul sursă, modul obiect sau modul executabil.
Modulul sursă al unei proceduri este textul acesteia scris de către programator într-un limbaj de programare şi care va fi
tratat de către compilator. Modulul obiect al procedurii este obţinut la ieşirea compilatorului, deci este un produs al
compilatorului. Modulul obiect este reprezentat într-un segment sau într-un fişier, destinat interpretării (după editarea
legăturilor, la necesitate) de către procesor ca instrucţiuni, valori etc., fiind manipulat în consecinţă. Pentru a separa
gestiunea resurselor de administrarea informaţiei, interferenţă ce are loc din mai multe motive (memorii limitate din
punctul de vedere al capacităţii, timpi de acces foarte variaţi, execuţia instrucţiunilor numai atunci când se află în
memoria operativă, ceea ce impune un grad de mobilitate al obiectelor pe suporturile fizice etc.), s-a introdus noţiunea
de memorie fictivă: memorie operativă ipotetică suficient de mare pentru a conţine toate obiectele sistemului. Memoria
fictivă este asociată sistemului, iar memoria virtuală este proprie procesului.
5.1.2.2. Structura reprezentărilor. Descriptori
Schema de mai jos poate fi utilizată pentru obiecte elementare, cum ar fi valori întregi, reale sau caractere,
reprezentarea cărora cere un singur amplasament şi pentru care funcţiile de acces sunt reprezentate direct prin
instrucţiunile maşinii fizice. Se va mai ţine cont de următoarele două aspecte:
1) pot exista obiecte compuse, structura internă a cărora poate fi complexă, lungimea poate varia pe perioada
timpului de existenţă a obiectului,
2) poate fi necesar să se realizeze unele funcţii complexe de accesare a obiectelor compuse.
Cum a fost menţionat, numele obiectului compus se află într-un amplasament al cărui conţinut este descriptorul
obiectului. Utilizarea unui descriptor pentru a accesa un obiect impune trecerea printr-un cod de accesare care va
interpreta acest descriptor şi prezintă următoarele avantaje:
1) în cazul în care obiectul este pasat ca parametru unei proceduri este suficient să fie transmis descriptorul
sau adresa acestuia: este mult mai simplu să administrezi informaţii de volum fix şi cunoscut,
2) descriptorul constituie un “punct de trecere” impus pentru accesarea reperată a obiectului şi, ca rezultat,
poate servi la implementarea unor controale de accesare, de măsurare, etc.,
3) descriptorul asigură un acces indirect la obiectul reperat, ceea ce permite modificarea dinamică a căii de
acces (substituirea unui obiect printr-un alt obiect) sau deplasarea unui obiect în memorie fără
recompilarea modulului sursă,
4) partajarea obiectelor între mai mulţi utilizatori cu drepturi sau proceduri de accesare diferite poate fi
realizată construind tot atâţia descriptori, câţi utilizatori există; aceşti descriptori reperează acelaşi obiect şi
au aceleaşi informaţii de localizare fizică.

Victor Beşliu p.4 din 20


Exemplul 5.1. Un tablou este de obicei reperat de un descriptor, care conţine adresa de început a implantării sale în memorie, numărul de
amplasamente, ocupate de un element, numărul dimensiunilor şi pentru fiecare dimensiune, valorile maxime ale indicilor. Aceste
informaţii permit calcularea adresei de implantare a fiecărui element al tabloului; ele mai permit să se controleze dacă indicii introduşi
aparţin intervalului permis. ◄

Noţiunea de descriptor este larg folosită în sistemele de gestiune a fişierelor (v. 5.2 şi cap. 7). O altă utilizare este
realizarea mecanismului de adresare segmentată. Segmentarea este o tehnică elementară de structurare a softului. Putem
spune, că segmentul este un obiect compus, de lungime variabilă, reprezentarea în memorie a căruia ocupă o suită de
amplasamente consecutive; el permite ordonarea obiectelor, care se află într-o relaţie logică. Segmentarea permite
utilizatorului să-şi organizeze programele şi datele sub forma unui ansamblu de segmente, fără să se preocupe de
implantarea lor fizică. De exemplu, fiecare procedură a unui program complex poate ocupa un segment distinct. În
calculatoarele cu adresare segmentată fiecare segment este reperat de un descriptor, numele acestor descriptori fiind
direct interpretate de procesor.
5.1.2.3. Contexte şi medii
Mulţimea obiectelor accesibile unui proces variază în timp. Iată câteva considerente:
1. Decompoziţia aplicaţiilor. Metodele de decompoziţie, utilizate pentru structurarea unei aplicaţii complexe,
definesc componentele (module, proceduri, etc.). Fiecărei componente i se asociază o mulţime distinctă de
obiecte accesibile.
2. Gestiunea dinamică. Mulţimea obiectelor accesibile unui proces îşi poate modifica compoziţia din
considerente, legate chiar de natura aplicaţiei: obiectele pot fi create sau distruse în timpul execuţiei.
3. Protecţia. O modalitate simplă de a împiedica un proces să aştepte un obiect, accesul la care îi este interzis,
este de a suprima toate căile de acces ale procesului spre acest obiect pentru durata interdicţiei. Vor fi
evitate în acest fel cheltuieli exagerate la execuţie.
4. Eficacitatea. Dacă un obiect este căutat într-o mulţime de alte obiecte, căutarea este cu atât mai eficace cu
cât mulţimea are mai puţine elemente.
Trebuie, deci, să luăm în consideraţie atât posibilitatea evoluţiei dinamice a mulţimii obiectelor, cât şi a căilor de
acces la aceste obiecte. Introducem pentru aceasta noţiunile care urmează.
Vom numi lexică o mulţime de identificatori. Mulţimea obiectelor, desemnate de identificatorii lexicii la un moment
de timp dat, se numeşte context asociat la această lexică (adică mulţimea obiectelor pentru care există o cale de acces
pornind de la unul dintre aceşti identificatori). Starea de execuţie a unui context este starea mulţimii obiectelor, care
constituie acest context.
Fiind dată doar lexica nu putem defini un context: mai trebuie să fie specificate regulile de interpretare, care vor fi
aplicate identificatorilor din cadrul lexicii. Vom numi mediu mulţimea formată dintr-o lexică şi informaţiile (programe,
date, reguli de interpretare) necesare la utilizarea acestei lexici. Aceste informaţii pot lua diferite forme în dependenţă
de limbajul utilizat (limbaj de comandă, limbaj de programare).
Vom numi accesibilitate a unui identificator într-un program regiunea programului în care acest identificator este
valid, adică poate fi utilizat ca origine a unei căi de acces. Altfel spus, un proces poate utiliza acest identificator pentru a
desemna un obiect atunci când el execută partea în cauză a programului.
Noţiunea de durată de existenţă sau de viaţă a unui obiect poate fi extinsă şi pentru căile de acces, înţelegând prin
aceasta perioada de timp în care acestea există (intervalul de timp care separă crearea de distrugere).
Atunci când un proces execută un program, mulţimea obiectelor la care procesul are acces este definită pentru orice
moment de timp, aplicând identificatorilor valizi în aceste momente de timp regulile de interpretare, specificate de
mediul curent: regăsim noţiunea de context pentru execuţia unui proces, introdusă în capitolul 3.
Exemplul 5.2. Fie procesul (presupus unic) asociat utilizatorului unui sistem interactiv. În mediul, definit de interpretorul limbajului de comandă,
lexica conţine numele fişierelor accesibile utilizatorului. Atunci când utilizatorul comandă execuţia unei proceduri, mediul se
modifică: lexica conţine identificatorii definiţi în interiorul procedurii de regulile de accesibilitate ale limbajului şi interpretaţi conform
regulilor proprii acestui limbaj.

ident.
context

reguli de
lexica interpretare obiect
cale de acces

mediul
Fig.5.3. Contextul de execuţie a unui proces

Victor Beşliu p.5 din 20


Conform specificaţiilor sistemului de operare, identificatorii fişierelor pot sau nu pot continua a fi utilizabili (conform regulilor proprii
de interpretare). ◄

Starea de execuţie a unui proces (“valoarea” obiectelor contextului său) se poate modifica la execuţia fiecărei
instrucţiuni, însă conţinutul contextului său (identitatea obiectelor care-l formează), se schimbă cu o frecvenţă mai mică.
Iată evenimentele principale care pot modifica conţinutul contextului unui proces:
1) Schimbarea mediului, implicând o modificare a compoziţiei lexicii şi, eventual, aplicarea unor reguli de
interpretare noi: apel de procedură, intrarea într-un bloc nou (într-un limbaj cu structură de blocuri),
schimbarea catalogului curent (într-un limbaj de comandă).
2) Modificarea explicită a căii de acces, pornind de la un identificator al lexicii: asocierea unui fişier sau unui
periferic unui flux de intrare-ieşire.
3) Crearea sau distrugerea explicită a unui obiect desemnat de un identificator din lexică: crearea sau
distrugerea unui fişier, alocarea sau eliberarea unei variabile administrate dinamic.
Examinând aceste cazuri putem diferenţia durata de viaţă a unui obiect, a unui identificator, care desemnează acest
obiect şi cea a unei căi de acces, care conduce la obiectul în cauză. Sunt posibile diferite situaţii: un identificator poate fi
legat succesiv de diferite obiecte; reciproc, un obiect poate succesiv (sau simultan) să fie desemnat de mai mulţi
identificatori diferiţi; un obiect poate deveni inaccesibil (nici o cale de acces nu conduce la el). Existenţa obiectelor
inaccesibile pune problema recuperării spaţiului ocupat de acestea: tehnici speciale de “adunare a fărămiturilor”, permit
rezolvarea acestei probleme.
Exemplul 5.3. Cu titlu de exemplu vom indica diferite clase de obiecte, accesibile unui proces în cursul execuţiei unei proceduri, exprimată într-un
limbaj de programare de nivel înalt. Aceste clase diferă din punct de vedere a duratei de viaţă, duratei legăturii şi modului de partajare
a obiectelor.
1) Obiecte interne: acestea sunt instrucţiunile, care compun textul procedurii. Ele sunt desemnate de etichetele, utilizate pentru
instrucţiunile de ramificare. Durată lor de viaţă coincide cu durată de viaţă a procedurii.
2) Obiecte locale: acestea sunt variabilele, declarate în interiorul procedurii. Aceste obiecte sunt create la fiecare apel al procedurii
şi distruse la retur. În cazul unui apel recursiv, un exemplar nou al fiecărui obiect local este creat la fiecare apel şi identificatorul
său desemnează ultimul exemplar creat (celelalte rămânând inaccesibile până la returul la nivelul corespunzător).
3) Obiecte remanente şi obiecte globale: acestea sunt obiectele care existau deja la apelul procedurii şi care vor supravieţui la retur;
durata lor de viaţă este fie cea a procesului (obiecte remanente), fie cea a unei proceduri, care înglobează procedura dată (obiecte
globale).
4) Obiecte externe: sunt obiectele construite şi păstrate independent de procedura şi procesul considerat (alte proceduri, fişiere,
etc.). Durata lor de viaţă nu depinde de cea a procedurii sau a procesului; ele pot fi create sau distruse în mod dinamic în timpul
execuţiei procedurii.
5) Parametri: parametrii formali sunt identificatori, utilizaţi în interiorul procedurii şi care sunt legaţi doar în momentul apelării.
Obiectele legate de acestea sunt numite parametri efectivi sau activi; parametrii efectivi sunt furnizaţi de către procedura apelantă
sau sunt obiecte externe. Legătura dintre parametrii formali şi cei efectivi poate lua diferite forme în dependenţă de regulile
definite în limbajul de programare: apelare prin nume, prin valoare, prin referinţă. Aceste forme diferă prin momentul stabilirii şi
permanenţei legăturii. Legătura dispare la returul din procedură. ◄

În cazul în care mai multe procese partajează o procedură, fiecare proces posedă un set propriu de obiecte locale,
remanente, globale. Obiectele externe sunt în exemplar unic, ca şi textul (invariant) al procedurii.
5.1.3. Legarea
Numim legare procesul construirii unei căi de acces. Acest proces acoperă o varietate mare de situaţii, care vor fi
analizate din mai multe puncte de vedere: natura relaţiei de desemnare, momentul legării, permanenţa legăturii. Vom
prezenta mai jos şi tehnicile principale utilizate.
Legarea obiectelor unui program poate fi efectuată la diferite momente de viaţă a programului în sistem:
1) În momentul scrierii programului. Este cazul unui program scris direct în cod binar când fiecare obiect este
desemnat prin adresa absolută a amplasamentului, care-l conţine. Un atare program poate fi imediat executat, dar orice
modificare este dificilă şi conţine un risc ridicat de eroare. În practică, unicele obiecte legate la etapa scrierii
programului sunt notaţiile universale, care desemnează constantele.
2) La una din fazele de translatare (asamblare sau compilare). Legătura este definitivă şi identificatorii sunt
înlocuiţi prin adrese absolute. Dezavantajul este că programul nu poate fi deplasat în memorie fără a fi recompilat (dacă
nu există mecanisme de translatare a adreselor). De asemenea, legătura stabilită la translatare nu este decât parţială:
identificatorii nu sunt înlocuiţi de adrese absolute, ci relative începând cu originea programului (deplasare).
3) La o fază de încărcare şi editare a legăturilor. Faza încărcării are drept scop înlocuirea adreselor relative prin
adrese absolute, fixând originea programelor în memorie. Faza editării legăturilor are ca scop stabilirea legăturii
referinţelor externe (să ne amintim, că vorbim despre identificatorii, care desemnează obiecte construite sau păstrate
independent de programul în cauză). Încărcarea şi editarea legăturilor pot fi combinate într-o singură operaţie sau
realizate separat. Algoritmii utilizaţi sunt descrişi în 5.3.
O operaţie analogică editării legăturilor este cea a legării fluxurilor de intrare-ieşire cu fişierele sau perifericele. Ca
şi editarea legăturilor, această operaţie, descrisă în 5.2.3.2 poate fi realizată în prealabil sau în timpul execuţiei.


Cu excepţia sistemelor de înlănţuire a programelor, numite “compile and go” în care programele sunt traduse şi executate imediat; aceste sisteme
sunt prevăzute pentru programe scurte, destinate unei singure execuţii.

Victor Beşliu p.6 din 20


4) În timpul execuţiei; legătura este numită în acest caz dinamică. Există mai multe considerente de retardare a
legăturii până la faza de execuţie:
 informaţiile necesare pot fi cunoscute doar la această fază, în particular dacă obiectele desemnate sunt create
dinamic, fiind, deci necunoscute la momentul compilării,
 calea de acces trebuie modificată în timpul execuţiei: este cazul când un identificator este reutilizat pentru a
desemna succesiv mai multe obiecte (de exemplu, flux de intrare-ieşire reasociat mai multor fişiere diferite),
 mecanismul interpretării impune o legătură dinamică: poate fi cazul, de exemplu, al variabilelor locale a unei
proceduri recursive, adresa cărora poate fi stabilită doar în cursul execuţiei.
Legarea dinamică constă, cel mai frecvent, în completarea unei căi de acces existente deja parţial.
Tabelul, care urmează, aduce un rezumat al caracteristicilor legăturii în dependenţă de momentul stabilirii acesteia.
Tabelul 5.1. Caracteristicile legăturilor
Legătura Condiţii Caracteristici
Devreme Informaţiile sunt cunoscute din timp Eficienţă în execuţie
Condiţii de execuţie invariante Cale de acces nemodificabilă
Târzie Informaţii cunoscute parţial Necesitatea păstrării informaţiilor de legătură
Condiţii de execuţie variabile Timp mare de execuţie, programe adaptabile
Dacă criteriul principal este comoditatea utilizării unui sistem şi adaptabilitatea lui la condiţii diverse de execuţie
(ceea ce este cazul sistemelor interactive), vom fi cointeresaţi să întârziem momentul stabilirii legăturii (“delay binding
time”). Motivaţia principală a unei legături, stabilite la etapa iniţială de elaborare a programului, este eficacitatea
execuţiei.
5.1.4. Protecţia
Vom înţelege prin termenul protecţie mulţimea metodelor şi mecanismelor, care vizează specificarea regulilor de
utilizare a obiectelor şi garantează respectarea acestor reguli. Protecţia este asigurată de o combinaţie de dispozitive
fizice şi logice.
Există legături strânse între desemnarea obiectelor şi protecţia lor. Să ne reamintim trei observaţii, legate de
protecţie:
1) O modalitate simplă de a interzice unui proces orice acces la un obiect constă în suprimarea tuturor căilor de
acces la acest obiect, altfel spus, de a le retrage din contextul procesului,
2) Atunci când operaţiile permise asupra unui obiect sunt specificate prin apartenenţa la o clasă sau un tip, este
posibilă verificarea prealabilă execuţiei (adică în momentul compilării sau editării legăturilor) dacă obiectul este
utilizat conform regulilor specificate,
3) În cazul în care verificarea este făcută în momentul execuţiei, o procedură de acces facilitează implementarea
verificării şi reduce riscul unor erori. Această procedură poate fi la nivel logic (un interpretor, de exemplu) sau
fizic (un dispozitiv va aproba trecerea mai departe).
Prezentăm mai întâi un model simplu, care va permite să introducem noţiunile principale, necesare studierii
protecţiei. Mecanismele, care permit implementarea protecţiei într-un sistem informatic, sunt descrise în 5.4.
5.1.4.1. Domenii şi drepturi de acces
Printre obiectele, care formează un sistem informatic cele care pot acţiona asupra altor obiecte, modificându-le
starea, vor fi numite “active”. Regulile de utilizare pot fi exprimate specificând drepturile de acces ale fiecărui obiect
activ, adică mulţimea de operaţii pe care obiectele active sunt autorizate să le execute asupra altor obiecte.
Să precizăm acum noţiunea de obiect “activ”, adică să definim entităţile cărora sunt ataşate drepturile. Am putea să
legăm drepturile direct de procese, însă această alegere nu permite exprimarea simplă:
1) a posibilităţii evoluţiei dinamice a drepturilor unui proces,
2) a faptului, că mai multe procese pot avea, în aceleaşi circumstanţe, acelaşi set de drepturi.
Pentru a ţine cont de aceste două aspecte a fost introdusă noţiunea de domeniu de protecţie. Această noţiune este un
caz particular al noţiunii de mediu - un domeniu defineşte:
 o mulţime de obiecte accesibile sau context,
 pentru fiecare dintre aceste obiecte, o mulţime de operaţii permise (drepturi),
 un mecanism, care asigură accesul la aceste obiecte, respectând restricţiile de mai sus.
Un proces este întotdeauna executat într-un domeniu bine definit; contextul său este cel ataşat domeniului, procesul
posedând drepturile specificate asupra tuturor obiectelor acestui context. Un proces poate schimba domeniul cu ajutorul
unei operaţii particulare (apelare domeniu). Un domeniu este el însuşi un obiect asupra căruia poate fi executată
operaţia de apel; alte operaţii sunt definite mai departe.
Exemplul 5.4. Fie o mulţime de procese executate pe un procesor. Pot fi definite două domenii, supervizor şi sclav, conform modului de execuţie,
specificat în cuvântul de stare. În modul supervizor, procesul poate executa toate instrucţiunile procesorului; în modul sclav el poate
executa doar instrucţiunile neprivilegiate. Un proces poate schimba domeniul, executând instrucţiuni speciale: atunci când procesul
este în modul supervizor este suficient să fie încărcat un cuvânt de stare care conţine modul sclave; dacă procesul este în modul sclave
el nu poate trece la modul supervizor decât în urma unei devieri sau a unui apel al supervizorului, care conţine modificarea modului.
Remarcăm, că în acest caz el poate executa doar programul asociat devierii sau apelului supervizorului şi nu orice program. Anume
acest mecanism asigură eficacitatea dispozitivului de protecţie. ◄

Victor Beşliu p.7 din 20


Domeniile de protecţie pot fi definite prin mai multe modalităţi; exemplificăm câteva mai jos.
 un domeniu pentru sistemul de operare, unul pentru fiecare utilizator,
 un domeniu pentru fiecare subsistem, care realizează o funcţie particulară,
 un domeniu pentru fiecare mediu (definit, de exemplu, de cuplul (procedură, catalog curent)).
Alegerea depinde de funcţiile cerute şi, cel mai important, de mecanismele disponibile (v. 5.4).
Presupunem pentru început, că există un număr constant de obiecte. Regulile de protecţie pot fi reprezentate sub
forma unui tablou bidimensional, numit matricea drepturilor. Acest tablou conţine câte o linie pentru fiecare domeniu
Di şi câte o coloană pentru fiecare obiect Oj (notăm, că domeniile, fiind obiecte particulare, apar de asemenea şi în
coloane). Caseta (i, j) conţine drepturile pe care le are un proces, care se execută în domeniul Di, asupra unui obiect Oj.
Tabelul 5.2. Exemplu de matrice de drepturi
fişierul 1 fişierul 2 periferic D1 D2 D3
D1 <citire, scriere, <citire, scriere, <alocare, <> <apelare> <schimbare
executare> executare> retragere> drepturi>
D2 <citire, scriere, <citire, scriere, <cerere, <apelare> <> <apelare>
executare> executare> eliberare>
D3 <citire, scriere, <citire, scriere, <> <nil> <apelare> <>
executare> executare>
Notaţia nil semnifică faptul, că obiectul Oj nu figurează în contextul domeniului Di, iar notaţia <> defineşte o listă
vidă. În ambele cazuri Oj este inaccesibil în Di; diferenţa apare dacă să vrea să se ofere lui Di drepturi asupra lui Oj: în
primul caz este necesar să se introducă Oj în contextul lui Di, adică să-l legăm; în cel de-al doilea caz este suficient să
extindem lista existentă.
În practică, matricea drepturilor este foarte rarefiată, adică foarte multe casete conţin nil sau <>. Din această cauză
sunt utilizate alte forme de reprezentare a matricei drepturilor:
1) Reprezentarea coloanelor: lista de acces
Lista de acces, asociată unui obiect este o listă (Di, <di>), unde Di este un domeniu, care conţine obiectul, iar <di>
este mulţimea drepturilor acestui domeniu asupra lui. De exemplu, dacă un domeniu este asociat fiecărui utilizator al
unui sistem în timp partajat, lista de acces a unui fişier conţine pentru fiecare utilizator lista operaţiilor pe care el este
autorizat să le întreprindă asupra fişierului.
O metodă frecvent utilizată pentru a reprezenta mai compact listele de acces constă în specificarea pentru un obiect a
unor drepturi implicite (default) pe care le posedă fiecare domeniu. De exemplu, putem specifica implicit, că orice fişier
este accesibil doar pentru lectură fiecărui utilizator. Lista de acces va conţine doar cuplurile (Di, <di>) pentru care
drepturile diferă de cele implicite.
2) Reprezentarea liniilor: lista de drepturi şi capacităţi
Lista drepturilor asociată unui domeniu este o listă (Oj, <dj>) în care Oj desemnează un obiect, care figurează în
contextul domeniului, iar <dj> este mulţimea drepturilor domeniului asupra lui Oj. Un proces, care este executat în
domeniul considerat, primeşte această listă de drepturi; la fiecare accesare a unui obiect mecanismul de accesare trebuie
să verifice că operaţia curentă este licită, adică este în <dj>. Din considerente de eficacitate, este de dorit ca acest
mecanism să fie cablat. Forma cea mai primitivă în acest sens este bitul supervizor-sclave a cuvântului de stare a unui
procesor. O formă mai evoluată este capacitatea (v. 5.4.3), care reuneşte într-o structură unică de date, interpretată la
fiecare accesare, adresa unui obiect şi mulţimea drepturilor permise. În acest fel, lista drepturilor unui domeniu este lista
capacităţilor.
O operaţie importantă este cea de schimbare a domeniului, care permite unui proces să-şi modifice mediul şi
drepturile asupra obiectelor. Această schimbare a domeniului ia adesea forma unui apel de procedură, atunci când
procesul trebuie să revină în domeniul său iniţial. Pentru a garanta respectarea regulilor de protecţie, trebuie luate
măsuri de precauţie de fiecare dată, când are loc extinderea drepturilor. Această circumstanţă se poate produce în egală
măsură atât la apel, cât şi la retur. Pentru controlarea operaţiei de schimbare, se cere ca apelul şi returul domeniului să
se facă în mod exclusiv prin execuţia unor proceduri speciale (ghişeu de apel sau de retur), programele cărora
garantează respectarea regulilor specificate. Schimbarea domeniului pe o altă cale decât cea a ghişeului este interzisă de
mecanismele de protecţie a domeniului.
Exemplul 5.5. În cazul domeniilor, definite de modurile supervizor şi sclav, ghişeele de apel, în modul sclav, sunt definite prin devieri şi apelări a
regimului supervizor, care realizează primitivele interfeţei sistemului de operare. Programul acestor primitive, care este protejat,
verifică validitatea parametrilor transmişi. Deoarece drepturile în modul supervizor sunt totdeauna mai mari decât cele din modul
sclav, ghişeul de retur este inutil şi primitivele sunt executate în totalitate în modul supervizor; ghişeul devine necesar, dacă aceste
primitive trebuie să apeleze o procedură în regimul sclav, deoarece are loc o extensie de drepturi la retur. ◄

Vom găsi în 5.4.2 şi 5.4.3 o cercetare mai detaliată a mecanismelor de protecţie şi câteva exemple de utilizare a
acestora în sistemele de operare.
5.1.4.3. Problemele protecţiei
Prezentăm succint câteva probleme, legate de implementarea protecţiei în sistemele informatice.
1) Protecţie ierarhizată

Victor Beşliu p.8 din 20


În această situaţie simplă vrem să protejăm un subsistem A contra erorilor sau acţiunilor prohibitive, provenite dintr-
un subsistem B, care utilizează serviciile subsistemului A, dar nu are vre-un drept asupra lui A. În acelaşi timp A poate
accesa fără restricţii toate informaţiile lui B. Subsistemul A este, de exemplu, un sistem de operare, iar B - o aplicaţie.
Această problemă este rezolvată prin mecanisme ierarhice cum ar fi regimurile supervizor/sclav, cu trecere obligatorie
printr-un apel la regimul supervizor pentru comunicarea între A şi B. Schema inelelor de protecţie (v.5.4.2.5) este o
generalizare a acestui principiu.
2) Subsisteme reciproc suspicioase
Există o suspiciune reciprocă între două subsisteme în cazul în care fiecare specifică, că unele din informaţiile sale
trebuie să fie protejate contra erorilor sau acţiunilor prohibitive ale celuilalt subsistem. Această situaţie nu poate fi
tratată cu ajutorul unui mecanism de protecţie ierarhic.
3) Acordarea şi retragerea drepturilor de acces
Problema pusă aici este problema modificării dinamice a drepturilor de acces. În particular, este posibil să se
dorească să avem posibilitatea de a extinde sau restrânge drepturile unui domeniu. Când transmiterea drepturilor este
tranzitivă (extinderea drepturilor unui domeniu permiţându-i la rândul său să transmită drepturi), poate fi foarte dificil
să se cunoască la un moment de timp dat mulţimea drepturilor ataşate unui obiect anume. Apare o problemă, dacă se va
decide restrângerea sau suprimarea acestor drepturi pentru toate domeniile sau doar pentru o parte a lor, care pot accede
obiectul. O soluţie posibilă constă în introducerea unui pasaj unic (descriptor) la traversarea căruia se vor permite
accesările obiectului. Însă această metodă nu permite tratarea cazului unei retrageri selective, pentru care poate fi
necesar să fie parcurse legăturile inverse între obiect şi domeniile, care au acces la obiect.

5.2. Desemnarea şi legarea fişierelor şi intrărilor-ieşirilor


Organizarea fişierelor şi realizarea funcţiilor lor de acces vor face obiectul de studiu al capitolului 6. Vom examina
aici modul de desemnare a fişierelor, legarea lor cu programele, care le utilizează şi relaţiile lor cu intrările-ieşirile. Nu
avem nevoie pentru aceasta să cunoaştem organizarea internă a unui fişier, interesându-ne doar organizarea lui ca un tot
întreg în cazul unui limbaj de comandă sau al unui program.
5.2.1. Căi de acces la un fişier
Un fişier este un obiect compus: el posedă un descriptor, care conţine informaţiile, necesare localizării sale fizice şi
realizării funcţiilor de acces. Pentru sistemul de operare, numele descriptorului unei fişier (adresa fizică sau indicile
într-un tabel de descriptori) permite accesul la fişier. Acest nume al descriptorului, de obicei necunoscut de utilizatori şi
rezervat doar pentru sistemul de operare, este numit nume intern al fişierului. Descriptorul şi numele intern al fişierului
sunt unice. Conţinutul unui descriptor de fişier este detaliat în 6.4.
Un fişier este desemnat de către utilizatorii externi cu ajutorul identificatorilor – nume externe. Aceste nume
externe sunt definite într-un mediu comun mai multor utilizatori. Structurile de date, care permit construirea căii de
acces la un fişier pornind de la unul din numele sale externe, sunt numite cataloage sau directorii (eng., directory).
Structura cataloagelor şi interpretarea numelor externe sunt descrise în 5.2.2.
În afara numelor interne şi externe, adesea mai este definit un nume, zis local sau temporar. Un nume local este
definit într-un mediu propriu unui utilizator şi are o existenţă doar temporară (de exemplu, durata de execuţie a unui
program). Necesitatea unui asemenea nume rezidă în următoarele:
 Eficacitate: numele locale sunt definite într-un mediu mai restrâns decât numele externe şi interpretarea lor este,
deci mai rapidă (cataloagele nu sunt parcurse la fiecare accesare a fişierului),
 Comoditatea utilizării şi adaptabilitatea programelor: acelaşi nume poate fi refolosit pentru a desemna fişiere
diferite pentru instanţe de timp distincte, ceea ce permite reutilizarea unui program cu fişiere diferite fără a fi
necesar să se modifice textul programului,
 Acces selectiv: interpretarea numelor locale permite introducerea unui acces selectiv la un fişier în dependenţă
de utilizator (funcţii de acces sau drepturi de acces diferite).
Legarea numelor locale este realizată prin înlănţuire: un nume local desemnează un descriptor local, care la rândul
său, direct sau indirect, reperează descriptorul unic al fişierului.

Mediul global Mediul local Mediul SGF

nume externe nume local nume intern

(Cataloage) descriptor local


Descriptor fişier

Fig.5.4. Căi de acces la un fişier

Victor Beşliu p.9 din 20


5.2.2. Desemnarea externă a fişierelor. Cataloage
Vom examina modul în care un utilizator poate nota fişierele cu ajutorul identificatorilor sau nume externe, şi
structurile de date sau cataloagele, care permit determinarea descriptorului fişierului, pornind de la un nume extern,
Pentru simplificarea expunerii vom presupune, că descriptorii se conţin direct în catalog; în realitate doar o parte a
descriptorului se poate afla în catalog, acompaniată de un nume intern, care permite determinarea restului.
5.2.2.1. Introducere
Un catalog defineşte în sensul 5.1.2, un mediu, adică o mulţime de identificatori (sau o lexică) şi regulile de
interpretare a acestor identificatori. Organizarea cea mai simplă poate fi schematic reprezentată de un tabel, care
asociază unui identificator descriptorul fişierului pe care acesta îl desemnează. Acest tabel este administrat prin una din
tehnicile cunoscute (organizare secvenţială, adresare dispersată, etc.). O astfel de organizare a fost descrisă în 3.3. Ea
tratează la acelaşi nivel toate numele, ceea ce implică următoarele inconveniente:
 într-un sistem mono-utilizator ar fi bine să avem la dispoziţie posibilitatea de a clasifica fişierele pe rubrici,
 într-un sistem multi-utilizator conflictele datorate omonimiei a două fişiere de utilizatori diferiţi, restricţionează
libera alegere a numelor,
 în toate cazurile, căutarea unui fişier cu numele dat, se efectuează pe toată mulţimea numelor, în timp ce
informaţii referitoare la natura sau apartenenţa fişierului ar putea accelera această căutare.
Reieşind din aceste considerente, organizarea pe un singur nivel (fig.5.5, (a)) nu este folosită, cu excepţia unor
sisteme mono-utilizator foarte mici. Este preferată cea ierarhică în care fişierele şi cataloagele sunt organizate conform
unei structuri arborescente. Această structură se reflectă în structura identificatorilor. Adâncimea arborescenţei poate fi
limitată: de exemplu, o structură cu două nivele (fig.5.5 (b)) permite definirea a câte un catalog pentru fiecare utilizator
a unui sistem, aceste cataloage fiind şi ele grupate într-un catalog general.

catalogul
(a) (b) utilizatorilor

catalog

Victor ... Christy ... Eugen

fişier program doc ... ... ...

test doc program doc program fişier

Fig. 5.5. Organizarea fişierelor pe niveluri


Modelul general al organizării ierarhice, prezentat mai jos, a fost propus în sistemul Multics; multe sisteme s-au
inspirat de acest model.
5.2.2.2. Organizarea arborescentă
O organizare arborescentă este definită după cum urmează:
 Unui catalog i se asociază o mulţime (care poate fi vidă) de alte cataloage şi fişiere; aceste obiecte se numesc
incluse în catalog; ele sunt desemnate aici printr-un identificator zis nume simple. Relaţia între un catalog şi un
alt catalog, inclus în primul, se numeşte relaţie de legătură; ea permite să se definească un fiu (catalogul inclus)
şi un tată.
 Există un catalog, şi numai unul singur, numit rădăcină, care nu are tată. Orice alt catalog are un tată, şi doar
unul singur.
Relaţia de legătură defineşte o arborescenţă de cataloage cu rădăcina în catalogul rădăcină. Sunt utilizaţi termenii de
predecesori sau descendenţi pentru a desemna cataloagele la care poate ajunge de la un catalog dat prin intermediul unei
suite de relaţii tată sau fiu.
Plecând de la un catalog dat, există o cale unică într-o arborescenţă pentru a ajunge la oricare din descendenţii săi.
Această proprietate este utilizată pentru desemnare: numele unui catalog este construit prin concatenarea numelor
simple succesive, care desemnează predecesorii săi, începând cu catalogul iniţial; numele unui fişier este concatenarea
catalogului, care îl include şi a numelui său simplu. În identificatorii construiţi astfel (zise nume calificate sau compuse)
este utilizat un simbol special (“>” în Multics, “/” în Unix sau “/” în MS DOS) pentru separarea numelor simple
succesive.
În acest mod putem asocia un mediu fiecărui catalog; lexica acestui mediu este mulţimea numelor, simple sau
compuse, construite cum a fost indicat; contextul este mulţimea formată din catalogul considerat, descendenţii săi şi
toate fişierele, incluse în aceste cataloage. Mediul şi numele asociate catalogului rădăcină se numesc universale.

Victor Beşliu p.10 din 20


De exemplu, în sistemul Multics, simbolul “>” este utilizat ca separator pentru construirea numelor compuse;
utilizarea separată a acestui simbol desemnează prin convenţie, catalogul rădăcină. La orice moment de timp un catalog
curent este asociat fiecărui utilizator. Prin convenţie, mediul utilizatorului este reuniunea mediului definit de catalogul
curent şi de mediul universal. Utilizatorul poate desemna orice obiect, utilizând numele universal (care începe cu “>”);
cu numele simplu, dar numai obiectele din catalogul curent, sau cu un nume calificat – obiectele incluse în descendenţii
acestui catalog.
Acest mod de desemnare permite determinarea oricărui fişier; totuşi, numele universal poate fi prea lung pentru
obiectele situate la o mare adâncime în ierarhie. Pentru a permite o desemnare mai simplă a obiectelor, care nu sunt
incluse în relaţia de descendenţă a catalogului curent, sunt definite două extensii pentru construcţia numelor:

rădăcina

... utilizatori lib_sistem

SYS ... Aplicaţii

cataloagele
Corina ... Alex Victor ... Eugen ... utilizatorilor

catalog
doc test doc ... fiş_exe

demo
fişier
program
în Pascal
legătură

Fig.5.6. Organizare arborescentă a unui sistem de gestiune a fişierelor


1) Desemnarea părintelui. Prin convenţie, un simbol special (“<” în Multics, “..” în Unix) desemnează în orice
catalog diferit de rădăcină, tatăl catalogului dat. Utilizarea poate fi iterată (“<<” desemnează bunelul, etc.). Pot
fi de asemenea desemnate simplu obiecte incluse în cataloagele “frate” sau ”verişor” ai catalogului curent.
2) Creare de legături. Numim legătură asocierea unui nume simplu (numele legăturii) şi a unui alt nume (nume
obiectiv sau scop). Crearea unei legături într-un catalog introduce aici numele simplu (numele legăturii), care
trebuie să fie unic în cadrul catalogului dat. Această operaţie este o legare prin înlănţuire: când numele legăturii
este interpretat, în mediul catalogului unde a fost creat, el este înlocuit prin numele obiectiv.
Posibilitatea creării legăturilor modifică caracterul pur arborescent al desemnării, ceea ce poate crea probleme
delicate necesităţii de a avea mai multe căi de acces la un obiect.
5.2.3. Legarea fişierelor cu fluxurile de intrare-ieşire
Un program schimbă informaţii cu mediul exterior prin intermediul unor operaţii de intrare-ieşire. care permit
comunicarea cu un fişier sau un periferic. În momentul elaborării programului nu este încă cunoscut cu care fişier sau
periferic se vor produce intrările-ieşirile; adesea este necesar să se utilizeze fişiere sau periferice, care diferă de la o
execuţie la altă. Din aceste considerente este util să se poată întârzia legătura unui program cu fişierele sau perifericele
pe care acesta le utilizează. În acest scop se introduce noţiunea de flux de intrare-ieşire.
Un flux de intrare-ieşire este un obiect, care posedă toate caracteristicile unui periferic de intrare-ieşire (nume,
operaţii de acces), dar care nu are o existenţă reală. Pentru a fi efectiv utilizat în transferul informaţiilor, un flux trebuie
să fie în prealabil legat, cu ajutorul unei operaţii, numite asociere, cu un fişier sau periferic. Transferul informaţiei,
descris de operaţiile asupra fluxului, vor fi executate asupra fişierului sau perifericului, asociat fluxului. Asocierea poate
fi modificată de la o execuţie la alta, însă textul programului, care face referinţă doar la numele fluxului, rămâne
invariant.
nume de flux nume de flux
nume de flux
fişier perif
nil descriptor descriptor descriptor
de flux de fişier de periferic

tampon procedură tampon procedură


(a) până la asociere de acces de acces

(b) după asociere la un fişier (c) după asociere la un periferic


Fig.5.7. Asocierea unui flux de intrare-ieşire

Victor Beşliu p.11 din 20


La realizarea asocierii este folosită legarea prin înlănţuire. Fiecărui flux i se asociază un descriptor. Operaţia de
asociere cere ca acest descriptor să conţină un pointer spre descriptorul fişierului sau perifericului, pe care îl asociază
fluxului. La execuţia unei operaţii de intrare-ieşire asupra fluxului, o direcţionare permite obţinerea suportului
corespunzător (fig.5.7).
În schema, prezentată în fig.5.7 am presupus, că descriptorul fluxului permite să se ajungă până la procedura şi zona
tampoanelor, utilizate pentru intrări-ieşiri. Legătura respectivă poate fi realizată, în dependenţă de sistem, la asocierea
fluxului sau la o fază ulterioară deschiderii.
Asemeni editării legăturilor, asocierea fluxurilor utilizate de un program poate fi realizată la două dintre etapele de
derulare:
 înaintea execuţiei programului, cu ajutorul unei instrucţiuni a limbajului de comandă,
 în timpul execuţiei, cu ajutorul unei primitive de sistem, implementată printr-un apel de supervizor.
Sistemele de operare oferă utilizatorilor un set de fluxuri predefinite şi asociate iniţial, în mod implicit, la periferice
determinate. De exemplu, un sistem interactiv utilizează un flux standard de intrare şi un flux standard de ieşire; în
momentul în care un utilizator este admis în sistem aceste fluxuri sunt asociate, implicit, la tastatură şi ecran. Ele pot fi
temporar reasociate fişierelor; în caz de eroare, asocierea implicită este în mod automat restabilită pentru a permite
utilizatorului să intervină.
Sistemele oferă de asemenea de obicei posibilitatea de a crea fluxuri noi, care se adaugă celor predefinite. Ca şi
asocierea, această creare poate fi cerută de o instrucţiune sau de un apel al regimului supervizor.
Exemplul 5.6. Fluxuri în sistemul Unix. În acest sistem sunt utilizate două tipuri de nume: nume externe, care sunt identificatori construiţi în mod
ierarhic, şi nume interne, care sunt numere întregi. Numele externe sunt interpretate într-un mediu global tuturor proceselor, numele
locale într-un mediu propriu fiecărui proces. Crearea şi interpretarea numelor locale sunt descrise în 6.6.
Numele locale sunt utilizate şi pentru desemnarea fluxurilor. Prin convenţie, numele locale 0, 1 şi 2 desemnează fluxul standard de
intrare, fluxul standard de ieşire şi fluxul mesajelor de eroare, respectiv. Orice instrucţiune este executată de un proces creat în acest
scop şi care foloseşte aceste trei fluxuri. Iniţial, fluxurile 0 şi 1 sunt în mod implicit asociate respectiv la claviatura şi ecranul
utilizatorului, care a creat procesul.
Sistemul pune la dispoziţie următoarele operaţii asupra fluxurilor:
1) Reasocierea fluxurilor. Dacă flux_in şi flux_out desemnează, respectiv, un flux de intrare şi un flux de ieşire, iar id_fişier este un
identificator de fişier, instrucţiunile
flux_in < id_fişier
şi flux_out > id_fişier
reasociază, respectiv, flux_in şi flux_out la id_fişier. Dacă flux_in şi flux_out nu sunt specificate în instrucţiune, ele iau
în mod implicit valorile 0 şi 1 respectiv, adică cele corespunzătoare fluxurilor standard. Astfel, instrucţiunea:
a < sursă > destinaţie
provoacă execuţia instrucţiunii a, după ce în prealabil au fost reasociate fluxurile standard de intrare şi ieşire la fişierele sursă şi
destinaţie.
2) Crearea mecanismelor pipe. Un tub (pipe în Unix) este un tampon, care permite ca două procese să comunice conform schemei
producător-consumator. El conţine un flux de intrare (depozit) şi unul de ieşire (retragere) şi poate fi creat în două feluri:
a) în mod implicit, prin intermediul limbajului de comandă. O instrucţiune de forma
a|b
în care a şi b sunt instrucţiuni elementare cu următorul efect:
i) să se creeze două procese, fie proc_a şi proc_b, împuternicite să execute a şi b, respectiv,
ii) să se creeze un tub,
iii) să se reasocieze fluxul standard a proc_a la intrarea tubului, iar fluxul standard de ieşire la ieşirea tubului.
Cele două procese vor funcţiona acum în modul producător-consumator. Pot fi create mai multe tuburi în serie (a|b|c...); este de
asemenea posibil înlănţuirea unei suite de instrucţiuni în “pipe-line”. Această construcţie poate fi combinată cu reasocierea
fluxurilor (exemplu: <sursă a|b...>destinaţie).
b) în mod explicit, prin apelarea regimului supervizor. Un apel al supervizorului permite crearea unui tub şi obţinerea numelor
locale pentru intrarea şi ieşirea sa; aceste nume pot apoi fi asociate fişierelor. Aceste nume locale sunt cunoscute procesului
apelant şi tuturor descendenţilor lui. ◄

5.3. Legarea programelor şi datelor


5.3.1. Etapele de viaţă a unui program
Am prezentat mai sus diferite momente în care poate fi stabilită legătura dintre instrucţiunile şi datele unui program.
Vom prezenta în rezumat cele mai frecvente scheme înainte de a trece la realizarea lor. Această prezentare vizează, în
principal, expunerea folosirii noţiunii de legare, fără a detalia aspectele tehnice ale funcţionării unui încărcător sau
editor de legături.
1) Program interpretat
date

program sursă program interpretat rezultat


2) Program compilat
a) program unic
program program obiect
translator program obiect încărcător (adrese absolute)
sursă (adrese relative)

date calculatorul

Victor Beşliu p.12 din 20


rezultatul
Compararea acestor două scheme pune în evidenţă diferenţa importantă între interpretare şi compilare: modificarea
unui program interpretat are efect imediat, în timp ce în cazul compilării suntem nevoiţi să parcurgem toate etapele,
începând cu translatarea.
b) program compus
Constituirea unui program unic, pornind de la programe construite independent, se realizează pornind de la
programe obiect în adrese relative (deplasabile), adică obţinute după translatare, prin legarea referinţelor externe.
Această operaţie poate fi combinată cu încărcarea (ceea ce nu este obligator). O condiţie este ca formatul modulelor
obiect în adrese relative să respecte o convenţie comună la care trebuie să se conformeze translatoarele; anume sub
această formă programele comune se vor păstra în memorie.
program obiect în
adrese relative
încărcător,
program obiect în editor de program obiect în
adrese relative legături adrese absolute

program obiect în
adrese relative

5.3.2. Funcţionarea unui încărcător


Un încărcător este destinat să pună în formă absolută un program (sau modul) obiect în adrese relative. Această
operaţie constă în înlocuirea tuturor adreselor relative la originea modulului prin adrese absolute. Pentru aceasta se va
efectua un lucru preliminar în faza de translatare: înregistrărilor modulului obiect, care conţin o adresă translatabilă, li
se va ataşa un indicator, care va fixa poziţia acestei adrese în interiorul înregistrării (dacă poziţia nu este specificată în
mod implicit). Adresele translatabile pot să apară:
 sau în câmpul de adresă al instrucţiunii,
 sau în cazul datelor, în ”expresii pentru calcularea adresei”, destinate a fi utilizate ca relaţii de direcţionare sau
să fie încărcate în registrele de bază.
Încărcătorul utilizează metoda substituţiei: orice adresă relativă a este înlocuită prin adresa absolută a+originea,
unde originea este adresa absolută începând cu care este încărcat modulul. Pentru un calculator cu registre de bază acest
lucru este simplificat considerabil; reamplasarea este realizată la execuţie prin calcularea adresei, cu condiţia că
registrele de bază sunt încărcate corect.
Dacă programul încărcat trebuie imediat executat, o funcţie suplimentară a încărcătorului va determina adresa
absolută de la care trebuie să înceapă execuţia. Această adresă este adesea fixată prin convenţie (de exemplu, se va
porni de la primul amplasament al modulului). Pentru cazuri mai generale, modulul poate avea mai multe puncte de
intrare, desemnate cu ajutorul identificatorilor; el va conţine în acest caz un tabel al punctelor de intrare, construit de
translator, care asociază o adresă relativă fiecărui identificator. Aceste adrese sunt transformate în adrese absolute;
adresa punctului de intrare este determinată pornind de la identificator prin intermediul unei căutări în tabel.
Pentru a ilustra prezentăm un format posibil al unui modul obiect translatabil şi programul corespunzător al
încărcătorului.
en-tête <id_modul, lungime,...>
...
corpul modulului <adr, n, r, cod>
...
...
tabelul punctelor de intrare <identificator, adresă relativă>
...
O înregistrare a corpului modulului este de forma <adr, n, r, cod> cu
adr : adresa relativă a codului <cod> în modul
n : lungimea lui <cod> în octeţi
r : 1 sau 0 (cod translatabil sau nu)
cod : n octeţi ai programului.
Algoritmul încărcătorului poate fi următorul:

Victor Beşliu p.13 din 20


Parametrii de apel : identitatea modulului (numele fişierului)
: adr_încărcare (adresa absolută de încărcare)
: id_început (identificatorul punctului de intrare)
citire(en-tête);
<verificare dacă lungimea permite încărcarea>
repeat
citire înregistrare; -- <adr, n, r, cod>
if r = 1 then
translatare(cod)
endif;
adr_implantare := adr + adr_încărcare;
<ordonarea codului pornind de la adr_implantare>
until corp de modul epuizat
citire(tabel de puncte de intrare);
căutare(id_început,adr_exe);
if eşec then
<ieşire eroare> -- sau alegerea unei adrese implicite
else -- implicit
adr_exe := adr_exe + adr_încărcare
endif;
<ramificaţie la adresa adr_exe>
Procedura translatare(cod) modifică <cod>-ul, translatând adresele relative ale acestuia: fiecare adresă relativă este
incrementată cu adr_încărcare. Poziţia acestor adrese în interiorul înregistrării trebuie, deci, să fie cunoscută (cel mai
des, fiecare înregistrare conţine o instrucţiune unică în care adresa ocupă o poziţie fixă).
Utilizarea unei adresări cu registre de bază simplifică lucrul încărcătorului, translatarea fiind realizată automat,
înaintea execuţiei, încărcând într-un registru de bază adresa de implantare a programului. Folosirea a mai multor
registre de bază permite reimplantarea independentă a mai multor fragmente de program (de exemplu, procedurile de o
parte, datele de alta). Unicele informaţii care trebuie să fie translatate de către încărcător sunt expresiile adreselor,
utilizate pentru încărcarea registrelor de bază.
5.3.3. Funcţionarea unui editor de legături
Vom descrie mai jos principiile de funcţionare a unui editor de legături presupunând, că el mai îndeplineşte şi
încărcarea. Editorul de legături primeşte la intrare un set de module obiect translatabile şi construieşte la ieşire un modul
obiect absolut. El este obligat, deci, pentru fiecare modul obiect:
1) să determine adresa de implantare a acestuia,
2) să îndeplinească modificările informaţiilor translatabile,
3) să realizeze legarea referinţelor externe.
5.3.3.1. Legarea prin substituţie
În cazul editării legăturilor prin substituţie fiecare referinţă la un obiect extern în cadrul unui modul este înlocuită
prin adresa absolută a acestui obiect.
Prin definiţie, un modul A utilizează un modul B dacă programul lui A face referinţe la obiecte, conţinute în B.
Deoarece graful relaţiei utilizează poate conţine circuite, editarea legăturilor foloseşte un algoritm în doi paşi. Primul
pas construieşte planul implantării modulelor şi determină adresa absolută a tuturor obiectelor externe; al doilea pas
soluţionează referinţele la aceste obiecte.
Formatul modulelor obiect, indicate în 5.3.2, este completat de un tabel de referinţe externe, care conţine
identificatorii tuturor obiectelor externe, folosite de modul; o referinţă externă din program este înlocuită printr-o
referinţă la intrarea corespunzătoare a tabelului. Această ordonare permite să fie păstrat doar un exemplar a fiecărui
identificator extern şi evită dispersarea acestor identificatori în corpul modulului.
Pentru prezentarea unui algoritm al editorului de legături indicăm un format posibil al modulelor translatabile.
en-tête <id_modul, lungime,...>
...
tabelul referinţelor externe <identificator extern>
...
...
corpul modulului (program) <adr, n, r, cod>

Victor Beşliu p.14 din 20


...
...
tabelul definiţiilor externe <identificator, adresă relativă>
...
O înregistrare din corpul modulului are acum următoarea semnificaţie:
adr : adresa relativă a codului <cod>
n : lungimea lui <cod> în octeţi
r : indicator de reimplantare a adresei
cod : fragment de program sau date
0 : informaţie absolută
1 : informaţie translatabilă (internă)
< 0 : informaţie externă, referinţa n0-r în tabelul referinţelor externe.
Comunicarea între cei doi paşi ai editorului de legături este asigurată de un tabel global de identificatori externi,
construit la primul pas, şi care pentru un obiect extern conţine cuplul
(identificator, adresă absolută)
Specificăm două proceduri de acces la acest tabel:
intrare(id, val) -- introduce cuplul (id, val) în tabel
căutare(id, val) -- caută un cuplu cu identificatorul id; în caz de eşec (nu a fost
găsit) val este fără semnificaţie, altfel returnează valoarea
asociată lui val.
Parametrii de intrare ai unui editor de legături sunt:
 adresa de încărcare a modulului executabil (adr_încărcare),
 numele fişierelor modulelor, care se vor lega,
 bibliotecile în care vor fi căutate referinţele nesatisfăcute.
Programul primului pas va fi de forma:
adr_init := adr_încărcare -- adresa începutului modulului
repeat -- iteraţii asupra modulului
citire(en-tête); -- (id_modul,lungime)
<tratare en-tête>;
repeat -- iteraţii asupra referinţelor externe
citire(id_ref);
<tratare ref_externe>;
until tabel de referinţe epuizat
trece(corpul modulului); -- pas de tratare
repeat -- iteraţii asupra definiţiilor externe
citire(id_def,adr_def);
<tratare_def_externe>
until tabel def epuizat
until mai există module de tratat;
<sfârşit pas 1>
În timpul constituirii tabelului externilor valoarea val=0, asociată unui identificator semnifică, prin convenţie, că
aceasta a fost întâlnită în cel puţin o referinţă, dar nu încă şi într-o definiţie. Avem, deci, o referinţă (provizoriu)
nesatisfăcută. Precizăm procedurile:
<tratare_ en-tête>:
căutare(id_modul,val); -- numele modulului
if eşec or val=0 then -- referinţă nouă
intrare(id_modul,adr_init)
else
eroare(“definiţie dublă”)
endif;
baza:=adr_init; -- începutul modulului curent
adr_init:=adr_init+lungime -- începutul modulului următor
<verificare dacă lungimea permite încărcare>
<tratare_def_externe> :
căutare(id_def,val);

Victor Beşliu p.15 din 20


if eşec or val=0 then
intrare(id_def,baza+adr_def) -- adresă absolută a definiţiei externe
else
eroare(“definiţie dublă”)
endif
<tratare_ref_externe> :
căutare(id_ref,val);
if eşec or val=0 then
intrare(id_ref,val) -- acţiune vidă, dacă referinţa este deja prezentă
endif
<sfârşit pas 1>:
pentru toate(id_ref,val) pentru care val=0 -- referinţă nesatisfăcută
<să se caute în biblioteca specificată modulul, care conţine id_ref şi să se determine
adresa sa de implantare (acest modul va fi încărcat în memorie cu programul)>
<să se calculeze val şi intrare(id_ref,val)
La trecerea pasului 1 tabelul global al externilor este construit. Cu excepţia cazurilor de eroare, orice identificator al
acestui tabel este asociat unei adrese absolute de implantare.
Rolul pasului 2 este de a efectua translatarea adreselor şi încărcarea în memorie, utilizând informaţiile găsite în
tabelul externilor.
<pasul 2>:
repeat -- iteraţii asupra modulului
citire(en-tête);
căutare(id_modul,val);
baza:=val;
citire(tabel de referinţe externe);
repeat -- iteraţii asupra tabelului de referinţe
<tratare_înregistrare>
until corpul mudulului epuizat
until mai există module de tratat;
<sfârşit pas 2>;
Precizăm procedurile fazei a doua:
<tratare_înregistrare>:
adr_implantare:=adr+baza;
if r=1 then -- referinţă internă translatabilă
<translatare_înregistrare(baza)>
else
if r<0 then -- referinţă externă
id_ref:=<intrarea n0 – r în tabelul referinţelor externe>;
căutare(id_ref,val);
translatare_înregistrare(val);
endif
endif; -- terminat, dacă r=0
<încărcare înregistrare de la adr_implantare>
<sfârşit pas 2>:
căutare(id_intrare,val);
if eşec or val=0 then
eroare(“adresă necunoscută de execuţie”) -- sau alegere implicită (default)
else
adr_exe:=val
endif;
<imprimarea conţinutului tabelului externilor> -- “diagrama implantării map”
<ramificaţie la adresa adr_exe>
Imprimarea tabelului externilor sub forma diagramei de implantare (eng. map) permite semnalizarea erorilor
(definiţii duble, referinţe nesatisfăcute) şi facilitarea punerii la punct şi localizării informaţiilor în memorie. Diagrama
de implantare este o secvenţă de linii de forma:

Victor Beşliu p.16 din 20


<identificator extern> <adresă absolută> <o diagnoză eventuală>
5.3.3.2. Legare prin înlănţuire
1) Vector de transfer
Metoda vectorului de transfer este relativ puţin utilizată pentru programele compilate, totuşi descriem principiile
acestei tehnici, deoarece:
 ea este aplicabilă în cazul programelor interpretate sau celor combinate,
 ea permite introducerea într-o formă primitivă a noţiunii de segment de legătură, noţiune dezvoltată în
continuare.
Fiecare modul conţine un tabel, numit vector de transfer, care are câte o intrare pentru o referinţă externă. În corpul
modulului fiecare referinţă la un obiect extern este înlocuită printr-o referinţă indirectă la intrarea respectivă a
vectorului de transfer. Prima trecere a editării legăturilor are loc ca şi în 5.3.3.1; a doua trecere constă în asocierea
intrărilor vectorilor de transfer din diferite module cu adresele corespunzătoare a obiectelor externe. La execuţie,
accesul la un obiect extern este, deci, realizat prin direcţionarea via un cuvânt al vectorului de transfer. Această metodă
este costisitoare în spaţiu (vectorii de transfer trebuie păstraţi) şi în timp (referire indirectă). Ea convine pentru cazul
înlocuirii unui modul într-un program deja legat; anume din această cauză metoda vectorilor de transfer prezintă interes
pentru programele interpretate sau pentru sistemele de depanare.
2) Registre de bază
Ca şi în cazul încărcătorului, adresarea cu ajutorul registrelor de bază simplifică lucrul editorului de legături. Există
două moduri distincte de utilizare a acestor registre:
1. Registrele de bază sunt accesibile utilizatorilor: în acest caz sunt definite convenţii de utilizare care permit, de
exemplu, folosirea registrelor de bază specificaţi pentru a adresa un subprogram, o zonă de date, un bloc de
parametri etc. Aceste convenţii sunt implementate de către translatoare sau direct de către utilizatori, dacă aceştia
programează în limbaj de asamblare.
2. Registrele de bază sunt administrate de sistemul de operare şi sunt inaccesibili utilizatorilor. În acest caz,
sistemul asociază un registru de bază fiecărui fragment independent (program sau zonă de date) şi asigură
realocarea acestor registre, dacă numărul lor este insuficient.
În ambele cazuri, lucrul unui editor de legături constă în calcularea expresiilor adreselor, care vor fi încărcate în
registrele de bază. În al doilea caz, printre altele, este necesar să fie introduse instrucţiunile de încărcare a acestor
registre (sub formă de apel al regimului supervizor) în modulele obiect.

5.4. Mecanisme de gestiune a obiectelor


5.4.1. Segmentarea
Utilizarea registrelor de bază permite reimplantarea independentă în memorie a procedurilor şi datelor unui
program. Totuşi, acest mecanism are două restricţii:
 pentru utilizator: necesitatea de a se conforma convenţiilor de folosire a registrelor de bază,
 pentru sistemul de operare: necesitatea gestiunii alocării registrelor de bază, dacă acestea sunt în număr
insuficient.
Aceste restricţii vor fi eliminate, dacă utilizatorul ar putea numi cu un nume la alegere proprie “elementele de
informaţie” şi dacă sistemul ar dispune de un mecanism de plasare în memorie şi de legare pentru a administra astfel de
elemente. Anume la aceste două întrebări încearcă să răspundă segmentarea.
Un segment este p mulţime de informaţii considerată ca o unitate logică şi desemnată de un nume; reprezentarea sa
ocupă o mulţime de amplasamente adiacente (contigue). Un segment poate fi de lungime variabilă. În interiorul unui
segment informaţiile sunt desemnate cu ajutorul unei deplasări, care este o adresă relativă în raport cu începutul
segmentului. O informaţie este desemnată de un cuplu (nume de segment, deplasare), care se numeşte adresă
segmentată (fig. 5.8).
Este important să se noteze, că segmentele sunt reciproc independente atât din punct de vedere fizic, cât şi logic.
Fizic, un segment poate fi implantat la o adresă oarecare, cu condiţia să fie ocupate adrese adiacente. Logic, diferite
segmente, administrate de un sistem de operare, sunt independente şi trebuie considerate ca tot atâtea spaţii de adresare
liniare distincte. Chiar dacă numele segmentelor sunt frecvent reprezentate de numere întregi consecutive, nu există o
relaţie de adiacenţă între ultimul amplasament al segmentului i şi primul amplasament al segmentului i+1. Folosirea
unei deplasări negative sau mai mare decât lungimea segmentului utilizat este o eroare de adresare.
segmentul 1 segmentul i segmentul n

Victor Beşliu p.17 (seg_i, d) din 20


Segmentele sunt utilizate:
 ca unităţi de secţionare logică a unui program, pentru reprezentarea, de exemplu, a diferitor proceduri, module,
date legate logic (tabele, structuri),
 ca unitate de partajare între mai mulţi utilizatori,
 ca unitate de protecţie (consecinţă a partajării): segmentul este entitatea la care sunt ataşate drepturile de acces.
Realizarea adresării segmentate utilizează principiul, descris în figura 5.9.
eroare
adresă segmentată d≥L
s d
d<L
Registru bază al tabelului segmentelor

Memoria fizică

s d
L
L a

Tabelul segmentelor

Fig.5.9. Realizarea adresării segmentate


Fiecărui segment îi este asociat un descriptor; el conţine (cel puţin) adresa de implantare a segmentului, lungimea sa
şi drepturile de acces. Descriptorii se află în tabelul segmentelor; un segment este desemnat de indicele descriptorului
său în acest tabel. Există mai multe posibilităţi de realizare, care sunt dictate de organizarea tabelelor descriptorilor:
1) Tabel unic. Toţi descriptorii sunt păstraţi într-un singur tabel; numele unic al unui segment este indicile
descriptorului său din acest tabel. Descriptorul conţine o listă de acces, care defineşte drepturile fiecărui
utilizator al segmentului. Această metodă permite partajarea segmentelor, însă toţi utilizatorii sunt obligaţi să
utilizeze unul şi acelaşi nume unic, ceea ce adesea nu este comod.
2) Tabele multiple. Există un tabel distinct pentru fiecare mediu; într-un mediu oarecare numele segmentului (dacă
este accesibil în acest mediu) este indicele descriptorului său în acest tabel local. Un tabel accesibil în mai multe
medii are mai mulţi descriptori şi mai multe nume distincte.
3) Organizare mixtă. Fiecare segment posedă un descriptor central, care conţine caracteristicile sale de implantare
fizică (lungimea, adresa). El mai posedă un descriptor local în fiecare mediu în care este accesibil; acest
descriptor conţine informaţiile proprii mediului (subliniem drepturile de acces) şi punctează pe descriptorul
central. Un segment are în acest mod un nume distinct pentru fiecare mediu, iar caracteristicile fizice sunt
situate într-un loc unic, descriptorul central.
Figura 5.10 prezintă aceste moduri de organizare.

nume local

nume
global

Victor Beşliu p.18 din 20


5.5. Exerciţii la capitolul 5
Exerciţiul 5.1. Examinaţi problemele, ce ţin de retragerea drepturilor de acces la un obiect într-un mecanism de
protecţie. Se doreşte să se permită unui proces proprietar al unui obiect posibilitatea de a acorda şi a retrage selectiv
drepturile de acces la acest obiect. Examinaţi separat cazul în care acordarea drepturilor este tranzitivă (un proces poate
la rândul său să retransmită drepturile pe care el le-a primit). Indicaţii: două mecanisme necesare sunt redirecţionarea şi
crearea unor legături inverse.
Exerciţiul 5.2. În schema integrării unui volum amovibil în cadrul unui catalog al unui sistem de gestiune a fişierelor
examinaţi următoarele probleme:
 posibilitatea de a crea legături, care să nu treacă prin rădăcina volumului,
 posibilitatea de a crea fişiere multivolum.
Exerciţiul 5.3. Specificând structura datelor necesare, precizaţi realizarea procedurilor de montare şi demontare a unui
volum amovibil.
Exerciţiul 5.4. Dacă vom reprezenta catalogul unui sistem de gestiune a fişierelor printr-un graf nodurile căruia sunt
cataloage şi fişiere, iar arcele – relaţiile de desemnare, sistemul de fişiere din Multics (fără a ţine seama de legături)
poate fi reprezentat printr-o arborescenţă şi cel din Unix (în care nu există diferenţă între legături şi nume simple) printr-
un graf fără circuite (subgraful catalogului rămânând o arborescenţă).
Examinaţi avantajele, inconvenienţele şi problemele de realizare, care vor apare pentru structuri mai generale.
Exerciţiul 5.4. Propuneţi o schemă care ar permite editarea legăturilor într-o singură fază conform principiului lanţului
de reluare, utilizat în asambloarele cu o singură fază.
Exerciţiul 5.5. Se propune să se realizeze un mecanism pentru executarea programelor modulare pe un calculator cu
adresare segmentată. Un modul conţine o mulţime de variabile globale şi proceduri, care accesează aceste variabile.
Procedurile unui modul M pot fi apelate dintr-un alt modul, care utilizează M. Ne vom limita la un proces unic.
Un segment este identificat prin indicele descriptorului său într-un tabel general al segmentelor. Unui modul îi sunt
asociate două segmente: unul conţine codul procedurilor sale, altul – variabilele sale globale. Două registre de bază
RBP şi RBD conţin numerele acestor două segmente pentru modulul, care este în curs de execuţie. Contorul ordinal CO
conţine deplasarea instrucţiunii curente în segmentul procedură. Un segment special serveşte ca stivă de execuţie;
parametrii procedurilor sunt pasaţi prin valori în stivă.
Procedurile modulelor, utilizate de un modul M, sunt numite externe pentru M. Desemnarea lor face apel la un segment
de legătură, fiecare amplasament n al căruia conţine numerele segmentelor procedură şi date ale unui modul E, folosit
de M. Un registru de bază RBL conţine numărul segmentului de legătură a modulului curent. Segmentul procedură a
unui modul M este organizat după cum urmează:
 primul amplasament (deplasarea 0) conţine adresa de bază a segmentului de legătură a modulului M,
 următoarele m amplasamente conţin deplasările punctelor de intrare a celor m proceduri ale modulului,
 restul segmentului conţine codul executabil al procedurilor.

punct de
intrare
proceduri proceduri

date date
registre segment de
Victor Beşliu de bază p.19
legătură din 20
modul apelant modul apelat
În programul unui modul M apelul procedurii cu numărul k a modulului, descris de amplasamentul cu numărul n al
segmentului de legătură este realizat cu ajutorul unei instrucţiuni call n, k.
1) Permite oare această schemă realizarea mai multor module care ar avea proceduri comune şi variabile globale
proprii? Care sunt avantajele unei atare posibilităţi?
2) Descrieţi detaliat secvenţa operaţiilor, care vor fi executate la apelul unei proceduri externe a unui modul şi la
returul din procedură.
call n, k
3) Permite oare această schemă editarea dinamică a legăturilor? Descrieţi structurile de date necesare şi principiul de
realizare.

Victor Beşliu p.20 din 20


6. Gestiunea fişierelor ............................................................................................................................................................ 2
6.1. Noţiuni generale .......................................................................................................................................................... 2
6.1.1. Funcţiile unui sistem de gestiune a fişierelor ....................................................................................................... 2
6.1.2. Organizarea generală a unui sistem de gestiune a fişierelor ................................................................................. 2
6.2. Organizarea logică a fişierelor .................................................................................................................................... 3
6.2.1. Introducere ........................................................................................................................................................... 3
6.2.2. Acces secvenţial ................................................................................................................................................... 4
6.2.3. Acces direct .......................................................................................................................................................... 5
6.2.3.1. Cheie unică.................................................................................................................................................... 5
6.2.3.2. Chei multiple ................................................................................................................................................. 7
6.3. Organizarea fizică a fişierelor ..................................................................................................................................... 8
6.3.1. Implantare secvenţială.......................................................................................................................................... 8
6.3.2. Implantare non contiguă....................................................................................................................................... 9
6.3.2.1. Blocuri înlănţuite........................................................................................................................................... 9
6.3.2.2. Tabele de implantare ..................................................................................................................................... 9
6.3.3. Alocarea memoriei secundare ............................................................................................................................ 11
6.4. Realizarea funcţiilor de acces elementar ................................................................................................................... 12
6.4.1. Organizarea descriptorilor.................................................................................................................................. 12
6.4.1.1. Localizarea fizică ........................................................................................................................................ 12
6.4.1.2. Informaţii de utilizare .................................................................................................................................. 12
6.4.2. Crearea şi distrugerea ......................................................................................................................................... 12
6.4.2.1. Crearea ........................................................................................................................................................ 12
6.4.2.2. Distrugerea .................................................................................................................................................. 13
6.4.3. Deschiderea şi închiderea ................................................................................................................................... 13
6.4.3.1. Deschiderea ................................................................................................................................................. 13
6.4.3.2. Închiderea .................................................................................................................................................... 14
6.4.4. Acces elementar la informaţii ............................................................................................................................ 14
6.5. Securitatea şi protecţia fişierelor ............................................................................................................................... 15
6.5.1. Despre securitate şi protecţie ............................................................................................................................. 15
6.5.2. Securitatea fişierelor .......................................................................................................................................... 15
6.5.2.1. Redundanţa internă şi restabilirea informaţiilor .......................................................................................... 15
6.5.2.2. Salvare periodică ......................................................................................................................................... 16
6.5.3. Protecţia fişierelor .............................................................................................................................................. 16
6.5.4. Autentificarea în Windows NT .......................................................................................................................... 16
6.5.4.1. Funcţia LogonUser .................................................................................................................................... 17
6.5.4.2. Autentificare cu ajutorul Security Support Provider Interface ...................................................... 19
6.5.4.3. Funcţia NetUserChangePassword .......................................................................................................... 20
6.6. SGF din sistemul de operare Unix ............................................................................................................................ 21
6.6.1. Caracteristici generale ........................................................................................................................................ 21
6.6.2. Organizarea datelor ............................................................................................................................................ 21
6.6.2.1. Descriptorii ................................................................................................................................................. 21
6.6.2.2. Implantarea fizică ........................................................................................................................................ 22
6.6.2.3. Administrarea perifericelor ......................................................................................................................... 23
6.6.2.4. Volume amovibile ....................................................................................................................................... 23
6.6.3. Funcţionarea şi utilizarea ................................................................................................................................... 23
6.6.3.1. Gestiunea descriptorilor. Nume locale ........................................................................................................ 23
6.6.3.2. Primitive de acces ....................................................................................................................................... 24
6.6.3.3. Protecţia fişierelor în UNIX ........................................................................................................................ 24
6.7. Exerciţii la capitolul 6 ............................................................................................................................................... 25

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.1 din25


6. Gestiunea fişierelor
Acest capitol este consacrat studierii detaliate a gestiunii fişierelor în sistemele de operare: organizarea logică,
reprezentarea informaţiei, realizarea funcţiilor de acces, protecţia şi securitatea. Noţiunile menţionate sunt ilustrate cu
exemple de gestionare a fişierelor în sistemele de operare Windows şi Unix.

6.1. Noţiuni generale


6.1.1. Funcţiile unui sistem de gestiune a fişierelor
Numim fişier o mulţime de informaţii, formate cu scopul păstrării şi utilizării lor în cadrul unui sistem informatic.
Fişierele au de obicei o durată de viaţă superioară timpului de execuţie a unui program sau duratei unei sesiuni de lucru:
ca rezultat, suportul lor permanent este memoria secundară. Fişierul este un obiect: el posedă un nume, care permite
desemnarea sa, are asociate funcţii de acces, adică operaţii, care permit crearea sau distrugerea, consultarea sau
modificarea informaţiilor, etc. Componentele unui sistem de operare, care asigură posibilitatea păstrării fişierelor şi
realizează funcţiile de acces se numeşte sistem de gestiune a fişierelor (SGF).
Utilizatorul unui sistem informatic organizează informaţiile conform necesităţilor proprii, impunându-le o structură
sau organizare, numită logică; funcţiile de acces sunt exprimate cu ajutorul acestei structuri. Reprezentarea informaţiilor
fişierelor în memoria secundară (adresa de implantare, codificarea informaţiei) determină organizarea fizică a fişierelor.
Reprezentarea structurii logice a fişierelor printr-o organizare fizică este sarcina SGF.
Adesea un fişier este definit ca o colecţie de informaţii elementare de aceeaşi natură, numite înregistrări sau articole
(eng. “items” sau “records”). O înregistrare poate ea însăşi avea o structură mai complicată (este introdusă noţiunea de
câmpuri pentru desemnarea unor componente). Exemple de organizare logică sunt date în 6.2.
Funcţiile principale, asigurate de un sistem de gestiune a fişierelor sunt:
 crearea unui fişier (definirea numelui, alocarea eventuală a spaţiului),
 distrugerea unui fişier (eliberarea numelui şi a spaţiului, alocat fişierului),
 deschiderea unui fişier (declararea intenţiei de a folosi fişierul cu ajutorul funcţiilor de acces şi a drepturilor
specificate),
 închiderea unui fişier deschis (interzicerea oricărui acces ulterior),
 diverse funcţii de consultare şi modificare: citire, scriere, modificarea lungimii, etc. (detaliile legate de aceste
funcţii depind de organizarea logică a fişierului).
Aceste funcţii sunt materializate prin operaţiile de bază, prezente în toate SGF. Trebuie să adăugăm aici diverse
funcţii detaliile cărora depind de organizarea sistemului de gestiune a fișierelor: specificarea şi consultarea drepturilor de
acces, consultarea caracteristicilor (data creării, modificării, etc.), operaţii asupra numelui (schimbarea numelui, etc.).
Păstrarea fişierelor şi realizarea funcţiilor de acces impune SGF să aibă în şarjă:
 gestiunea suporturilor fizice ale informaţiei, ascunzând unui utilizator obişnuit detaliile organizării fizice;
 securitatea şi protecţia fişierelor, adică garantarea integrităţii,confidențialității și accesibilității în caz de accident
sau de rea voinţă şi respectarea regulilor stabilite de utilizare (drepturi de acces, condiţii de partajare).
Într-un sistem de operare SGF joacă rolul central, deoarece el trebuie să comande cea mai mare parte a informaţiilor
utilizatorilor, cât şi a sistemului propriu-zis. SGF are legături strânse cu sistemul de intrare-ieşire, este adesea convenabil
conceptual să nu se facă distincţie între fişiere şi unităţile periferice ca suport sursă sau destinaţie a informaţiei în timpul
execuţiei unui program. În sistemele cu dispozitive speciale de adresare şi desemnare a informaţiei, cum ar fi memoria
virtuală segmentată sau paginată, SGF trebuie să fie legat de aceste mecanisme, din care cauză pot avea loc confuzii.
6.1.2. Organizarea generală a unui sistem de gestiune a fişierelor
SGF realizează corespondenţa între organizarea logică şi organizarea fizică a fişierelor. Organizarea logică,
unică cunoscută de utilizatorii obișnuiți, este determinată de consideraţii de comoditate şi universalitate. Organizarea
fizică, legată de suporturile de memorie utilizate, este determinată de considerente de economisire a spaţiului şi
eficacitatea accesului. Aceste două organizări sunt, în genere, diferite fiecare fiind definite prin structuri de date proprii,
controlate de SGF. Drept rezultat, SGF sunt construite conform unei structuri ierarhice, care are cel puţin două niveluri
corespunzătoare celor două organizări, menţionate mai sus: orice acţiune, definită la nivelul logic este interpretată de un
set de acţiuni la nivelul fizic. Pentru facilitarea concepţiei sau pentru a răspunde unor necesităţi specifice (portabilitate, de
exemplu) pot fi definite şi unele nivele intermediare.
Pentru separarea organizării fizice de organizarea logică este recomandabil să fie introdusă o organizare intermediară,
care joacă rol de interfaţă. Această organizare intermediară poate fi un segment, adică o suită de amplasamente adiacente,

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.2 din25


desemnate de valori întregi pozitive, numite adrese logice sau deplasări. Putem separa, în acest caz, în două etape
stabilirea corespondenţei între organizarea logică şi cea fizică (fig.6.1):
 traducerea numelor, specificate de funcţiile de acces la fişier, în adrese logice (un atare nume desemnează o
înregistrare sau un câmp al acesteia),
 traducerea adreselor logice în adrese fizice
.
funcţii de acces

desemnarea înregistrării adresă logică adresă fizică

Fig.6.1. Adresare logică într-un fişier


Această schemă reprezintă doar un model explicativ, adesea etapa intermediară este scurtcircuitată, funcţiile de acces
fiind traduse direct în adrese fizice. Mai notăm, că în cazul unui calculator cu memorie segmentată, reprezentarea
fişierelor se reduce la prima etapă: implantarea fizică a segmentelor este în şarja sistemului de operare.
Completând modelul de mai sus cu elementele, legate de desemnarea fişierelor din 5.2, construirea organizării SGF
poate fi reprezentată conform schemei din figura 6.2.
Funcţii de acces logic
Nume externe
şi locale Interfaţa
legarea numelor utilizatorului

Interpretarea Interpretarea
numelor locale numelor externe

Nume Realizarea
interne funcţiilor de acces
logic

Adrese Interfeţe interne la SGF


logice Realizarea
funcţiilor de acces
fizic

Adrese
fizice Alocarea Realizarea
memoriei I-E
secundare fizice

Fig.6.2. Organizarea unui sistem de gestiune a fişierelor

Această schemă nu trebuie să fie considerată drept un cadru rigid, care ţine cont de toate modurile de organizare a
SGF, ci doar ca un ghid pentru stabilirea funcţiilor şi structurilor de date mai frecvente. Planul adoptat pentru restul
capitolului va urma, într-un mod descendent, ierarhia astfel stabilită.

6.2. Organizarea logică a fişierelor


6.2.1. Introducere
Vom examina acuma modurile principale de organizare logică a unui fişier şi realizarea lor. La această fază a studiului
este suficient să traducem în adrese logice sau deplasare localizarea înregistrărilor, manipulate de funcţiile de acces;
determinarea adreselor lor fizice este examinată în 6.4.
Pentru specificarea organizării logice a unui fişier definim mai întâi o structură abstractă a fişierului. Pentru aceasta
vom utiliza un model simplu de descriere a datelor, care ne va permite să caracterizăm înregistrările, să definim
organizarea globală a fişierului şi să exprimăm funcţiile de acces. Vom preciza mai apoi reprezentarea concretă a
informaţiilor, care se conţin în fişier.
Un fişier este o mulţime de înregistrări (articole). Fiecărui articol îi este asociat un număr constant de n atribute,
aceleaşi pentru toate articolele. Un atribut este definit printr-un nume şi un domeniu de valori. Numele este pentru

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.3 din25


desemnarea atributului; două atribute distincte au nume diferite. Domeniul de valori specifică valorile pe care le poate lua
atributul. Specificarea organizării fişierului este completată de restricţiile, care trebuie să fie satisfăcute de către articole.
Aceste restricţii pot lua forme diverse (restricţii de ordine a articolelor, restricţii legate de valorile atributelor, relaţii între
atributele diferitelor articole, etc.). Desemnarea articolelor, în expresia funcţiilor de acces, utilizează atributele articolelor,
ţinând cont de restricţiile specificate.
Ilustrăm aceste definiţii cu două exemple, care vor fi necesare mai apoi.
Exemplul 6.1. Fişier secvenţial de caractere. Fiecare înregistrare a fişierului posedă următoarele atribute:
(număr, <întreg>)
(conţinut, <caracter ASCII>)
Restricţia este, că articolele fişierului sunt ordonate, articolele succesive având drept număr valori întregi consecutive.
În reprezentarea fişierului atributul număr nu este reprezentat explicit, dar este definit de ordinea articolelor. Mai mult, atributul
valoare este reprezentat doar prin valoarea sa, iar fişierul este simplu reprezentat sub forma unei secvențe de caractere.
Utilizarea atributului număr permite specificarea diferitor funcţii de acces. De exemplu, dacă ne vom limita la consultare:
citire(urm) citeşte caracterul, care urmează după o poziţie curentă specificată (poziţia ultimei lecturi); pune valoarea
caracterului în urm.
citire(i, c) citeşte caracterul cu numărul i; valoarea acestuia este pusă în c.
În ambele cazuri se va specifica efectul funcţiei, dacă caracterul nu există.
Prima funcţie este de tip acces secvenţial, cea de-a două de tip acces direct. ◄
Exemplul 6.2. Fişier de tip document. Fiecare înregistrare a acestui fişier, folosit pentru gestiunea unei biblioteci, are următoarele atribute:
(nume_lucrare, <identificatorul lucrării>)
(autor, <lanţ de caractere>)
(editor, <lanţ de caractere>)
(an, <întreg>)
(subiect, <lanţ de caractere>)
O restricţie poate fi că două articole diferite au ca nume identificatori de lucrări distincte (cu alte cuvinte, o lucrare este determinată în
mod unic de numele său).
Să examinăm reprezentarea acestui fişier. Dacă stabilim o anumită ordine a celor cinci atribute ale unei înregistrări, numele acestor
atribute (care este acelaşi pentru orice articol), nu este necesar să fie păstrat în mod explicit. Fiecare articol este reprezentat de un şir
de cinci câmpuri, fiecare având un format prestabilit.
Pot fi specificate funcţii de acces direct, desemnând un articol prin atributul nume_lucrare (dacă această desemnare este unică). Pentru
a specifica funcţii de acces secvenţial va fi necesar să ordonăm în prealabil articolele cu ajutorul unei restricţii suplimentare (relaţie de
ordine, de exemplu, definind o ordine a numelor, autorilor, anului de editare, etc.). ◄

Metodele de organizare logică a fişierelor (reprezentarea datelor, realizarea funcţiilor de acces) sunt aplicaţii directe
ale structurilor de date: tabele, fire de aşteptare, liste, etc., care sunt tratate în alte discipline. Ne vom opri la o succintă
descriere a organizării uzuale, făcând trimitere la literatura de specialitate pentru studii mai aprofundate. Interesul
principal al acestei descrieri este de a elucida restricţiile introduse de organizarea fizică a fişierelor.
6.2.2. Acces secvenţial
În cadrul unei organizări secvenţiale înregistrările sunt ordonate şi pot fi desemnate de valori întregi consecutive.
Totuşi, aceste numere de ordine nu pot fi folosite în cadrul funcţiilor de acces; este permisă doar utilizarea funcţiei
“succesor”. Accesul secvenţial este modul obişnuit de utilizare a unui fişier, implantat fizic pe un suport în care accesarea
amplasamentelor este ea însăşi secvenţială, cum ar fi banda magnetică.
Un fişier f poate fi deschis pentru citire sau scriere. Unele organizări autorizează scrierea începând de la o înregistrare
oarecare (v. exemplul din capitolul 9). Vom considera că scrierea se face la sfârşitul fişierului şi deschiderea pentru
scriere iniţializează fişierul în “vid”.
Deschiderea pentru scriere este realizată prin operaţia:
deschide(mod):
if mod=citire then
f.rest:=<şirul înregistărilor fişierului>
else
f:=<vid>
endif;
f.mod:=mod;
avansare
unde funcţia avansare este definită după cum urmează:
if f.rest=vid then
f.sfârşit:=true
else

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.4 din25


f.primul:=<pointer pe primul(f.rest)>;
f.rest:=f.rest-primul(f.rest)
endif
Operaţia de citire a unei înregistrări are forma:
citire(f, a):
if f.sfârşit=false then
a:=<înregistrarea desemnată de f.primul>;
avansare
endif
Scrierea adaugă o înregistrare la sfârşitul fişierului:
scriere(f,a):
if mod=citire then
<eroare>
else
alocare spațiu pentru articol nou;
if eşec then -- lungimea maximă a fost atinsă sau este necesar un spaţiu mai mare
<eroare>
else
f.pa:=<pointer pe amplasamentul înregistrării noi>;
<copiere a în amplasamentul desemnat de f.pa>
endif
endif
Aceste funcţii de acces se traduc utilizând adresele logice. Dacă articolul curent nu este ultimul în fişier, adresa logică
a succesorului său este dată de adresa(curentă)+lungimea(curentă).
Dacă articolele sunt de lungime variabilă, lungimea înregistrării curente poate fi obţinută plecând de la conţinutul
acestui articol (de obicei, lungimea unei înregistrări este prezentă explicit).
6.2.3. Acces direct
În cadrul organizărilor cu acces direct funcţiile de acces sunt exprimate ca funcţii ale atributelor înregistrărilor; aceste
atribute sunt valori ale diferitor câmpuri. Se numeşte cheie orice câmp al unei înregistrări valoarea căruia poate servi la
identificarea înregistrării. Conform organizării adoptate, una sau mai multe câmpuri pot servi drept cheie.
6.2.3.1. Cheie unică
Într-un fişier cu cheie unică fiecare înregistrare conţine o singură cheie, care identifică înregistrarea fără ambiguitate;
restul înregistrării este informaţia propriu-zisă. Două înregistrări distincte vor avea totdeauna două valori diferite ale
cheii. Definim o procedură căutare(cheie, al), care pentru orice valoare a cheii:
 sau pune la dispoziţie adresa logică al (unică) a înregistrării pentru care cheia posedă valoarea dată (caz de succes)
 sau semnalizează cu ajutorul unui mecanism special, că o atare înregistrare nu există (caz de eşec): excepţie, cod
de condiţie; valoarea al este adresa la care înregistrarea ar putea fi inserată (valoare specială, dacă nu mai este
spaţiu liber).
Procedura căutare serveşte la realizarea funcţiilor elementare de acces direct citire(cheie, info), adăugare(cheie, info),
suprimare(cheie, info), modificare(cheie, info). Funcţiile citire, suprimare, modificare pot conduce la erori, dacă
procedura căutare eşuează; procedura adăugare generează o eroare, dacă procedura căutare se termină cu succes.
Metodele realizării procedurii căutare formează obiectul multor cercetări speciale. Aducem aici doar rezultatele
principale. Procedura căutare poate fi realizată utilizând două metode: adresarea dispersată şi constituirea unui indice.
a) Adresare dispersată (funcție “hash”)
Procedura căutare este realizată direct, construind o funcţie al = f(cheie). Funcţia f se numeşte funcţie de dispersare
(funcție “hash”). Pare a fi o soluţie funcţia identitate: de exemplu, în cazul unei chei cu valoare întreagă, trebuie să luăm
în calitate de adresă al valoarea cheii (sau de k ori această valoare, dacă o înregistrare ocupă k amplasamente). Totuşi,
această metodă este impracticabilă. Fie, de exemplu, un fişier pentru care cheia are 9 cifre; un atare fişier poate să ocupe
maximum 109 amplasamente logice. Dacă lungimea medie a fişierului este de 10 5 înregistrări rata de umplere a fişierului
cu înregistrări utile este doar de ordinul 10 -4. Dacă dorim să evităm utilizarea ineficientă a spaţiului memoriei va trebui să

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.5 din25


îndreptăm atenţia spre alegerea funcţiei de corespondenţă a adreselor logice şi celor fizice. Folosirea funcţiei identitate
este limitată la cazurile pentru care avem o rată ridicată de ocupare a memoriei.
O funcţie de dispersare ideală realizează o permutare între mulţimea cheilor şi cea a adreselor logice, limitată la
numărul de înregistrări din fişier. Pentru simplitate presupunem, că adresele logice pentru un fişier cu n înregistrări sunt
0,..., n-1. Funcţia hash trebuie să posede următoarele proprietăţi:
 pentru orice înregistrare din fişier cu cheia c: 0 ≤ f(c) < n, (6.1)
 pentru orice cuplu de înregistrări f(c1) ≠ f(c2), dacă c1 ≠ c2. (6.2)
În practică este foarte dificil să se satisfacă proprietatea (6.2). Din această cauză trebuie admisă posibilitatea
coliziunilor, adică existenţa cheilor, care nu satisfac ultima condiție. Numărul de valori distincte calculate de funcţia de
dispersare este inferior valorii lui n. În caz de coliziune este necesară o fază suplimentară pentru determinarea înregistrării
căutate sau, în cazul unei inserări, să i se caute un loc. Alegerea funcţiei de dispersare în scopul reducerii probabilităţii
coliziunilor şi a metodelor de tratare a coliziunilor trebuie să ţină cont de caracteristicile utilizării fişierului:
 probabilitatea unor valori diferite ale cheii,
 frecvenţa relativă a operaţiilor de căutare, inserare şi suprimare a articolelor.
Figura 6.3 prezintă schematic organizarea unui fişier cu acces direct prin adresare dispersată.

articol 2 al2=f(cheie2)
f(cheie2)= f(cheie3)

cheie 1
cheie 2 funcţie de al1=f(cheie1)
f(cheie1) articol 1
dispersare
cheie 3
tratare
coliziuni
(coliziune între cheie1 şi cheie3)
articol 3 al 3

Fig.6.3. Acces direct prin adresare dispersată


Principalul avantaj al metodei adresării dispersate (dacă se reuşeşte să se asigure un nivel acceptabil al coliziunilor)
este rapiditatea: în lipsa coliziunilor găsirea unei înregistrări necesită o singură accesare a discului. Totuşi, în cazul cel
mai frecvent, când mulţimea cheilor este ordonată, funcţia de dispersare nu întotdeauna asigură o relaţie simplă între
ordinea cheilor şi ordinea adreselor logice a înregistrărilor respective. Drept consecinţă, un acces secvenţial, care ar
respecta ordinea cheilor, trebuie să fie realizat ca o suită de accese directe, fără simplificări. Metodele accesului indexat
permit remedierea acestui inconvenient.
b) Fişiere indexate
Metodele accesului indexat sunt utilizate în cazul când mulţimea cheilor este ordonată. Relaţia dintre cheie şi adresa
logică este materializată printr-un tabel, numit tabel al indicilor, în care ordinea cheilor este semnificativă. Schema
principiului organizării indexate este dată de fig.6.4
Tabelul indicilor
articol 2

Cheie 1

Cheie 2 articol 1

Cheie 3

articol 3

Fig.6.4. Acces direct prin indexare


Schemele utilizate efectiv în practică sunt mai complexe pentru a permite:
 accelerarea căutării în cadrului indicelui,

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.6 din25


 facilitarea inserării şi a suprimării înregistrărilor.
Fie n numărul de înregistrări într-un fişier. Dacă tabelul indicilor este organizat secvenţial în ordinea cheilor şi
căutarea unei chei se face prin parcurgere secvenţială, numărul mediu de comparări (şi de accesare a tabelului) este de
ordinul n/2. Această valoarea poate fi redusă până la log2n adoptând o organizare arborescentă a tabelului (log2n
reprezintă adâncimea medie a unui arbore binar echilibrat cu n vârfuri). Arborele riscă să devină dezechilibrat, dacă există
foarte multe inserări şi suprimări; pentru cazul cel mai puţin favorabil adâncimea arborelui devine de ordinul lui n. De
asemenea sunt utilizate forme particulare de arbore, cum ar fi B-arborii, pentru care este garantat, că timpul de căutare
rămâne de ordinul lui log2 n.
Atunci când un fişier cu acces direct trebuie să poată fi utilizat în egală măsură şi în acces secvenţial, fişierul poate fi
organizat conform unei scheme mixte, numită secvenţial indexată, care conţine un tabel al indicilor la diferite nivele la
care există adrese fizice directe (v.6.3.2).
6.2.3.2. Chei multiple
Este cazul când pot fi utilizate mai multe chei pentru a desemna o înregistrare. În caz general, pot exista mai multe
înregistrări pentru care o cheie particulară are o valoare dată. O cheie, valoarea căreia determină înregistrarea în mod
univoc, se numeşte cheie primară; acest termen este aplicat, prin extensie, şi pentru o combinaţie de chei.
Tehnica de bază folosită pentru manipularea unui fişier cu chei multiple este organizarea multilistă. Este utilizat câte
un indice distinct pentru fiecare cheie. Fiecare intrare a tabelului indicilor, asociată unei chei concrete, care corespunde
unei valori distincte a acestei chei, punctează topul unei liste în care sunt toate înregistrările pentru care cheia considerată
posedă valoarea dată. Pentru realizarea acestor liste fiecare înregistrare trebuie să conţină tot atâţia pointeri câte chei ale
referinţelor distincte există. Figura 6.5 ilustrează această organizare pentru exemplul unui fişier document.
pointeri autori
tabelul indicilor 200 pointeri editori
referinţelor 500
900
adrese logice
100
750

tabelul indicilor
autorilor

tabelul indicilor
editorilor

Fig.6.5. Organizare multilistă pentru un fişier cu chei multiple


În afara tabelului indicilor referinţelor au mai fost introduse un tabel al autorilor şi unul al editorilor. Fiecare intrare a
tabelului indicilor autorilor este topul unei liste, care grupează toate înregistrările pentru care valoarea câmpului autor
este aceeaşi. Pointerii acestor liste sunt adrese logice. Este simplu de găsit toate lucrările unui autor publicate la una şi
aceeaşi editură. Pot fi obţinute combinaţii pentru aceste cereri cu ajutorul operaţiei intersecţie.
Este posibilă comprimarea reprezentării fişierului, utilizând liste circulare, care includ intrările corespunzătoare ale
tabelelor indicilor (lista lucrărilor scrise de Paul, de exemplu, se închide la intrarea Paul din tabelul indicilor autorilor).
Câmpurile autor şi editor ale părţii info a reprezentării înregistrărilor pot fi suprimate pentru că ele pot fi determinate din
listele respective. Dezvoltând această idee, se poate crea câte un indice distinct pentru fiecare câmp; reprezentarea
înregistrărilor va conţine doar pointeri şi toată informaţia se conţine doar în tabelele indicilor. Un fişier reprezentat în
acest mod se numeşte inversat. Această reprezentare permite un răspuns imediat la cereri legate de combinaţii ale
câmpurilor şi poate fi combinată cu organizarea directă, utilizând o cheie primară. Tabelele indicilor secundari conţin în
acest caz listele valorilor cheii primare. Pentru exemplul unui fişier documentar organizarea descrisă mai sus este
schematic prezentată în figura 6.6.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.7 din25


adresă logică
tabelul
indicilor
referinţelor

tabelul indicilor
autorilor înregistrări

tabelul indicilor
editorilor

tabelul indicilor
anilor

Fig.6.6. Organizarea unui fişier inversat


Terminăm studierea funcţiilor de acces logic subliniind, că funcţiile de acces complex sunt construite pornind de la
funcţii elementare. De exemplu, fişierele sistemului Unix sunt fişiere de caractere pentru care sunt puse la dispoziţie un
set de primitive de acces direct. Orice funcţie de acces mai complicat trebuie programată, utilizând aceste primitive.

6.3. Organizarea fizică a fişierelor


În modelul ierarhic, prezentat mai sus, problema organizării fizice a fişierelor poate fi formulată astfel: să se elaboreze
o implantare în memoria secundară a unei mulţimi de fişiere respectând următoarele ipoteze:
 orice fişier este definit logic ca un segment, adică ca o mulţime de informaţii, care ocupă amplasamente adiacente,
reperate prin adrese logice sau deplasări,
 dacă nu există concretizări particulare (bandă magnetică, de exemplu), memoria secundară este de tip disc,
organizată ca o mulţime de blocuri de lungime fixă. Modul de adresare a blocurilor este precizat în 6.3.3; este
suficient să se cunoască că blocurile sunt desemnate de adrese fizice ordonate, adrese consecutive desemnând
blocuri adiacente.
Notăm aici, că dacă sistemul de operare realizează o memorie virtuală segmentată, implantarea fizică a segmentelor şi
realizarea funcţiilor de acces elementar (citire, scriere, execuţie) sunt puse în şarja sistemului. Este posibilă în acest caz
confundarea noţiunilor de segment şi fişier. Funcţiile SGF sunt reduse la gestiunea numelor şi organizarea logică, ceea ce
este realizat, de exemplu, pentru sistemul Multics.
Vom trata cazul unei gestionări directe de către SGF a implantării fizice a fişierelor. Pot fi evidenţiate două clase de
metode, dacă luăm în consideraţie respectarea sau nerespectarea contiguităţii adreselor logice.
6.3.1. Implantare secvenţială
În acest caz fiecare fişier ocupă o mulţime de blocuri consecutive în memoria secundară. Este unicul mod de
implantare în cazul unei benzi magnetice: fişierele sunt aranjate consecutiv pe bandă, fiecare fiind separat de următorul cu
ajutorul unui simbol, numit sfârşit de fişier (end of file, EOF). Un EOF dublu marchează sfârşitul părţii utilizate a benzii.
Descriptorul unui fişier este plasat la începutul fişierului şi, adesea, repetat la sfârşitul fişierului. În interiorul fişierului
înregistrările sunt aranjate consecutiv; dacă lungimea lor este variabilă, ea va fi prezentă la începutul fiecărei înregistrări.
Caracterul EOF este detectat în mod automat de controlerul mecanismului de derulare a benzii. O operaţie “căutarea
EOF-ului fişierului” permite saltul de la un fişier la altul pentru căutarea unui fişier cu numele dat.
Implantarea secvenţială poate fi în egală măsură folosită şi pentru discuri. Avantajul principal constă în garantarea
unui acces secvenţial eficient (informaţiile cu adrese logice succesive sunt implantate în blocuri adiacente) permiţând în
acelaşi timp un acces direct eficient (calcularea adresei fizice pornind de la adresa logică este foarte simplă şi nu cere

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.8 din25


accesarea discului). Totuşi, această metodă prezintă inconveniente grave în cazul în care crearea, distrugerea sau
modificarea lungimii unui fişier sunt operaţii frecvente:
 memoria secundară devine fragmentată, defragmentarea periodică este costisitoare;
 este complicată organizarea modificării lungimii unui fişier: un fişier poate fi de o lungime mai mare doar
recopiindu-l integral într-o zonă de memorie mai mare.
Drept consecinţă, implantarea secvenţială pe disc este utilizată doar în cazurile în care dezavantajele susmenţionate
pot fi diminuate:
 pentru fişierele numărul şi lungimea cărora nu variază (de exemplu, fişiere create odată pentru totdeauna şi
utilizate mai apoi doar pentru consultare);
 sisteme primitive pentru microcalculatoare, când simplitatea realizării este un factor preponderent.
6.3.2. Implantare non contiguă
Dacă abandonăm restricţia contiguităţii implantării, memoria secundară se transformă într-o resursă banalizată,
blocurile memoriei secundare fiind echivalente din punctul de vedere al alocării lor. Pentru început introducem
informaţiile necesare pentru realizarea funcţiilor de acces; informaţiile pentru asigurarea securităţii sunt descrise în 6.5.
6.3.2.1. Blocuri înlănţuite
Blocurile fizice, care conţin amplasamente logice consecutive sunt înlănţuite între ele; pentru această înlănţuire
trebuie să fie rezervat în fiecare bloc un pointer. Descriptorul conţine un pointer la primul şi ultimul bloc şi numărul
blocurilor ocupate (fig.6.7).

Fig.6.7. Alocare prin blocuri înlănţuite

Ultimul bloc, care poate fi utilizat parţial, trebuie să conţină indicaţii despre numărul de amplasamente ocupate. Deci,
este necesar un amplasament în fiecare bloc pentru această informaţie sau cel puţin un bit (indicator) pentru marcarea
ultimul bloc. Deoarece există un pointer la ultimul bloc este simplu să extindem un fişier, adăugând informaţii la sfârşit.
Acest mod de alocare este bine adaptat accesului secvenţial. Ca rezultat, putem accesa un bloc doar respectând
înlănţuirea; accesul direct este costisitor, deoarece fiecare citire a unui pointer necesită o accesare a discului. La fel şi
extinderea altfel, decât la sfârşit, este foarte dificilă: trebuie să permitem existenţa blocurilor parţial pline, să prevedem o
dublă înlănţuire, etc. Utilizarea alocării înlănţuite este limitată de cazul sistemelor mici, în special pentru organizarea
fişierelor pe dischete.
6.3.2.2. Tabele de implantare
În cazul accesului direct timpul de acces la un bloc trebuie să nu depindă de adresa sa, ceea ce poate fi obţinut punând
toţi pointerii într-un tabel unic de implantare. Descriem mai multe variante ale acestei metode, care diferă prin modul de
organizare a tabelului. Problema principală este garantarea uniformităţii timpilor de acces pentru tabelele de lungime
mare şi permiterea inserării şi distrugerii blocurilor în orice punct al fişierului.
1) Tabel unic
Figura 6.8 (a) descrie o organizare cu tabel unic. Lungimea fişierului este limitată de numărul blocurilor pe care
descriptorul le defineşte în tabel (el însuşi conţinându-se într-un număr întreg de blocuri).
2) Tabel înlănţuit
Conform organizării din fig.6.8 (b) tabela de implantare constă dintr-o suită de blocuri înlănţuite. Putem depăşi în
acest fel limitarea dimensiunii unui fişier, devine posibilă inserarea blocurilor în mijlocul fişierului, cu condiţia rezervării
unor amplasamente libere în tabel. Reorganizarea generată de inserare este legată de un bloc al tabelului, iar dimensiunea
tabelului de implantare este limitată de costul căutării în acest tabel. Pentru tabele mari organizarea descrisă este mai
eficace.
3) Tabele cu mai multe nivele
Figura 6.9 descrie o organizare în care tabelul de implantare a fişierului este organizat în mod arborescent, pe niveluri
(de obicei, două sau trei niveluri).

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.9 din25


Organizarea dată permite un acces direct rapid la un bloc cu adresa logică dată; ea permite inserările cu unele măsuri
de precauţie.

Fig.6.8. Tabel de implantare cu un nivel

Fig.6.9. Tabel de implantare cu două nivele


4) Aplicaţii: organizare secvenţială indexată
Cu titlu de exemplu vom descrie o organizare frecvent utilizată, cea a fişierelor secvenţiale indexate. Este vorba de o
schemă în care organizarea logică şi cea fizică nu sunt separate net: tabelul indicilor şi tabelul implantării sunt grupate
într-o structură de date unică.
Această organizare se aplică la fişiere pentru care se cere utilizarea simultană a accesului direct (cu ajutorul cheilor) şi
a accesului secvenţial (specificat de o ordonare a cheilor). Pentru simplitate, vom descrie o organizare în care cheia este
unică.
Principiul constă în organizarea tabelului indicilor (ordonaţi conform valorii cheii) ca un tabel de implantare cu mai
multe niveluri în care figurează nu adrese logice, ci adrese fizice. Printre altele, cel puţin pentru implantarea iniţială se
încearcă să se plaseze informaţii logic contigue în blocuri vecine pentru a permite un acces secvenţial eficient.
Figura 6.10 ilustrează principiul organizării secvenţiale indexate pentru cazul, descris în exemplul 2 din 6.2.1. Cheia
utilizată este numărul referinţei. Este folosită o organizare pe două niveluri. Intrarea i a tabelului primar al indicilor (cheia
cp[i]) punctează la un tabel secundar al indicilor, care reperează înregistrările pentru care cheia c verifică relaţia
cp[i-1] < c ≤ cp[i]
Mai mult, fiecare intrare a tabelului secundar punctează o zonă, unde sunt plasate secvenţial înregistrările cu aceeaşi
organizare a cheilor. Această ultimă zonă este de lungime suficient de mică pentru a putea fi citită întreagă în memorie
atunci când este accesat un articol pe care ea îl conţine. Tabelul primar fiind păstrat în memoria centrală atunci când
fişierul este deschis, consultarea unei înregistrări cere două accesări a discului pentru prima citire a unei zone şi nici una
pentru consultarea înregistrărilor succesive din zonă. Accesul secvenţial este astfel eficient, însă accesul direct rămâne
posibil graţie tabelului indicilor.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.10 din25


Fig.6.10. Fişier secvenţial indexat
Problema principală a organizării secvenţiale indexate vine de la inserarea şi suprimarea înregistrărilor. Chiar de la
crearea iniţială a fişierului, pot fi lăsate amplasamente libere în fiecare zonă, care este apoi modificat prin compresie,
atunci când au loc modificări. Dacă toate amplasamentele rezervate sunt ocupate, sunt utilizate zone de depăşire: fiecărui
tabel secundar i se asociază o zonă de depăşire, înregistrările fiind ordonate în ordinea inserării. Căutarea unui articol are
o durată mai mare, iar atunci când zonele de depăşire sunt foarte pline este preferabil să fie reorganizat fişierul în
întregime, alocând zone noi şi creând, la necesitate, tabele secundare noi.
6.3.3. Alocarea memoriei secundare
Problema alocării memoriei secundare poate fi pusă în termeni similari cu cea a memoriei principale; restricţiile
principale sunt:
 alocarea prin blocuri de lungime fixă,
 costul ridicat al accesului,
 caracteristicile proprii fiecărui suport: organizarea pe piste, dispozitive de citire-scriere mobile sau fixe.
Interfaţa alocatorului memoriei secundare conţine două primitive:
cerere_zonă(n,a) date : n (întreg), numărul de blocuri contigue cerute
rezultat : a (adresă), adresa primului bloc
excepţie : număr de blocuri insuficiente
eliberare_zonă(n,a) date n (întreg), numărul de blocuri contigue eliberate
:
a (adresă), adresa primului bloc
excepţie : număr de blocuri eliberate
Cazul n=1 este întâlnit frecvent şi poate justifica folosirea primitivelor particulare (cerere_zonă, eliberare_zonă).
Structura de date cel mai des utilizată pentru a descrie starea de ocupare a memoriei este un lanţ de biţi, bitul cu
numărul i indicând starea (ocupat sau liber) a blocului cu acelaşi număr.
Acest tabel de ocupare poate atinge dimensiuni importante; de exemplu, sunt necesari 12,5 Ko pentru a descrie
ocuparea unui disc de 200 Mo alocaţi prin blocuri de 2 Ko. Pentru a spori eficienţa algoritmilor de alocare tabelul poate fi
organizat pe mai multe niveluri.
Exemplul 6.3. Discurile cu braţe mobile sunt organizate pe cilindre (mulţime de blocuri, accesibile pentru o poziţie dată a braţului mobil). Fiecare
cilindru conţine tabelul de ocupare a blocurilor pe care intră în componenţa sa; mai mult, un tabel care duce evidenţa umplerii
cilindrelor, încărcat în memoria centrală, indică numărul de blocuri libere în fiecare cilindru. Căutarea unei zone libere poate să se facă
fără deplasarea braţului, dacă cilindrul curent conţine un număr suficient de blocuri libere; în caz contrar, dintre cilindrele posibile
poate fi ales cilindrul, care este cel mai aproape de poziţia curentă a braţului. ◄

Din raţionamente de securitate (v. 6.5), starea liber sau ocupat a unui bloc este păstrată chiar în blocul propriu-zis.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.11 din25


6.4. Realizarea funcţiilor de acces elementar
6.4.1. Organizarea descriptorilor
Un descriptor de fişier trebuie să conţină informaţii de tipuri diverse:
 informaţii pentru localizarea fizică,
 informaţii referitor la utilizare,
 informaţii asociate protecţiei şi securităţii.
6.4.1.1. Localizarea fizică
Informaţiile pentru localizarea fizică a unui fişier au fost descrise în 6.3. Dacă aceste informaţii sunt de dimensiune
fixă şi redusă (implantare contiguă, blocuri înlănţuite) ele se conţin direct în descriptor; în caz contrar (tabele de
implantare înlănţuite sau pe mai multe niveluri), descriptorul conţine doar un pointer la tabelul de implantare şi nişte
informaţii sintetice, cum ar fi dimensiunea fişierului, dimensiunea tabelului de implantare, etc.
6.4.1.2. Informaţii de utilizare
Informaţiile, legate de utilizarea unui fişier pot fi clasificate după cum urmează:
1) Informaţii de stare. Aceste informaţii definesc starea curentă a fişierului: deschis sau închis, gradul de partajare
(numărul de utilizatori, care au deschis simultan fişierul), disponibilitatea pentru modificare, etc.
2) Informaţii despre conţinutul fişierului. Aceste informaţii permit interpretarea conţinutului fişierului. Este posibil
să se asocieze unui fişier un tip, care specifică operaţiile permise. Sunt utilizate, de exemplu, tipurile “text
ASCII”, “binar translatabil”, “binar absolut”, “catalog”, etc. Chiar la deschiderea unui fişier putem verifica, dacă
utilizarea pretinsă este compatibilă cu tipul fişierului.
3) Informaţii despre structura logică. Aici pot fi plasate informaţiile care permit trecere de la structura logică la
structura fizică a fişierului. De exemplu, în cazul înregistrărilor de lungime fixă este convenabil să se aleagă
lungimea înregistrării multiplu sau submultiplu al lungimii blocului fizic. Raportul lungimea blocului/lungimea
înregistrării, adesea numit factor de bloc, figurează în cadrul descriptorului.
4) Informaţii despre utilizările precedente. Aceste informaţii pot fi de natură statistică (numărul deschiderilor,
accesărilor, intervalul mediu timp de între accesări, gradul mediu de partajare, etc.) şi au scopul de a înţelege mai
bine funcţionarea sistemului pentru ameliorarea lui. De exemplu, informaţiile despre utilizare pot ajuta la o
gestiune automată a ierarhiei memoriei secundare: fişierele neutilizate o perioadă lungă pot fi transferate într-o
memorie de arhivare pentru a elibera loc în memoriile cu acces rapid. Aceste informaţii mai pot fi utilizate pentru
diferite funcţii de securitate: înregistrarea datei ultimului acces sau a ultimei modificări permite un control al
utilizării fişierului.
Precizăm realizarea funcţiilor elementare de acces (primitive), definite în 6.1.
Ca şi majoritatea funcţiilor unui sistem de operare, aceste primitive pot fi apelate în două moduri: cu ajutorul unor
instrucţiuni sau prin apelarea regimului supervizor. La nivelul limbajului de comandă fişierele sunt desemnate prin
numele lor simbolic, care este interpretat în contextul curent. Dacă o primitivă este apelată printr-un apel al
supervizorului, în timpul execuţiei unui program, fişierele sunt, de obicei, desemnate de numele local, care este cel al unui
descriptor valid în interiorul programului curent. Corespondenţa între numele simbolice şi numele locale este realizată
prin instrucţiuni de asociere. Interpretarea numelor fişierelor este comună tuturor primitivelor.
Pentru fiecare primitivă vom prezenta:
 specificările interfeţei,
 algoritmul care o realizează,
 situaţiile anormale posibile.
6.4.2. Crearea şi distrugerea
6.4.2.1. Crearea
1) Specificarea interfeţei
Parametrii furnizaţi sunt:
numele fişierului
tipul (opţional)
lungimea (opţional)
starea iniţială (opţional)
Cel mai frecvent, parametrii starea iniţială şi lungimea nu sunt furnizaţi, având valori implicite: lungimea = 0, fişierul
este închis, lista de acces predefinită.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.12 din25


2)Operaţii
 să se creeze un descriptor pentru fişier, obţinem astfel un nume intern,
 dacă numele furnizat este un nume extern, să se creeze o intrare a acestui nume în catalogul curent,
 să se aloce memorie fişierului; chiar dacă lungimea sa este nulă, un fişier conţine un antet, care ocupă primul său
bloc,
 să se iniţializeze descriptorul cu informaţiile de localizare, lungime, protecţie (lista drepturilor iniţiale de acces),
 dacă descriptorul nu se conţine direct în catalog, să se introducă o intrare în catalog cu numele intern al fişierului
(adresa descriptorului).
3) Cazuri anormale
 nume furnizat incorect (incorect construit sau care desemnează un fişier deja existent);
 memorie insuficientă în memoria secundară.
Fişierul nu poate fi creat şi situaţia anormală este semnalată.
6.4.2.2. Distrugerea
1) Specificarea interfeţei
Unicul parametru furnizat este numele fişierului. Efectul operaţiei este de a suprima orice acces ulterior la fişier,
invalidând toate numele acestuia şi eliberând toate resursele pe care fişierul le utilizează (intrări în tabele, memorie).
2) Operaţii
 să se elibereze toată memoria, care a fost alocată fişierului;
 să se elibereze memoria alocată descriptorului şi numele intern să devină reutilizabil (sau invalidat definitiv);
 suprimarea numelui extern al fişierului în catalogul, care-l include, de asemenea, dacă este cazul, în tabelul
numelor locale.
Această ultimă operaţie poate fi destul de delicată, dacă există mai multe căi de acces la fişier. Poate fi utilizată una
din următoarele soluţii:
 dacă căile multiple de acces sunt legături, nu se va lua nici o măsură; un acces ulterior prin una din aceste legături
va conduce la numele extern. Inexistenţa fişierului va fi detectată (cu excepţia cazului în care un fişier cu acelaşi
nume a fost creat în intervalul de timp dat);
 dacă căile multiple de acces sunt nume (ceea ce se poate produce, dacă structura catalogului nu este o
arborescenţă) vor fi utilizate sau legături inverse (metodă costisitoare), sau un contor al referinţelor păstrat în
descriptor, care duce evidenţa numărului căilor de acces. Un fişier poate fi distrus doar dacă există o singură cale
de acces. Această soluţie este utilizată, de exemplu, în sistemul Unix.
6.4.3. Deschiderea şi închiderea
6.4.3.1. Deschiderea
1) Specificarea interfeţei
Parametrii operaţiei de deschidere sunt:
 numele fişierului
 condiţiile de utilizare:
 modul de acces (citire, scriere, execuţie, etc.)
 procedurile de acces (secvenţial, direct, sincron, etc.)
 parametrii de transfer (tampoane, etc.)
Operaţia de deschidere are scopul de a pune un fişier în starea în care accesul este posibil conform modului specificat.
Această operaţiei este de dublă utilitate pentru SGF:
 Protecţie. SGF poate să controleze:
 la deschidere, dacă utilizatorul este autorizat să acceseze fişierul în condiţiile specificate,
 la fiecare accesare a fişierului, dacă condiţiile de acces sunt compatibile cu cele specificate la deschidere,
 în caz de partajare, dacă condiţiile de accesare ale utilizatorilor sunt reciproc compatibile.
 Eficienţă. SGF poate să accelereze accesul la fişierele deschise, aducând în memorie descriptorii lor, tabelele de
implantare şi textele procedurilor de acces. Fişierul însuşi poate fi transferat, eventual, pe un suport cu acces mai
rapid; dacă el se află pe un suport amovibil nemontat, montarea este necesară.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.13 din25


Numele furnizat ca parametru poate fi un nume extern sau local. Pentru durata deschiderii unui fişier SGF trebuie să
poată accesa rapid toate informaţiile necesare utilizării: descriptorul şi condiţiile de utilizare valabile pentru perioada
deschiderii. Aceste informaţii sunt apoi plasate într-un descriptor local, durata de existenţă a căruia este durata aflării
fişierului în starea deschis; numele local este numele acestui descriptor local.
2) Operaţii
La deschidere vor fi realizate următoarele operaţii:
 localizarea fişierului şi, eventual, transferarea lui pe un suport mai rapid; cerere eventuală de montare a acestuia,
 controlarea dreptului utilizatorului de a deschide fişierul în modul specificat (consultând lista de acces),
 crearea unui descriptor local (dacă fişierul nu posedă deja unul în mediul curent) şi atribuirea unui nume local,
 alocarea eventuală a memoriei pentru zonele tampon de intrare-ieşire; în unele cazuri programul de intrare-ieşire al
canalului poate fi construit în dependenţă de condiţiile specificate pentru transfer.
3) Cazuri anormale
 condiţii de deschidere incompatibile cu drepturile utilizatorului,
 imposibilitatea deschiderii, datorată restricţiilor specificate pentru partajare (de exemplu, restricţii de tipul cititor-
redactor),
 lipsa spaţiului în memorie pentru descriptorul local sau zonele tampon.
6.4.3.2. Închiderea
1) Specificarea interfeţei
Unicul parametru necesar este numele fişierului. Efectul operaţiei este de a interzice orice acces ulterior la fişier şi de
a-l transfera într-o stare coerentă şi stabilă, redându-i definitiv toate modificările operate în perioada cât a fost deschis.
2) Operaţii
Descriptorul fişierului este actualizat (dacă aceasta nu a fost făcut anterior) pentru a înregistra definitiv modificările
operate în perioada cât a fost deschis; descriptorul local este suprimat, numele local putând fi reutilizat. Memoria ocupată
de zonele tampon şi procedurile de intrare-ieşire este eliberată, dacă ea a fost alocată doar pentru perioada de deschidere a
fişierului. Fişierul este, eventual, transferat pe suportul său de origine; o cerere de demontare este trimisă dacă suportul de
origine este amovibil.
Unele sisteme operează cu fişiere temporare, adică fişiere desemnate doar de numele local. La închiderea unui astfel
de fişier, utilizatorul are de ales între două posibilităţi:
 să catalogheze fişierul, atribuindu-i un nume extern; fişierul va fi în acest caz salvat.
 (implicit) să nu facă nimic, fişierul fiind distrus în acest caz.
3) Cazuri anormale
Pentru garantarea coerenţei fişierului, în timpul închiderii nu trebuie să aibă loc operaţii de transfer (a descriptorului
sau a fişierului).
6.4.4. Acces elementar la informaţii
Parametrii primitivelor de transfer permit specificarea:
 “metodei de acces” utilizate, care determină modul de desemnare a înregistrărilor - obiectul transferului (acces
secvenţial, direct, cu chei, etc.),
 sincronizarea transferului (transfer sincron sau asincron); în cazul unui transfer asincron, modul de deblocare a
unui proces apelant,
 zonele tampon utilizate (specificate de către utilizator sau furnizate de SGF).
Accesul elementar (citire sau scriere) la o înregistrare a fişierului constă din două etape:
 determinarea adresei fizice a înregistrării plecând de la desemnarea sa logică; pentru aceasta sunt utilizate
metodele descrise în 6.2,
 executarea transferului fizic; va fi folosită adresa obţinută mai sus şi primitivele de acces fizic la disc (v.cap.4).

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.14 din25


6.5. Securitatea şi protecţia fişierelor
6.5.1. Despre securitate şi protecţie
Fişierele conţin toată informaţia administrată de sistemul de operare, inclusiv informaţia necesară gestiunii sistemului.
Este important să se garanteze integritatea acestor informaţii în eventualitatea unor pene fizice, logice sau în caz de rea
voinţă. Obiectivele şi metodele pot fi considerate aparţinând la două direcţii: securitate şi protecţie.
Cu titlul securitate vom îngloba mulţimea metodelor, care sunt chemate să garanteze execuţia tuturor operaţiilor
asupra unui fişier în conformitate cu specificaţiile lor, chiar în cazul unor defecte în cursul execuţiei, şi că informaţiile
conţinute într-un fişier nu sunt alterate, dacă nici o operaţie nu a fost executată. Metodele utilizate sunt, în caz general,
cele care asigură toleranţa sistemului la defecte; baza lor este redundanţa informaţiilor.
Prin protecţie vom înţelege mulţimea metodelor chemate să specifice regulile de utilizare şi să garanteze respectarea
lor. O descriere succintă a metodelor principale de protecţie a fost adusă în 5.1.4. Ele se bazează pe noţiunea de drept de
acces şi existenţa unui mecanism, care permite să se garanteze conformitatea operaţiilor drepturilor de acces specificate.
6.5.2. Securitatea fişierelor
Securitatea fişierelor este asigurată, după cum a fost menţionat, prin redundanţa informaţiilor. Redundanţa poate fi
introdusă în două moduri: salvarea periodică a unor informaţii, pentru a putea restabili o stare anterioară în caz de
distrugere, şi redundanţa internă, care permite reconstituirea unor informaţii devenite incoerente din cauza unui accident
de origine fizică sau logică, care a provocat o alterare parţială.
6.5.2.1. Redundanţa internă şi restabilirea informaţiilor
Principiul redundanţei interne constă în organizarea structurilor de date astfel, încât orice informaţie să poată fi
obţinută prin cel puţin două căi distincte. Se reduce astfel probabilitatea că distrugerea accidentală a unei părţi a
informaţiei va conduce la pierderea iremediabilă a conţinutului fişierului.
Tehnicile frecvent utilizate în acest scop sunt următoarele:
 pentru un fişier păstrat pe disc în blocuri înlănţuite se va folosi înlănţuirea dublă (succesor-predecesor),
 se va include în fiecare bloc un pointer la blocul, care conţine descriptorul, sau indicaţia că blocul este liber,
 se va include în descriptor numele simbolic al fişierului şi un pointer la catalogul în care se conţine fişierul,
 o parte a descriptorului va fi dublată (de exemplu, în primul şi ultimul bloc al fişierului).
Exemplul 6.4. Cu titlul de ilustrare a tehnicilor de redundanţă internă descriem principiul organizării fişierelor pe un calculator personal (Alto Xerox,
organizare, care a fost preluată în sistemul Pilot al firmei Xerox).
Un fişier este organizat logic sub forma unei suite de înregistrări de lungime fixă (256 octeţi), numite pagini. Pagina fişierului este
informaţia elementară accesibilă. Concepţia SGF se bazează pe următoarele principii:
1. Informaţiile se împart în absolute şi auxiliare; informaţiile absolute sunt suficiente, în principiu, pentru definirea totală a
SGF; informaţiile auxiliare servesc pentru accelerarea accesului,
2. Dacă o informaţie auxiliară este utilizată pentru un acces, validitatea accesului este întotdeauna verificată utilizând o
informaţie absolută,
3. Informaţiile auxiliare pot fi reconstituite pornind de la cele absolute.
Sunt disponibile următoarele funcţii:
 crearea unui fişier (iniţial vid),
 adăugarea unei pagini la sfârşitul unui fişier,
 distrugerea ultimei pagini a unui fişier,
 citirea sau scrierea unei pagini oarecare a unui fişier,
 distrugerea fişierului.
Un fişier este desemnat cu ajutorul unui nume intern FV, care este concatenarea unui nume unic F şi unui număr de versiune V. O
pagină cu numărul N a unui fişier FV este desemnată printr-un nume logic (FV, N). Orice acces la o pagină a fişierului utilizează
numele său logic.
Fiecare pagină ocupă un bloc pe disc. Un bloc cu adresa fizică AD pe disc, care conţine o pagină (FV, N) conţine următoarele
informaţii:
 numărul discului şi adresa AD paginii pe acest disc,
 un antet compus după cum urmează:
F nume unic absolut
V numărul versiunii absolut
N numărul paginii în fişier absolut
AP adresa pe disc a paginii N-1 auxiliar
AS adresa pe disc a paginii N+1 auxiliar
 256 octeţi care conţin “valoarea” paginii fişierului.
Desemnarea externă a fişierelor este realizată cu ajutorul cataloagelor, care ele singure sunt fişiere. Orice intrare a unui catalog, care
corespunde unui fişier, este un triplet (id, FV, AD) unde:
id este identificatorul fişierului
FV este numele intern al fişierului
AD este adresa pe disc a paginii 0 a fişierului.
Un fişier poate aparţine mai multor cataloage; unul dintre acestea fiind identificat catalog proprietar.
Fiecare fişier conţine o pagină suplimentară, numită pagină de gardă, identificată de numărul –1. Această pagină conţine:

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.15 din25


 identificatorul fişierului,
 numele catalogului proprietar şi adresa primei sale pagini.
Aceste informaţii sunt absolute, conţinutul catalogului, din contra, este considerat informaţii auxiliare.
Principiul redundanţei active este realizat după cum urmează.
a) Verificare la alocare şi la eliberare
Un bloc liber are antetul plin de zerouri. Această informaţie este absolută; tabelul de ocupare a discului (un bit per bloc, starea liber
sau ocupat) are doar valoare auxiliară.
Antetul unei pagini este modificat în două situaţii:
 la prima scriere după alocare; se verifică dacă blocul este liber,
 la eliberarea blocului; se verifică dacă FV este al paginii eliberate, umplând antetul cu zerouri.
b) Verificarea accesului
Numele absolut al unei pagini de fişier este (FV, N); este numele utilizat pentru specificarea unui acces. De fapt, aceasta este o adresă,
informaţie auxiliară, care este utilizată pentru operaţia fizică de acces. La fiece acces fizic la o pagină antetul acesteia este consultat
pentru a verifica dacă numele absolut (FV, N), care-i prezent aici este chiar cel al paginii specificate. Modul de funcţionare a
controlerului discului permite executarea acestei operaţii “din zbor” fără a pierde o turaţie a discului.
c) Restabilirea
Operaţia de restabilirea permite reconstituirea informaţiilor auxiliare pornind de la informaţiile absolute, în mod special:
 se verifică, dacă toate legăturile sunt valide şi sunt restabilite care au putut fi distruse,
 sunt restabilite cataloagele,
 este restabilit tabelul de ocupare a discului,
 sunt semnalate toate incoerenţele, care nu au putut fi reparate.
Restabilirea este realizată la lansarea sistemului, dar mai poate fi cerută, dacă au apărut unele incoerenţe în timpul lucrului. Algoritmul
restabilirii poate fi de forma:
1) Va fi parcurs tot discul, bloc cu bloc; pentru fiecare bloc de număr i procedându-se după cum urmează:
 dacă antetul blocului conţine doar zerouri, se va marca blocul i liber în tabelul de ocupare,
 în caz contrar, să se introducă (FV, N, i) într-un tabel de blocuri, triat conform FV, N; să se verifice legăturile şi să fie
actualizate, dacă este cazul.
2) Vor fi parcurse toate cataloagele (cataloagele au numerele F rezervate); se va verifica dacă fiecare catalog conţine un pointer la
pagina 0 a unui fişier; dacă rămân fişiere necatalogate, se va crea o intrare pentru fiecare în catalogul proprietarului său; dacă
acest catalog nu există, fişierul va fi clasat într-un catalog al fişierelor eronate.
3) Vor fi inventariate fişierele, care nu au putut fi restabilite. ◄

6.5.2.2. Salvare periodică


Se poate apriori conveni să fie salvate, la intervale regulate de timp, toate informaţiile conţinute într-un SGF.
Admiţând o salvare pe discul dur la un debit de 20 Mo/s, durata acestei operaţii este de aproximativ 50 s pentru 1 Go.
Poate fi realizată salvarea doar a modificărilor, care au avut loc pentru ultima perioadă, concomitent cu lucrul normal al
sistemului.
Informaţiile obţinute în acest mod pot fi utilizate în două moduri:
 la cererea explicită a unui utilizator, pentru a restabili o stare anterioară a unui fişier specificat,
 după o pană, conform procedurii de mai jos.
În caz de pană, se va încerca mai întâi să se restabilească informaţiile SGF utilizând redundanţa internă, cum a fost
descris mai sus. La terminarea acestei operaţii vom avea la dispoziţie o listă a fişierelor bănuite a fi alterate. După aceasta
vor fi restabilite fişierele presupuse a fi alterate, folosind datele cele mai recent salvate.
6.5.3. Protecţia fişierelor
Protecţia fişierelor foloseşte principiul listelor de acces. O listă de acces, asociată unui fişier, conţine drepturile
fiecărui utilizator asupra fişierului, adică mulţimea operaţiilor care îi sunt permise. În practică, diferite convenţii permit
reducerea listei. Este definită mai întâi mulţimea drepturilor atribuite implicit fiecărui utilizator (mulţime, care poate fi
vidă); lista de acces va conţine doar utilizatorii, drepturile cărora diferă de cele implicite. Convenţii de grupare permit
asocierea unei mulţimi de drepturi unui grup de utilizatori (membrii unui proiect, etc.), ceea ce reduce şi mai mult lista.
Lista de acces serveşte la verificarea validităţii oricărei operaţii asupra fişierului.
6.5.4. Autentificarea în Windows NT
Sistemul de operare Windows NT posedă mai multe instrumente de control a drepturilor de acces al utilizatorilor la
resursele sistemului. Aceste instrumente ar fi absolut inutile în lipsa posibilităţii de a controla dacă la calculator se află
anume acel utilizator, care corespunde datelor de evidenţă. Mecanismul, cu ajutorul căruia un utilizator îşi poate confirma
autenticitatea se numeşte de autentificare. Autentificarea se produce în baza unui element secret (autentificator), aflat
doar în posesia utilizatorului definit de informaţia de evidenţă. De obicei, drept autentificator serveşte parola
utilizatorului, însă acesta poate fi şi o cartelă specială (smart, badge) sau informaţii, legate de datele biometrice ale
utilizatorului. Windows NT permite dezvoltatorilor externi extinderea mecanismelor de autentificare. SO Windows NT
execută autentificarea la intrarea în sistem. Pentru majoritatea cazurilor aceasta este suficient, deoarece sistemul în mod
automat personalizează accesul în baza numelui utilizatorului intrat în sistem. Mai mult, Microsoft nu recomandă
introducerea unor mecanisme de autentificare proprii în aplicaţii, respectând principiul intrării unice (Unified Logon) –
utilizatorul trebuie să introducă parola o singură dată la intrarea în sistem. Există mai multe motivaţii pentru aceasta:
1. Cereri suplimentare de introducere a numelui şi parolei pot fi enervante pentru unii utilizatori,

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.16 din25


2.Programarea incorectă a mecanismului de autentificare poate diminua securitatea sistemului,
3.Windows NT permite extinderea mecanismului de autentificare. Programele, construite cu un mecanism
propriu de autentificare pot fi inutile, dacă sistemul utilizează un alt mecanism, decât cel presupus la
elaborarea aplicaţiei.
Dacă se presupune obligator controlul numelui utilizatorului şi a parolei, pot fi propuse două metode de autentificare:
1. cu ajutorul funcţiei LogonUser - este cea mai simplă metodă, dar cere existenţa unor priorităţi pentru cel
care apelează funcţia dată (nu este cazul şi pentru Windows XP).
2. utilizând Security Support Provider Interface (SSPI) - o metodă mai complicată, dar nu cere priorităţi
suplimentare. Mai mult, metoda este funcţională şi pentru autentificare la distanţă.
Vom mai cerceta şi metoda bazată pe funcţia NetUserChangePassword, recomandată pentru controlul parolelor.
Unii autori nu agreează această metodă la prima vedere foarte simplă.
Fiecare metodă va fi ilustrată cu ajutorul unei funcţii de forma:
BOOL CheckPassword_Method(
IN PCTSTR pszDomainName, // numele domenului
IN PCTSTR pszUserName, // numele utilizatorului
IN PCTSTR pszPassword, // parola
OUT PHANDLE phToken // token-ul utilizatorului
);
La intrarea funcţiei se va da numele informaţiei de evidenţă, parola şi numele domenului care conţine înregistrarea de
evidenţă. Numele domenului poate fi NULL, în acest caz funcţia alege singură domenul. Dacă numele utilizatorului şi
parola au fost indicate corect, funcţia returnează TRUE, altfel – FALSE. Codul erorii poate fi obţinut prin funcţia
GetLastError. Funcţia mai întoarce aşa numitul token al utilizatorului (obiectul marker). Acesta poate fi util, dacă va fi
necesar să se îndeplinească anumite operaţiuni în numele utilizatorului autentificat (cerere de ajutor în cazul în care parola
a fost uitată poate fi un exemplu). În caz contrar parametrul phToken poate fi pus NULL.
6.5.4.1. Funcţia LogonUser
Funcţia LogonUser din Win32 API este destinată exclusiv pentru soluţionarea problemei autentificării şi este de
forma:
BOOL LogonUser(
PTSTR pszUsername, // numele utilizatorului
PTSTR pszDomain, // numele domenului
PTSTR pszPassword, // parola
DWORD dwLogonType, // tipul accesării
DWORD dwLogonProvider, // provider-ul accesării
PHANDLE phToken // token-ul utilizatorului
);
Destinaţia primilor trei parametri este evidentă. Unele versiuni timpurii ale SO Windows NT nu permiteau să fie
indicată valoarea NULL pentru numele domenului. Acest caz trebuie tratat în mod separat, dacă se doreşte ca procedura
autentificării să funcţioneze în toate versiunile sistemului. Parametrul dwLogonType indică modul de intrare în sistem.
Principiul de bază, care permite diferenţierea intrărilor în sistem, este legat de priorităţile prezente în informaţiile de
evidenţă şi setul de grupe introdus în token-ul final. De exemplu, dacă se încearcă intrarea în sistem în regim de tratare pe
loturi, informaţia de evidenţă, desemnată de parametrul pszUsername, trebuie să posede prioritatea
SE_BATCH_LOGON_NAME, iar în token-ul utilizatorului va fi adăugat grupul Batch (S-1-5-3). Suplimentar există o
serie de diferenţe subtile, care pot fi găsite în documentaţia LogonUser. Pentru exemplul nostru vom folosi metoda de
intrare LOGON32_LOGON_NETWORK, care este cea mai rapidă. În acest caz utilizatorii, controlaţi cu ajutorul
funcţiei date, trebuie să posede dreptul de intrare în reţea (în mod implicit toţi utilizatorii au acest drept). Parametrul
dwLogonProvider indică care provider va fi utilizat. Utilizând valoarea LOGON32_PROVIDER_DEFAULT, va fi
folosit provider-ul implicit. Parametrul phToken punctează variabila în care, în caz de succes, va fi introdus token-ul
utilizatorului.
Mai jos este prezentat un fragment de cod în care funcţia CheckPassword_LogonUser foloseşte LogonUser pentru
controlul numelui şi parolei utilizatorului:
BOOL CheckPassword_LogonUser(
IN PCTSTR pszDomainName,
IN PCTSTR pszUserName,
IN PCTSTR pszPassword,
OUT PHANDLE phToken
)
{

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.17 din25


_ASSERTE(pszUserName != NULL);
_ASSERTE(pszPassword != NULL);

HANDLE hToken;

TCHAR szDomainName[DNLEN + 1];


TCHAR szUserName[UNLEN + 1];
TCHAR szPassword[PWLEN + 1];

if (pszDomainName == NULL)
{
BYTE bSid[8 + 4 * SID_MAX_SUB_AUTHORITIES];
ULONG cbSid = sizeof(bSid);
ULONG cchDomainName = countof(szDomainName);
SID_NAME_USE Use;

if (!LookupAccountName(NULL, pszUserName, (PSID)bSid, &cbSid,


szDomainName, &cchDomainName, &Use))
return FALSE;
}
else
lstrcpyn(szDomainName, pszDomainName, countof(szDomainName));

lstrcpyn(szUserName, pszUserName, countof(szUserName));


lstrcpyn(szPassword, pszPassword, countof(szPassword));

if (!LogonUser(szUserName, szDomainName, szPassword,


LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
&hToken))
return FALSE;

if (phToken == NULL)
_VERIFY(CloseHandle(hToken));
else
*phToken = hToken;
return TRUE;
}
Câteva comentarii sunt necesare. În primul rând, toate string-urile de intrare sunt copiate în masive speciale din stiva
funcţiei. Aceasta este necesar din cauza că toţi parametrii funcţiei sunt declaraţi constante string, iar LogonUser primeşte
indicatori la string-uri, care pot fi modificate. În unele condiţii LogonUser poate scrie în parametrii pe care îi primeşte
ceea ce poate conduce la prohibitarea protecţiei memoriei. Doi: conform celor menţionate mai sus, unele versiuni timpurii
ale sistemului de operare Windows NT nu permit valoarea NULL pentru numele domenului. Această situaţie va fi tratată
în mod individual şi numele corespunzător pentru domen este depistat cu ajutorul funcţiei LookupAccountName.
Observăm, că utilizarea funcţiei LogonUser nu este complicată, dar în Windows NT şi Windows 2000 are o restricţie
substanţială: utilizatorul, care apelează această funcţie trebuie să posede prioritatea SE_TCB_NAME. Este o prioritate
foarte înaltă, chiar nici administratorii nu o posedă, semnificând controlul total asupra sistemului. TCB - Trusted
Computing Base (Baza Calculelor Sigure, în care poţi avea încredere) este o componentă a sistemului de calcul, care
asigură îndeplinirea politicii securităţii. Este un cod, executat în regim de nucleu şi un cod de regim user, executat în
contextul informaţiilor de evidenţă, care are prioritatea TCB. Deşi nu este periculos să fie acordată această prioritate
înregistrării de evidenţă, destinate execuţiei unui serviciu de sistem, Microsoft nu recomandă acest lucru, ci recomandă să
fie executat un cod, care cere prezenţa priorităţii TCB în contextul înregistrării de evidenţă de sistem. Folosirea
înregistrării de evidenţă de sistem are un avantaj: aceasta nu posedă parolă, în rezultat ea nu poate fi furată sau calculată.
Dacă nu este respectată recomandarea Microsoft, securitatea sistemului este redusă la zero, controlul parolei devenind
inutil.
Necesitatea prezenţei priorităţii TCB restricţionează substanţial domeniul de utilizare a metodei date. În Windows XP
LogonUser nu mai cere prezenţa priorităţii TCB la apelant, dar numărul de copii Windows NT şi Windows 2000 este
încă foarte mare.

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.18 din25


6.5.4.2. Autentificare cu ajutorul Security Support Provider Interface
O altă posibilitate este cea bazată pe Security Support Provider Interface (SSPI), o variaţie a standardului
Generic Security Service API (GSS-API), realizat de firma Microsoft. Ambele interfeţe sunt destinate autentificării şi
protecţiei informaţiilor, transmise prin reţea. Ideea se bazează pe faptul, că toate protocoalele autentificării de reţea (fie
NTLM, Kerberos sau SSL) pot fi reprezentate sub forma unui schimb ordonat de mesaje, în timpul căruia un participant
identifică pe celălalt (sau părţile se autentifică reciproc). Evident, SSPI poate fi utilizat şi local, în acest caz transmiterea
pachetelor prin reţea este înlocuită de transmiterea zonei de memorie tampon dintr-un loc al programului în altul.
SSPI este doar o interfaţă care permite acces standardizat la diferite pachete de securitate (security packages). În
componenţa SO Windows NT 4 intră un singur pachet (NTLM), care poate fi utilizat pentru autentificarea utilizatorilor.
Începând cu Windows 2000 la acest pachet au mai fost adăugate pachetele Kerberos şi Negotiate. Fragmentul de cod,
care urmează controlează corectitudinea numelui şi parolei unui utilizator folosind interfaţa SSPI şi pachetul de
securitate NTLM.
BOOL CheckPassword_SSPI(
IN PCTSTR pszDomainName,
IN PCTSTR pszUserName,
IN PCTSTR pszPassword,
OUT PHANDLE phToken
)
{
_ASSERTE(pszUserName != NULL);
_ASSERTE(pszPassword != NULL);

ULONG lRes;
CSspiClient Client;
CSspiServer Server;

// iniţializarea obiectului client


lRes = Client.Initialize(pszDomainName, pszUserName, pszPassword);
if (lRes != ERROR_SUCCESS)
return SetLastError(lRes), FALSE;

// iniţializarea obiectului server


lRes = Server.Initialize();
if (lRes != ERROR_SUCCESS)
return SetLastError(lRes), FALSE;

PVOID pRequest = NULL, pResponse = NULL;


ULONG cbRequest, cbResponse;

// generarea cererii iniţiale de autentificare


lRes = Client.Start(&pRequest, &cbRequest);
if (lRes != ERROR_MORE_DATA)
return SetLastError(lRes), FALSE;

// ciclul principal de schimburi de mesaje


for (;;)
{
// prelucrarea cererii client şi generarea răspunsului
lRes = Server.Continue(pRequest, cbRequest,
&pResponse, &cbResponse);
if (lRes != ERROR_MORE_DATA)
break;

Client.FreeBuffer(pRequest);
pRequest = NULL;

// prelucrarea cererii serverului şi crearea unei cereri noi

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.19 din25


lRes = Client.Continue(pResponse, cbResponse,
&pRequest, &cbRequest);
if (lRes != ERROR_SUCCESS &&
lRes != ERROR_MORE_DATA)
break;

Server.FreeBuffer(pResponse);
pResponse = NULL;
}

if (pRequest != NULL)
Client.FreeBuffer(pRequest);
if (pResponse != NULL)
Server.FreeBuffer(pResponse);

if (lRes != ERROR_SUCCESS)
return SetLastError(lRes), FALSE;

// control înregistrare de evidenţă a oaspeţilor


lRes = Server.CheckGuest();
if (lRes != ERROR_SUCCESS)
return SetLastError(lRes), FALSE;

// creare token la necesitate


if (phToken != NULL)
{
lRes = Server.GetToken(phToken, TOKEN_ALL_ACCESS);
if (lRes != ERROR_SUCCESS)
return SetLastError(lRes), FALSE;
}

return TRUE;
}
În codul iniţial al funcţiei CheckPassword_SSPI nu există apelări directe a funcţiei SSPI – toate apelurile sunt incluse
în superclasele СSspiClient şi CsspiServer. Aceasta permite pe de o parte evidenţierea schimbului de mesaje între
client şi server, iar pe de altă parte – folosirea acestor clase în calitate de bază, dacă se doreşte realizarea autentificării de
reţea în aplicaţie.
Lucrul începe cu crearea şi iniţializarea obiectelor clientului şi ale serverului, în procesul de iniţializare obiectului
clientului fiindu-i transmise informaţii despre utilizator. Apoi este apelată metoda CSspiClient::Start, pentru a genera
cererea iniţială de autentificare şi are loc trecerea în ciclul de mesaje. Aici funcţia apelează metoda
CSspiServer::Continue şi CSspiClient::Continue. Aceste metode primesc la intrare mesajul celeilalte părţi şi
returnează mesajul de răspuns. Ciclul de mesaje durează până în momentul în care serverul stabileşte, că autentificarea s-a
petrecut cu succes sau invers. Pentru autentificarea NTLM în Windows NT 4.0 şi Windows 2000 este caracteristic
următorul moment: dacă un client încearcă să intre în sistem cu un nume necunoscut nici pentru sistemul local, nici
pentru domene, şi în sistemul local nu este blocată înregistrarea de evidenţă a oaspeţilor, atunci autentificarea se termină
cu succes, iar clientul intră în sistem sub numele înregistrării locale de evidenţă a oaspeţilor. Aceasta s-a realizat din
dorinţa compatibilităţii cu produsul mai vechi al firmei Microsoft NT Lan Manager (de unde şi vine numirea NTLM).
De aceea, în caz de succes, este apelată metoda CSspiServer::CheckGuest, care controlează, dacă nu cumva succesul
autentificării se datorează acestui moment. În sfârşit, dacă este necesar token-ul utilizatorului, funcţia apelează metoda
CSspiServer::GetToken, responsabilă de obţinerea token-ului. Cercetarea claselor CSspiClient şi CsspiServer, care
necesită o studierea mai amănunţită a interfeţei SSPI, este lăsată ca exerciţiu.
6.5.4.3. Funcţia NetUserChangePassword
Utilizarea acestei funcţii pentru autentificare are loc conform codului care urmează:
BOOL CheckPassword_ChangePwd(
IN PCTSTR pszDomainName,
IN PCTSTR pszUserName,
IN PCTSTR pszPassword,

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.20 din25


OUT PHANDLE phToken
)
{
_ASSERTE(pszUserName != NULL);
_ASSERTE(pszPassword != NULL);
_ASSERTE(phToken == NULL);

USES_CONVERSION;

PCWSTR pszPasswordW = T2CW(pszPassword);

ULONG lRes = NetUserChangePassword(T2CW(pszDomainName),


T2CW(pszUserName), pszPasswordW, pszPasswordW);

if (lRes == ERROR_INVALID_PASSWORD ||
lRes == NERR_UserNotFound)
return SetLastError(ERROR_LOGON_FAILURE), FALSE;

return TRUE;
}
Există mai multe considerente, care nu recomand utilizarea acestei funcţii pentru autentificare. Principalul considerent
este faptul, că funcţia NetUserChangePassword nu este destinată autentificării utilizatorilor.

6.6. SGF din sistemul de operare Unix


Descriem cu titlu de exemplu organizarea fişierelor în sistemul de operare Unix.
6.6.1. Caracteristici generale
Toate fişierelor manipulate de utilizator formează o bază de date de tip ierarhic, modelul matematic fiind un arbore în
care vârfurile intermediare corespund cataloagelor, iar frunzele – cataloagelor vide sau fişierelor. Structura sistemului de
gestiune a fişierelor este prezentată în fig. 6.11. În realitate fiecare disc logic conţine o structură ierarhică separată de
cataloage şi fişiere. Pentru a obţine în mod dinamic arborele general este utilizată „conectarea” ierarhiilor separate la o
rădăcină fixă a sistemului de fişiere. În mediul utilizatorilor sistemului de operare UNIX istoric noţiunea de „sistem de
fişiere” semnifică în acelaşi timp ierarhia cataloagelor şi fişierelor şi partea nucleului sistemului de operare, care
administrează cataloagele şi fişierele. Ar fi mai corect că numim ierarhia cataloagelor şi fişierelor arhivă a fişierelor, iar
noţiunea de „sistem de fişiere” să fie utilizată doar în cel de-al doilea sens.
Utilizatorii sistemului de operare Unix cunosc trei tipuri de fişiere: fişiere ordinare, cataloage şi fişiere speciale.
Fişierele speciale sunt de fapt unica cale de acces direct la periferice; utilizarea lor este prezentată mai târziu. Diferenţa
dintre fişierele ordinare şi cataloage este că modificarea conţinutului cataloagelor este permisă doar prin intermediul unor
comenzi speciale ale sistemului. Un fişier în Unix este o suită de caractere (8 biţi); alte structurări nu sunt furnizate de
către SGF. Sistemul de gestiune a fişierelor nu face nici o ipoteză despre conţinutul fişierelor ordinare, interpretarea fiind
pusă în şarja utilizatorului.
Desemnarea fişierelor se bazează pe schema arborescentă, descrisă în 5.2.2. Identificatorii sunt interpretaţi în mediul
catalogului curent; simbolurile speciale . (un punct) şi .. (două puncte) desemnează respectiv, în orice mediu, altul decât
catalogul rădăcină, catalogul curent şi tatăl său. Simbolul / desemnează catalogul rădăcină; orice identificator, care începe
cu / este interpretat în mediul rădăcinii. Acelaşi simbol / serveşte ca separator pentru numele calificate.
Este posibilă crearea unor legături la un fişier. O legătură, definită pentru fişier, cablează un nume nou, care are
acelaşi statut ca şi numele iniţial. Pentru a păstra organizarea arborescentă a cataloagelor nu se permite crearea unei
legături la un catalog. Suprimarea ultimei legături la un fişier antrenează în mod automat distrugerea fişierului.
6.6.2. Organizarea datelor
6.6.2.1. Descriptorii
Într-un catalog, intrarea care corespunde unui fişier conţine identificatorul fişierului şi un nume intern, care este
indicele descriptorului său într-un tabel general, asociat suportului. Descriptorul (“i-nod” în terminologia Unix) conţine:
 tipul fişierului (ordinar, catalog, special),
 numele şi grupul proprietarului fişierului (v.6.5.3),
 informaţiile de protecţie,
 informaţiile localizării fizice (v.6.3.2.2),

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.21 din25


 lungimea fişierului, în caractere,
 datele despre creare, ultima modificare, ultimul acces.
Fiecare suport fizic are un tabel propriu al descriptorilor (6.6.2.4).

punct de montare a unui catalog

catalog

fişier obişnuit

fişier special

SGF la distanţă

cale

Fig.6.11. Structura SGF UNIX


6.6.2.2. Implantarea fizică
Memoria secundară este organizată în blocuri de lungime fixă (512 octeţi). În descriptorul unui fişier este rezervat un
tabel T de 13 cuvinte pentru informaţiile despre localizarea fizică. În dependenţă de numărul t al blocurilor ocupate de
fişier, sunt utilizate 1, 2 sau 3 niveluri de direcţionare (v.6.3.2.2):
 cuvintele de la T[0] la T[9] conţin adresele blocurilor 0 – 9 ale fişierului (ultimele fiind puse în 0, dacă t<10),
 dacă t>10, cuvântul T[10] conţine adresa unui tabel de implantare de 128 de cuvinte, în care sunt adresele
blocurilor de la 10 la 137,
 dacă t>138, în cuvântul T[11] se află adresa unui tabel, care stabileşte adresele a 128 noi tabele de implantare; se
poate ajunge astfel până la 10+128+1282 = 16522 blocuri,

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.22 din25


 în sfârşit, dacă t>16522, pentru blocurile următoare este utilizată o direcţionare pe trei niveluri; adresa tabelului
primar este în T[12]; se poate astfel atinge o lungime maximă de 16522+1283 = 2 113 674 blocuri.
Notăm, că timpul de accesare a informaţiilor unui fişier nu este uniform, începutul fişierului fiind privilegiat. Astfel,
timpul de acces la primele 5120 caractere (10 blocuri) nu depinde de lungimea fişierului. Această proprietate poate fi
exploatată, plasând în fişier informaţiile cel mai frecvent utilizate.
Dacă există mai multe suporturi de memorie secundară, sau volume, pentru fişiere, fiecărui suport i se va asocia un
tabel distinct de descriptori. Tabelul se află la o adresă fixă pe volum. Numele intern al unui fişier este cuplul (adresă
suport, indicile descriptorului în tabel).
6.6.2.3. Administrarea perifericelor
Perifericele sunt reprezentate de fişiere speciale, grupate într-un catalog unic (/dev). În locul informaţiilor de
implantare, descriptorul unui fişier special conţine un pointer la descriptorul perifericului, care, la rândul său conţine doi
indici, numiţi major şi minor. Indicele major identifică tipul perifericului şi punctează la programele primitivelor sale de
acces, partajate de periferice de acelaşi tip. Indicele minor identifică individual fiecare periferic şi permite accesul la
datele sale proprii, adică la tampoanele de intrare-ieşire utilizate.
6.6.2.4. Volume amovibile
Administrarea volumelor amovibile este realizată conform principiilor, descrise în 5.2.3.2. Catalogul unui volum
amovibil este organizat exact ca şi catalogul general. Comanda unei montări logice (montare) permite integrarea
catalogului unui volum în catalogul general, la un nivel oarecare şi cu un nume ales. De la acest moment, toate fişierele
volumului devin accesibile. Unica restricţie este că nu-i posibilă crearea unor legături între suporturi diferite: un fişier
dintr-un volum este accesibil doar traversând rădăcina catalogului acestui volum, iar această rădăcină nu punctează la
tatăl său. Sunt evitate astfel orice căutări de legături la demontare.

TDA
nume local
0
TFD
nmax

utilizatorul 1 citire ptr1

exec ptr2

utilizatorul 2
[în memorie]

[pe disc]

descriptor

zona descriptorilor
blocuri
Fig.6.12. Descriptorii fişierelor în Unix

6.6.3. Funcţionarea şi utilizarea


6.6.3.1. Gestiunea descriptorilor. Nume locale
Din considerente de economie, doar descriptorii fişierelor deschise au o copie în memoria centrală. Aceşti descriptori,
zişi activi, sunt grupaţi într-un tabel unic (TDA). Un fişier poate fi deschis simultan de mai mulţi utilizatori, fiecare
utilizându-l independent cu ajutorul unui pointer de citire-scriere propriu. Acest pointer nu poate fi conţinut în
descriptorul fişierului, care este unic: el este păstrat într-un tabel rezident, numit tabel al fişierelor deschise (TFD). La
fiecare nouă deschidere în acest tabel este creată o intrare nouă şi mai multe intrări pot desemna acelaşi fişier, deschis

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.23 din25


simultan pentru mai mulţi utilizatori. Plus la pointerul de citire-scriere, această intrare conţine modul de deschidere a
fişierului şi un pointer la o intrare a TDA (fig.6.12).
În sfârşit, pentru a reduce frecvenţa căutărilor în cataloage şi a simplifica desemnarea, un utilizator poate desemna un
fişier printr-un nume local. Acest nume, care este un întreg din intervalul 0..nmax (nmax având valori până la 20), este
alocat la deschiderea fişierului. El serveşte ca indice într-un tabel al numelor locale, păstrat în spaţiul propriu al fiecărui
utilizator. Intrările acestui tabel sunt pointeri la TFD. Să ne amintim, că un nume local este de fapt un nume de flux, care
poate în egală măsură desemna un fişier sau un tub (v.5.2.3.1).
6.6.3.2. Primitive de acces
Funcţiile de acces, descrise mai jos sunt primitive realizate prin apelarea regimului supervizor. Ele sunt utilizate
pentru a realiza operaţiile disponibile în limbajul de comandă. Fiecare primitivă returnează un rezultat de tip întreg, care
serveşte în special pentru a semnala erorile posibile.
Primitiva dup (duplicare) permite crearea unui alt nume local pentru un fişier deja deschis. Ea serveşte în special
pentru a conecta tuburile şi pentru a determina, dacă un nume local dat este al unui fişier deschis.

Citirea şi scrierea are loc pornind de la o poziţie curentă, definită de un pointer. Aceste operaţii incrementează în mod
automat pointerul cu numărul de caractere citite sau scrise. Primitiva lseek permite deplasarea explicită a pointerului.
Denumirea operaţiei Efectul Rezultatul
open(nume fişier, mod de acces) deschide fişierul cu modul de acces indicat nume local alocat (-1 dacă eşec)
close(nbloc) abrogă asocierea între numele local nbloc şi succes → 0, eroare → -1
fişierul (sau tub) asociat
dup(nbloc) dacă nbloc este numele local al unui fişier succes → nbloc1, eroare → -1
deschis, alocă un alt nume local nbloc1
sinonimul lui nbloc (desemnând acelaşi
fişier)
read(nbloc,tampon,ncar) citeşte ncar caractere din fişierul (sau tub) numărul de caractere citite efectiv
cu numele local nbloc în zona tampon (mai mic decât ncar, dacă s-a
ajuns la sfârşitul fişierului)
write(nbloc,tampon,ncar) scrie ncar caractere din zona tampon în numărul de caractere efectiv scrise
fişierul (sau tubul) cu numele local nbloc
lseek(nbloc,depl,orig) deplasează pointerul de citire-scriere depl poziţia curentă nouă, (-1 în caz de
caractere, pornind de la poziţia definită de eroare)
orig: 0 – începutul fişierului,
1 – poziţia curentă a pointerului
2 – sfârşitul fişierului
Notăm, că este posibil să deplasăm pointerul după sfârşitul fişierului. Efectul este sporirea lungimii fişierului, poziţiile
intermediare rămânând goale; aceste “găuri” nu ocupă loc în memorie.
6.6.3.3. Protecţia fişierelor în UNIX
Protecţia este asigurată cu ajutorul listelor de acces conform principiului din 6.5.3. Există trei moduri de acces
elementar: citire, execuţie, scriere pentru un fişier; consultare, acces, modificare pentru un catalog.
Pentru controlul drepturilor, utilizatorii nu sunt individualizaţi, ci partajaţi în trei clase: proprietarul fişierului, membrii
unui grup de utilizatori, restul utilizatorilor. Lista de acces la un fişier este, deci, de lungime fixă; ea enumără drepturile
de acces ataşate fiecărei grupe; ea poate fi modificată doar de proprietarul fişierului sau de administratorul sistemului. O
caracteristică originală a sistemului de protecţie este că proprietarul unui fişier poate fi schimbat.
De la începuturi UNIX a fost gândit ca un sistem de operare interactiv. Pentru a începe lucrul un utilizator trebuie „să
intre” în sistem, introducând de la terminal numele propriu de evidenţă (contul, account name) şi, poate, parola
(password), devenind astfel utilizator înregistrat al sistemului. Noii utilizatori sunt introduşi (înregistraţi) de către
administrator. Utilizatorul nu-şi poate modifica contul propriu, în schimb parola este la discreţia lui. Parolele sunt
codificate şi păstrate într-un fişier separat. Nici administratorul nu poate restabili o parolă uitată. Fiecărui utilizator
înregistrat îi corespunde un catalog propriu al SGF, numit home. La intrare utilizatorului i se conferă acces total la acest
catalog, inclusiv şi la toate cataloagele şi fişierele, care se conţin aici. Accesul la alte cataloage şi fişiere poate fi
restricţionat.
Deoarece UNIX este un sistem de operare multiuser, o problemă foarte actuală este problema autorizării accesului
utilizatorilor la fişierele SGF. Prin „autorizarea accesului” sunt considerate acţiunile sistemului, care conduc la permiterea
sau interzicerea accesului unui utilizator concret la un fişier dat în dependenţă de drepturile de acces ale utilizatorului şi

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.24 din25


restricţiile de acces, asociate fişierului. Schema autorizării accesului în UNIX este foarte simplă, în acelaşi timp foarte
comodă şi puternică, încât a devenit standard de facto pentru sistemele contemporane.
Fiecărui proces în SO UNIX îi sunt asociate un identificator real şi un identificator activ al utilizatorului. Aceşti
identificatori sunt desemnaţi cu ajutorul apelului de sistem setuid, care poate fi executat doar în mod supervizor.
Analogic, de fiecare proces sunt legaţi doi identificatori ai grupului de utilizatori – unul real şi unul activ. Aceştia sunt
desemnaţi cu ajutorul apelului de sistem privilegiat setgid. La intrarea utilizatorului în sistem programul login
controlează, dacă utilizatorul este înregistrat în sistem şi a introdus parola corectă (dacă parola este necesară), formează
un proces nou şi lansează în acest proces mediul (shell) utilizatorului dat. Dar, înainte de aceasta login setează, pentru
procesul nou creat, identificatorii utilizatorului şi grupului, folosind informaţia din fişierele /etc/passwd şi /etc/group.
Restricţiile de accesare a fişierelor devin active după legarea acestor identificatori de proces. Procesul poate avea acces la
un fişier sau să execute un fişier executabil numai dacă restricţiile de accesare, păstrate cu fişierul permit aceasta.
Identificatorii procesului sunt transmişi tuturor proceselor descendente, extinzând pentru acestea aceleaşi restricţii. În
unele cazuri un proces îşi poate modifica drepturile sale utilizând apelurile de sistem setuid şi setgid, iar în alte cazuri
sistemul poate modifica drepturile de accesare ale procesului în mod automat.
Fie ca exemplu următoarea situaţie. Scrierea în fişierul /etc/passwd este permisă doar administratorului (superuserul
poate scrie în orice fişier). Acest fişier conţine, printre altele, parolele utilizatorilor şi fiecare utilizator are dreptul să-şi
modifice parola. Există un program special /bin/passwd, care realizează modificarea parolelor. Însă un utilizator obişnuit
nu poate face acest lucru chiar utilizând acest program, deoarece scriere în /etc/passwd este interzisă. În UNIX problema
dată este rezolvată în modul următor. Pentru un fişier executabil poate fi indicat, că la lansarea lui vor fi setaţi
identificatorii utilizatorului şi/sau grupului. Dacă utilizatorul cere lansarea unui atare program (cu ajutorul apelului de
sistem exec), atunci pentru procesul respectiv este stabilit identificatorul utilizatorului, care corespunde identificatorului
stăpânului fişierului executabil şi/sau identificatorul grupului acestui stăpân. În particular, la lansarea programului
/bin/passwd procesului se atribuie identificatorul administratorului şi programul poate scrie în fişierul /etc/passwd.
Pentru identificatorul utilizatorului şi pentru identificatorul grupului ID real este identificatorul adevărat, iar ID activ este
identificatorul execuţiei curente. Dacă identificatorul curent al utilizatorului corespunde identificatorului
administratorului, atunci acest identificator ca şi identificatorul grupului poate fi modificat cu ajutorul apelurilor de sistem
setuid şi setgid. În cazul în care identificatorul curent al utilizatorului diferă de identificatorul administratorului, atunci
execuţia apelurilor de sistem setuid şi setgid conduce la înlocuirea identificatorului curent cu identificatorul adevărat (al
utilizatorului sau al grupului, respectiv).
În UNIX, ca şi în orice sistem de operare multiuser, este susţinut un mecanism standard de control al accesului la
fişierele şi directoriile sistemului de fişiere. Orice proces poate accesa un fişier atunci şi numai atunci, când drepturile de
acces, ataşate fişierului, corespund posibilităţilor procesului dat.
Protecţia fişierelor contra unor accese nesancţionate se bazează pe trei momente. Unu: fiecărui proces, care crează un
fişier (sau un director) este ataşat un identificator al utilizatorului (identificator unic în sistem), care mai apoi va fi
considerat ca identificatorul posesorului fişierului nou creat. Doi: de fiecare proces, care încearcă să acceseze un fişier,
este legat un cuplu de identificatori – identificatorii activi al utilizatorului şi al grupului utilizatorului. Trei: fiecărui fişier
în mod univoc îi corespunde descriptorul propriu – i-node. Informaţia dintr-un i-node conţine identificatorii posesorului
curent (imediat după crearea fişierului identificatorii posesorului curent sunt stabiliţi de către identificatorul respectiv
activ al procesului părinte, dar mai târziu pot fi modificaţi cu ajutorul apelurilor de sistem chown şi chgrp). Tot aici se
conţin indicaţii despre operaţiile permise posesorului fişierului, ce drepturi au asupra fişierului membrii grupului
posesorului şi care sunt drepturile celorlalţi utilizatori.

6.7. Exerciţii la capitolul 6

17.10.11 16:13 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\6.doc p.25 din25


7. Alocarea resurselor ......................................................................................................................................................... 2
7.1. Noţiuni generale ...................................................................................................................................................... 2
7.1.1. Definiţii ............................................................................................................................................................ 2
7.1.2. Probleme în alocarea resurselor ........................................................................................................................ 2
7.1.3. Exemple de sisteme cu fire de aşteptare ........................................................................................................... 3
7.2. Modele pentru alocarea unei resurse unice .............................................................................................................. 3
7.2.1. Alocarea procesorului ....................................................................................................................................... 3
7.2.1.1. Introducere ................................................................................................................................................. 3
7.2.1.2. Prim sosit, prim servit ................................................................................................................................ 4
7.2.1.3. Cererea cea mai scurtă servită prima ......................................................................................................... 4
7.2.1.4. Caruselul şi modele derivate ...................................................................................................................... 5
7.2.2. Disc de paginare ............................................................................................................................................... 6
7.3. Tratarea blocărilor ................................................................................................................................................... 8
7.3.1. Enunţul problemei ............................................................................................................................................ 8
7.3.2. Algoritmi de prevenire...................................................................................................................................... 8
7.3.2.1. Algoritmi de profilaxie .............................................................................................................................. 8
7.3.2.2. Algoritmul bancherului .............................................................................................................................. 9
7.3.3. Algoritmi de detectare şi tratare ..................................................................................................................... 10
7.4. Exerciţii la capitolul 7 ........................................................................................................................................... 10

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.1 din 11


7. Alocarea resurselor
În acest capitol prezentăm principiile de alocare a resurselor într-un sistem informatic. Sunt abordate două aspecte:
1. utilizarea rezultatelor teoriei firelor de aşteptare pentru analiza câtorva modele simple ale sistemelor informatice,
în special pentru alocarea procesoarelor;
2. prezentarea unor metode de evitare a impasurilor (blocarea reciprocă a mai multor procese rezultată din alocarea
eronată a unor resurse comune).

7.1. Noţiuni generale


7.1.1. Definiţii
Numim resursă orice obiect, care poate fi utilizat de către un proces. Unei resurse îi sunt asociate proceduri de
acces, care permit utilizarea resursei şi reguli de utilizare, care constituie “modul de utilizare”. Exemple de asemenea
reguli au fost aduse în capitolul 4 (acces exclusiv, cititori-redactori, etc.). Nu există vre-o diferenţă fundamentală între
noţiunea de obiect şi cea de resursă. Folosirea celor doi termeni semnifică mai mult o diferenţă de domeniu: se
utilizează noţiunea obiect atunci când ne interesează specificarea şi realizarea obiectului şi a funcţiilor sale de acces, iar
resursă pentru problemele de alocare şi partajare.
Se spune că o resursă este alocată unui proces dacă procesul poate utiliza resursa, folosind procedurile ei de acces.
Legarea unei resurse de un proces poate fi implicită sau explicită. În primul caz, este suficientă trecerea procesului într-
o anumită stare pentru ca el să devină candidat la utilizarea resursei; în cel de-al doilea caz, solicitarea trebuie să fie
formulată explicit sub forma unei cereri adresate unui alocator al resursei. Alocatoarele şi cererile pot lua forme
diverse: de exemplu, un alocator poate fi un proces căruia cererile îi sunt transmise prin emiterea unor mesaje; sau chiar
un monitor (v. capitolul 4) o procedură a căruia serveşte la emiterea unor mesaje. Reacţia unui alocator la o cerere poate
de asemenea fi diferită: alocarea resursei solicitate, refuz cu sau fără blocarea procesului solicitant. Terminarea utilizării
unei resurse de către un proces poate la fel lua diferite forme: eliberarea explicită sau implicită a resursei sau
retragerea forţată a resursei de către alocator. O resursă se numeşte banalizată dacă ea există în mai multe exemplare
echivalente, în sensul că o cerere poate fi satisfăcuta de alocator folosind indiferent care exemplar al resursei. Aceste
noţiuni sunt precizate de câteva exemple.
Exemplul 7.1. Procesorul. Procedurile “de acces” la procesor sunt determinate de instrucţiuni şi cuvântul de stare; alocarea procesorului unui
proces se face prin încărcarea cuvântului său de stare. Nu există cereri explicite: pentru a fi în stare să depună o astfel de cerere,
procesul ar trebui să posede deja procesorul – obiectul cererii! Un proces devine în mod implicit candidat la utilizarea procesorului
din momentul când trece în starea eligibil. Alocatorul constă din două proceduri: planificatorul şi dispecerul. ◄
Exemplul 7.2. Memoria principală. Alocarea memoriei principale pune în funcţie două mecanisme distincte:
a) Alocarea explicită: este mecanismul de obţinere a unei zone de memorie fie de către un program în curs de execuţie, fie de către
sistemul de operare înaintea încărcării unui program nou.
b) Alocarea implicită: pentru acest mod de alocare cererea este emisă în momentul executării unei instrucţiuni, când adresa emisă
de procesor este adresa unui amplasament nealocat procesorului. Acest mecanism stă la baza realizării memoriei virtuale. ◄
Exemplul 7.3. Memoria secundară. Memoria secundară este alocată prin blocuri banalizate de lungime fixă. Alocarea şi eliberarea poate fi
explicită sau implicită (de exemplu, extinderea unui fişier provoacă emiterea unei cereri pentru un bloc suplimentar). ◄
Exemplul 7.4. Linii de comunicaţie. Dacă mai multe procese partajează serviciile unui dispozitiv de intrare-ieşire comun (o imprimantă sau o linie
de comunicaţie, de exemplu), cererile sunt transmise sub formă de mesaje unui proces, numit server, care administrează acest
dispozitiv. Fiecare mesaj conţine informaţiile necesare execuţiei transferului cerut. Mesajele sunt administrate cu ajutorul unui fir de
aşteptare cu sau fără priorităţi. ◄

7.1.2. Probleme în alocarea resurselor


Obiectivul unui sistem de alocare a resurselor este să satisfacă cererile într-un mod echitabil, asigurând în acelaşi
timp şi performanţe acceptabile. Dacă toate procesele au aceeaşi prioritate, o alocare este echitabilă, atunci când este
asigurată o tratare asemănătoare fiecărui proces, de exemplu, aşteptarea medie este identică. Dacă între procese există
priorităţi, este dificil să se definească noţiunea de echitate în caz general, dar ea poate fi exprimată prin faptul, că
calitatea serviciului (măsurată, de exemplu, prin valoarea inversă a timpului mediu de aşteptare sau printr-o altă
expresie semnificativă) este funcţie crescătoare de prioritate, două procese de aceeaşi prioritate beneficiind de aceeaşi
tratare. A fost stabilit, că unii algoritmi de alocare conţin riscul de a face un proces să aştepte la infinit: acest fenomen,
numit privaţiune, este contrar principiului de echitate şi trebuie evitat.
Dacă resursele sunt utilizate de mai multe procese pot avea loc două fenomene nedorite:
 Blocarea, deja întâlnită în capitolul 4 în cazul imbricării secţiunilor critice, este stoparea a mai multor
procese pentru un interval de timp nedefinit, fiecare dintre procese fiind în aşteptarea eliberării resurselor
alocate altor procese.

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.2 din 11


 Căderea – este situaţia în care o cerere excesivă a unui oarecare tip de resurse conduce la degradarea
performanţelor sistemului (căderea unei reţele de transport sau a unei centrale telefonice). Situaţii
analogice sunt constatate şi în sistemele informatice.
Vom presupune, că alocarea se va face în mod centralizat, adică algoritmii utilizaţi ştiu situaţia de alocare a mulţimii
resurselor la orice moment.
Instrumentul principal, utilizat pentru studiul cantitativ a alocării resurselor sunt modelele firelor de aşteptare.
7.1.3. Exemple de sisteme cu fire de aşteptare
Un sistem informatic este constituit din N instalaţii identice, fiecare fiind descrisă de modelul M/M/1, cu parametrii
λ şi μ (fig. 7.1a). Vom examina influenţa asupra timpului de răspuns al acestui sistem a utilizării comune a resurselor,
caracteristicile totale de tratare fiind constante.

Fig.7.1. Modelul unui sistem de servire în masă


În sistemul din figura 7.1b, clienţii celor N fire de aşteptare sunt grupaţi într-un fir unic. Intensitatea sosirii, fiind
superpoziţia unor intensităţi poissoniene, va rămâne de tip Poisson cu parametrul Nλ. Sistemul este M/M/N cu
parametrii Nλ şi μ.
În sistemul din figura 7.1c, N servere paralele sunt înlocuite printr-un server unic, de N ori mai puternic. Puterea
totală de tratare rămâne în acest caz constantă, dar timpul mediu de servire a unei cereri se împarte la N: avem un sistem
de tipul M/M/1 cu parametrii Nλ şi Nμ.
Timpul mediu de răspuns (timpul mediu de aflare în sistem a unei cereri) pentru fiecare caz va fi:
tma = 1/[μ(1-ρ)]
tmb = 1/μ+C(N,Nρ)/[Nμ(1-ρ)]
tmc = 1/[Nμ(1-ρ)]
Aici avem tmc = tma/N şi putem demonstra, calculând C(N, Nρ), că tma > tmb > tmc. De exemplu, pentru N=2, μ=1 şi
ρ=0,8 vom avea tma = 5, tmb = 2,8, tmc = 2,5.
Acest rezultat ilustrează câştigul adus de concentrarea resurselor. Intuitiv, fenomenul poate fi explicat astfel: în
cazul a un server poate fi neutilizat, atunci când avem cereri în alte fire de aşteptare, serverele acestora fiind ocupate.
Această situaţie nu se poate produce în cazul b, însă dacă există servere neutilizate, posibilitatea lor de tratare nu este
folosită, deşi ele ar putea servi la accelerarea tratării, care are loc pe serverele ocupate. Sistemul c realizează folosirea
deplină a resurselor.

7.2. Modele pentru alocarea unei resurse unice


Vom trata două cazuri: alocarea procesorului şi gestiunea schimburilor cu o memorie secundară paginată.
7.2.1. Alocarea procesorului
7.2.1.1. Introducere
Algoritmii de alocare a procesorului pot fi clasificaţi în funcţie de mai multe caracteristici.
1) Algoritmi cu sau fără retragere
Retragerea presupune alocarea procesorului unui alt proces înainte ca procesul curent să-şi termine execuţia. Ea
permite să se ia în consideraţie:
 prioritatea cererilor nou sosite,
 timpul deja consumat de către procesul ales.
2) Noţiuni de prioritate şi modul de determinare a priorităţii

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.3 din 11


Prioritatea unui proces este o informaţie, care permite clasificarea procesului în cadrul altor procese, dacă trebuie
făcută o alegere (intrarea sau ieşirea dintr-un fir de aşteptare, de exemplu). Prioritatea poate fi definită prin mai multe
moduri:
 prioritate constantă: definită apriori, funcţie de timpul de servire cerut.
 prioritate variabilă în timp: funcţie de timpul de aşteptare scurs, de serviciul deja acordat, etc.
Variabila principală, care va prezenta interes este timpul mediu de răspuns. Cererea este caracterizată de repartiţia
intervalelor de sosire şi de timpul de servire. Aceşti parametri nu sunt întotdeauna bine cunoscuţi şi este important să se
evidenţieze influenţa variaţiei lor.
Din practică este cunoscut, că un utilizator suportă cu atât mai greu aşteptarea servirii unei cereri cu cât lucrul trimis
de el este de durată mai mică; aceasta este adevărat atât pentru lucrul interactiv, cât şi pentru cel de fond. Din aceste
considerente metodele de alocare a procesorului au drept scop reducerea timpului mediu de aşteptare a lucrărilor celor
mai scurte. Ele diferă conform modului de estimare a duratei lucrărilor şi în dependenţă de privilegiile acordate
lucrărilor funcţie de această durată estimată.
7.2.1.2. Prim sosit, prim servit
Disciplina “Prim sosit, prim servit” (în engleză, “First In, First Out”, sau FIFO) utilizează un fir unic, fără prioritate
şi fără retragere. Procesul ales este executat până la terminarea sa, iar cel care va urma este procesul din topul firului de
aşteptare. Un proces nou intră în coada firului.
Pentru modelul M/G/1 timpul mediu de răspuns este dat de formula Pollaczek-Khintchine:
tm = tms[1+ρ(1+C2ts)/2(1- ρ)], C2ts= Var(ts)/(tms)2 (7.1)
Figura 7.2 arată variaţia timpului mediu de răspuns funcţie de încărcarea sistemului şi de variaţia timpului de
servire. Putem remarca:
 creşterea rapidă a timpului mediu de răspuns, atunci când sistemul se apropie de saturaţie: un sistem este cu atât
mai sensibil la o variaţie a şarjei, cu cât este mai ridicat gradul lui de încărcare,
 influenţa dispersiei timpilor de servire asupra timpilor de răspuns.

tm

Var(ts)

1 ρ=λts
Fig.7.2. Timpul mediu de răspuns pentru disciplina FIFO

Aceste două efecte pot fi întâlnite în toate disciplinele de alocare.


7.2.1.3. Cererea cea mai scurtă servită prima
În acest caz cererile sunt ordonate în cadrul firului de aşteptare conform timpului lor de servire, presupus apriori
cunoscut, cererile cu durata de servire cea mai scurtă aflându-se în top.
Timpul mediu de aşteptare tm funcţie de timpul de servire ts este dat de formula (7.1):

t m (1  C t )
2 2 ts
tm(ts) = s s
cu  (t s )    tdB(t ) (7.2)
2[1   (t s )] 2 0

Formulele de aproximare sunt


 pentru valori mici ale ts, unde ρ(ts) poate fi neglijat:

t m (1  C t )
2 2

tm(ts) ≈ s s
(7.3)
2
 pentru valori mari ale ts, unde ρ(ts) este aproape de λtms, fie ρ:

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.4 din 11


t m (1  C t )
2 2

tm(ts) ≈ s s
(7.4)
2(1   ) 2

Figura 7.3 prezintă dependenţa timpului mediu de răspuns de timpul de servire cerut pentru cazurile FIFO şi Cererea
cea mai Scurtă Servită Prima (CSSP). Pentru disciplina de servire FIFO acest timp depinde doar de gradul încărcării
sistemului ρ, considerat de noi constant. Figura pune în evidenţă tratarea privilegiată a lucrărilor scurte.

tm
CSSP

FIFO

ts
Fig.7.3. Dependenţa timpului mediu de răspuns de timpul de servire
în cazul disciplinelor FIFO şi CSSP
În plan practic disciplina CSSP are două dezavantaje: ea prezintă un risc de privaţiune pentru cererile lungi, dacă
rata de sosire a cererilor scurte este ridicată şi necesită cunoaşterea apriori exactă a timpului de servire.
O modalitate de evitare a riscului de privaţiune este de a acorda cererilor priorităţi care vor creşte odată cu creşterea
timpului lor de aflare în firul de aşteptare, prioritatea iniţială fiind determinată de timpul de servire estimat. De exemplu,
în cadrul disciplinei HRN (Highest Response Ratio Next) prioritatea unei cereri la un moment de timp τ este dată de
relaţia
p(t) = [t(τ)+ts)]/ts (7.5)
unde t(τ) este timpul de aflare a unei cereri în firul de aşteptare (fie t(τ)= τ – τs, aici τs fiind momentul sosirii cererii), iar
ts timpul de servire estimat. Pentru două cereri cu acelaşi timp de aşteptare, prioritate are cererea mai scurtă. În practică,
priorităţile sunt recalculate în momente discrete de timp şi firul de aşteptare este reordonat la necesitate.
Ideea directoare a acestui algoritm este de a partaja echitabil procesorul, încercând să se menţină o valoare constantă
a raportului k = t/ts, unde t este timpul total de aflare a unei cereri în sistem. Dacă aceasta se respectă, totul se va petrece
pentru fiecare lucrare ca şi cum ea ar dispune de un procesor de k ori mai slab (mai puţin rapid) decât procesorul real.
Disciplina HRN privilegiază lucrările scurte, însă penalizarea lucrărilor de lungă durată este redusă de efectul priorităţii
variabile.
Algoritmii descrişi mai jos vizează la fel partajarea echitabilă a procesorului, dar nu necesită cunoaşterea apriori a
timpului de servire.
7.2.1.4. Caruselul şi modele derivate
În modelul caruselului (“round robin”) procesorul este alocat succesiv proceselor eligibile pentru o perioadă
constantă de timp τ, numită cuantă. Dacă un proces se termină sau se blochează înainte de sfârşitul cuantei, procesorul
este imediat alocat procesului următor. Această disciplină de servire este implementată ordonând procesele într-un fir de
aşteptare circular; un pointer de activare, care avansează cu o poziţie la fiecare realocare a procesorului, desemnează
procesul ales (fig.7.4).

ieşire
intrare

f_eligibil proc_ales

Fig.7.4. Alocarea procesorului: metoda caruselului


Caruselul este un exemplu de disciplină cu retragere. Ea poate fi considerată o aproximare a disciplinei “cel mai
scurt primul” pentru cazul când durata execuţiei lucrărilor nu este cunoscută anticipat. Este utilizată în sistemele
interactive; valoarea cuantei este aleasă astfel ca majoritatea cererilor interactive să poată fi executate în timpul unei
cuante. Evident, valoarea cuantei trebuie să fie net mai mare decât durata comutării procesorului.
Analiza modelului caruselului nu este defel simplă. Doar cazul limită (τ →0, iar timpul de comutare a procesorului
neglijat) este mai simplu. În acest model, zis procesor partajat, totul are loc ca şi cum fiecare proces dispune imediat

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.5 din 11


(fără aşteptare) de un procesor viteza de procesare a căruia este cea a procesorului real, divizată la numărul curent al
proceselor servite. Se poate arăta că timpul de aşteptare în modelul procesorului partajat este
ta(ts) = ρts/(1-ρ),
iar timpul de răspuns este
t(ts) = ts/(1-ρ).
Modelul procesorului partajat realizează, deci, o alocare echitabilă, în care timpul de aflare a unui proces în sistem
este proporţional cu durata serviciului cerut.
O îmbunătăţire a modelului caruselului, chemată să reducă timpul de servire a lucrărilor de scurtă durată, este
caruselul multinivel. Acest model conţine n fire de aşteptare F0, F1,..., Fn-1. Fiecărui fir Fi îi este asociată o cuantă
proprie τ i, valoarea căreia creşte odată cu i. O lucrare din Fi este servită doar dacă firele de număr inferior lui i sunt
vide. Dacă o lucrare din Fi şi-a epuizat cuanta sa fără a se termina, ea intră în firul Fi+1; lucrările din Fn-1 se întorc tot
aici. Lucrările noi intră în F0 (fig. 7.5).

intrare procesor ieşire

Fig. 7.5. Carusel cu mai multe niveluri


Această disciplină sporeşte privilegiile acordate lucrărilor de scurtă durată în raport cu CSSP; ca şi ultima, ea
conţine un risc de privaţiune pentru lucrările de lungă durată. La fel poate fi definit un model limită pentru τ →0, iar
n→∞, pentru care poate fi calculată valoarea timpului mediu de aşteptare. Figura 7.6 ilustrează caracteristicile
disciplinelor de servire examinate [16].

t(ts) t(ts)

CM PP CM
PP
CSSP

CSSP

ts ts
FIFO – prim sosit prim servit PP – procesor partajat
CSSP – cerere scurtă servită prima CM – carusel multinivel
Fig. 7.6. Compararea disciplinelor de alocare a procesorului
Putem aprecia, în conformitate cu gradul de încărcare a procesorului, avantajele acordate de diferite discipline de
servire lucrărilor de scurtă durată.
7.2.2. Disc de paginare
Vom cerceta acum metodele de gestiune a schimburilor între memoria principală şi un disc cu dispozitive de citire-
scriere (DCS, capuri) fixe. Astfel de discuri sunt organizate pe piste şi sectoare şi are câte un DCS per pistă.
Schimburile sunt comandate de un server care primeşte cererile de transfer; fiecare cerere presupune transferul unui
sector cu indicaţia direcţiei de transfer, o adresă în memorie şi una pe disc (pista şi sectorul) [17].
Vom cerceta două discipline de tratare a cererilor:

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.6 din 11


1) Fir de aşteptare unic. Cererile de transfer sunt ordonate într-un fir unic şi tratate în ordinea sosirii lor,
2) Un fir per sector. Un fir distinct este administrat pentru fiecare sector; se speră să poată fi redus timpul mediu de
aşteptare, eliminând timpul mort.
Aceste două discipline sunt prezentate schematic în figura 7.7. Un disc administrat conform schemei b este numit
disc de paginare, deoarece acest mod de funcţionare este adesea utilizat pentru gestiunea memoriilor paginate.
Sectorul i

Cereri

(toate sectoarele)
Cerere a
sectorului i

(a) (b) Cu sectoare fixe şi


DCS mobil

Fig. 7.7. Gestiunea transferelor memorie-disc


Vom compara aceste două discipline, în ipoteza unor cereri poissoniene la sosire şi repartizate uniform între
sectoare. Notăm
λ fluxul mediu de sosire a cererilor,
R durata unei rotaţii a discului,
N numărul de sectoare pe pistă,
Durata de derulare a unui sector sub DCS este, deci, de R/N.
1) Fir unic de cereri. Discul poate fi considerat un server M/G/1, durata servirii ia N valori echiprobabile din [R/N,
(N-1)R/N]. Timpul mediu de servire tms este în acest caz:
1 N iR R( N  1)
tms =  = , (7.6)
N Ni 1 2N
iar coeficientul de variaţie
2  2N  1 
2
1  iR 
1 N
C t2 =    1, sau 1+ C t = 
 
2
(7.7)
t m i 1 N  N 
2
s
s
3  N 1  s

Lungimea medie a unui fir de aşteptare, fiind inclusă şi cererea în curs de servire, este obţinută din formula
Pollaczeck-Khinchine:
 t (1  Ct2s ) 
nm = λtms 1  ms  (7.8)
 2(1  t ms ) 
şi timpul mediu de servire este:
n R( N  1)  (2 N  1)R 
tm = m = 1   (7.9)
 2 N  3[2 N  R( N  1)] 

2) Disc de paginare. Fiecare fir poate fi tratat independent, utilizând modelul lui Skinner (server cu restabilire), cu
λi = λ/N ts = R/N, tr = (N-1)R/N,
T=R S = t s + tr = R
Pentru un fir de aşteptare vid, ca şi pentru începerea tratării următoarei cereri, este necesar să se aştepte o rotaţie
completă. Lungimea medie a unui fir de sector este:
2 R 2 / N 2 R  1 1 
nmi =     (7.10)
2(1  R / N ) N  N 2 
şi timpul mediu de servire:
n R 2 / N N 2
tm = mi = R . (7.11)
i 2(1  R / N ) 2N

În figura 7.8 sunt comparate cele două modele de administrare a discului.

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.7 din 11


W

a) fir unic b) disc de paginare

2N/R(N+1) N/R λ
Fig. 7.8. Compararea modelelor de administrare a discului
Compararea pragurilor de saturare pentru cele două discipline permite calcularea câştigului obţinut pentru discul de
paginare. Pragul de saturare este definit prin ρ = 1. Vom obţine în acest caz: pentru discul cu fir unic: λR(N+1)/2N = 1,
iar pentru discul de paginare: λR/N = 1.
Raportul pragurilor critice pentru λ este, deci, (N+1)/2; acest raport este o măsură a câştigului obţinut prin
organizarea firelor pentru sectoare.

7.3. Tratarea blocărilor


7.3.1. Enunţul problemei
Un exemplu de blocare reciprocă (impas) a fost prezentat în capitolul 4, când două secţiuni critice, corespunzătoare
la două resurse distincte, sunt imbricate eronat, existând un risc de blocare pentru o perioadă de timp nedefinită.
O atare situaţie poate fi generalizată pentru un număr oarecare de procese şi resurse, dacă sunt îndeplinite
următoarele condiţii:
1) resursele sunt utilizate în excludere mutuală,
2) fiecare proces trebuie să utilizeze simultan mai multe resurse, şi acaparează fiecare resursă pe măsura
necesităţilor sale, fără a le elibera pe cele pe care le posedă deja,
3) cererile de resurse sunt blocante şi resursele nu pot fi retrase,
4) există o mulţime de procese {p0,..., pn}, astfel încât p0 cere o resursă ocupată de p1, p1 cere o resursă ocupată de
p2, ..., pn cere o resursă ocupată de p0.
Exemplul 7.5. Două procese p1 şi p2 utilizează două tipuri de resurse, r1 şi r2. Sistemul conţine 7 unităţi de tipul r1 şi 6 r2. Cantităţile respective de
r1 şi r2 necesare pentru execuţia proceselor sunt 6 şi 3 pentru p1, 4 şi 5 pentru p2. Presupunem că sistemul se află în starea următoare:
r1 r2
alocat lui p1 4 2
alocat lui p2 2 3
disponibil 1 1
Oricare ar fi ordinea de execuţie a proceselor, nici unul nu va putea obţine totalitatea resurselor necesare, dacă nici o resursă nu este
eliberată sau retrasă. Pornind de la această stare a sistemului, impasul este inevitabil. ◄

Problema impasului poate fi abordată în două moduri:


 prin prevenire: algoritmul de alocare a resurselor garantează, că o situaţie de blocare nu se poate produce,
 prin detectare şi tratare: nu sunt luate măsuri preventive; blocarea este detectată doar dacă are loc, iar tratarea şi
“însănătoşirea” constă în aducerea sistemului într-o stare, în care procesele sunt deblocate, în caz general, cu o
pierdere de informaţii.
7.3.2. Algoritmi de prevenire
7.3.2.1. Algoritmi de profilaxie
Atunci când nu se cunoaşte anticipat nimic despre cererile proceselor, metodele de prevenire constau în înlăturarea
uneia din condiţiile 1) – 4) de mai sus.
Metoda alocării globale vizează eliminarea condiţiei “2”: fiecare proces cere toate resursele de care are nevoie în
bloc; el poate elibera o resursă dacă nu mai are nevoie de ea. Metoda dată conduce la imobilizarea unor resurse în mod
neproductiv, şi aduce adesea în practică la suprimarea oricărui paralelism în execuţie; totuşi această metodă nu trebuie
refuzată din start.

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.8 din 11


Metoda claselor ordonate vizează eliminarea situaţiei unei aşteptări circulare (condiţia “4”). Resursele sunt divizate
în clase C1, C2,..., Cm. Un proces poate primi o resursă din clasa Ci numai dacă el a primit deja toate resursele necesare
în clasele Cj, j<i. Toate procesele cer resursele de care au nevoie în aceeaşi ordine, cea a claselor.
Presupunem, că avem o aşteptare circulară, adică există procese p0, p1,..., pn-1 astfel încât pi aşteaptă o resursă ri
alocată procesului pi1 (simbolul  desemnează suma modulo n). Fie c(ri) numărul clasei resursei ri. Deoarece procesul
pi1 aşteaptă resursa ri1 şi posedă resursa ri, avem c(ri)<c(ri1), de unde, datorită tranzitivităţii, obţinem c(r0)<c(r0).
Aşteptarea circulară este astfel imposibilă şi blocarea evitată.
7.3.2.2. Algoritmul bancherului
Algoritmul de prevenire poate fi îmbunătăţit dacă există informaţii anticipate despre cererile de resurse. Dacă fiecare
proces prezintă în avans o declaraţie de intenţii (anunţ), adică valoarea unei borne superioare ale cererilor sale pentru
numărul de resurse de fiecare tip, algoritmul bancherului permite evitarea blocării reevaluând riscul acestora la fiecare
alocare. Acest algoritm se bazează pe noţiunea de stare fiabilă: o stare de alocare este numită fiabilă dacă, pornind de
la această stare este posibil să se asigure funcţionarea sistemului fără blocări în ipoteza cea mai pesimistă, cea în care
fiecare proces cere efectiv cantitatea maximă presupusă de fiecare dintre resurse. Algoritmul bancherului va aloca o
resursă doar dacă această alocare păstrează starea fiabilă a sistemului.
Considerăm un sistem care conţine n procese şi m clase de resurse. Starea sa este reprezentată de următoarele
structuri de date:
Res, Disp: array[0..m-1] of integer
Anunt, Aloc: array[0..n-1, 0..m-1] of integer
unde
Res[j]: este numărul total de resurse din clasa j,
Anunt[i, j]: numărul maxim de resurse din clasa j necesare la un moment de timp procesului i,
Aloc[i, j]: numărul maxim de resurse din clasa j alocate la un moment de timp procesului i,
Disp[j]: numărul de resurse din clasa j disponibile la un moment de timp dat.
Avem, prin definiţie, pentru un moment oarecare de timp:
n 1
Disp[j]=Res[j]-  Aloc[i, j ] pentru j=0, 1,..., m-1.
i 0

Notăm prin A[i,*] vectorul format din linia i a matricei A. Dacă U şi V sunt doi vectori de aceeaşi lungime k, vom
conveni să scriem:
UV dacă şi numai dacă U[i]  V[i] pentru i=0, 1,..., k-1
U<V dacă şi numai dacă U  V şi UV.
Specificaţiile sistemului impun următoarele restricţii:
0  Aloc[i,*]  Anunt[i,*]  Res, pentru i=0,...,n-1
Aloc[i,*]  Res
Disp  0 vectorul nul.
Aceste relaţii exprimă, pentru fiecare clasă de resurse, că anunţul nu poate depăşi numărul resurselor disponibile, că
cantitatea resurselor alocate unui proces nu poate depăşi anunţul său şi, în sfârşit, că sistemul nu poate aloca mai multe
resurse decât există în total. O stare a sistemului se numeşte realizabilă, dacă este conformă acestor specificaţii.
Fie E0 o stare realizabilă a sistemului. Încercăm să găsim un proces pi, care, dacă el era executat singur pornind de la
starea E0, utilizând totalitatea resurselor specificate de anunţul său, procesul ar putea ajunge până la sfârşit. Un
asemenea proces trebuie să verifice , în starea E0:
Anunt[i, *]-Aloc[i, *]  Disp.
Presupunem că a fost găsit un astfel de proces, fie pi0, şi că el este executat până la sfârşit. El eliberează atunci toate
resursele sale şi sistemul trece într-o stare realizabilă E1, definită prin
DispE1=DispE0+Aloc[i0,*].
Operaţia poate fi repetată, căutând un proces nou pi1 şi tot aşa cât este posibil. Suita de procese, obţinută în acest
mod se numeşte fiabilă. O stare a sistemului se numeşte fiabilă, dacă, pornind din această stare, putem construi o suită
fiabilă completă (adică, care conţine toate procesele sistemului).
Urmând această definiţie, un sistem într-o stare fiabilă nu este în blocare, deoarece poate fi definită o ordonare a
proceselor, care permite execuţia tuturor proceselor. Putem demonstra afirmaţia reciprocă (exerciţiu): dacă un proces nu
este în blocare, el se află într-o stare fiabilă. Algoritmul bancherului se bazează pe această proprietate; el este executat la
fiecare cerere de resursă de un proces. Fie Cerere[i, j] numărul de resurse cerute din clasa j în starea curentă a
sistemului, de către procesul i.
if Aloc[i,j]+Cerere[i,j]>Anunt[i,j] then
<eroare> -- cererea totală > anunţul
else
if Cerere[i,j]>Disp[j] then

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.9 din 11


<pune procesul p în aşteptare>
else -- simularea alocării
<definire stare nouă prin:
Aloc[i,j]:=Aloc[i,j]+Cerere[i,j]
Disp[j]:=Disp[j]-Cerere[i,j]>
endif;
if starea nouă este fiabilă then
<efectuare alocare>
else
<restaurare stare primitivă>
<pune procesul p în aşteptare>
endif
endif
Locul central al acestui algoritm îl constituie testarea fiabilităţii unei stări, care se reduce la încercarea construirii
unei suite fiabile. Este vorba de un algoritm combinator, care presupune iniţial o complexitate de ordinul n!, însă
complexitatea poate fi redusă la n2 datorită următoarei proprietăţi, care elimină necesitatea întoarcerii înapoi în caz de
eşec: dintr-o stare fiabilă orice suită fiabilă poate fi prelungită până la o suită fiabilă completă.
Cu alte cuvinte, dacă tentativa de extindere a unei suite fiabile parţiale eşuează, starea sistemului nu este fiabilă şi
este inutil să se încerce construirea unei alte suite.
Ţinând cont de această proprietate, testarea fiabilităţii este realizată cu ajutorul algoritmului de mai jos:
Dispcurente : array[0..m-1] of integer;
Rest : set of procese;
Dispcurente:=Disponibil;
Rest:={toate procesele};
posibil:=true;
while posibil do
căutare p din Rest astfel ca
Anunt[i,*]-Aloc[i,*] Dispcurente;
if găsit then -- simularea execuţiei procesului p
Dispcurente:=Dispcurente+Aloc[i,*];
Rest:=Rest-{p}
else
posibil:=false
endif
endwhile;
stare fiabilă:=(Rest=<vid>)
Acest algoritm poate fi simplificat, dacă există o singură clasă de resurse.
7.3.3. Algoritmi de detectare şi tratare
Pentru detectarea unei blocări putem utiliza testul de fiabilitate a unei stări, înlocuind pentru fiecare proces cererea
maximă Anunt[i,*]-Aloc[i,*] cu cererea efectivă la instanţa considerată. Dacă în aceste condiţii este imposibil să se
găsească o suită fiabilă completă, sistemul se află în blocare. Mai precis, procesele blocate sunt elementele mulţimii
Rest, la terminarea algoritmului.
Lecuirea blocării vizează reluarea execuţiei sistemului; aceasta poate fi făcut doar recuperând resursele deja alocate.
O metodă mai dură constă în distrugerea proceselor blocate, începând cu cele pentru care preţul distrugerii este cel mai
mic (conform unui criteriu definit), până la procesele pentru care execuţia poate fi reluată. Această metodă nu este fără
pericole, dacă procesele distruse au lăsat date într-o stare incoerentă. De asemenea este preferabil să se salveze periodic
starea proceselor, definind puncte de reluare, corespunzătoare unor stări semnificative. În caz de retragere forţată a
resurselor unui proces, acesta poate fi repus în starea corespunzătoare ultimului său punct de reluare.
Tratarea blocărilor prin distrugere sau întoarcerea la o stare anterioară prezintă un risc de privaţiune, dacă criteriul
de preţ ales conduce întotdeauna la desemnarea aceluiaşi proces. Pentru remediere au fost propuse diferite metode:
acordarea unor “privilegii” care ar proteja procesele protejate contra distrugerilor forţate sau factor de preţ crescător
odată cu creşterea numărului de retrageri.
Atunci când retragerea este autorizată şi dacă ea are loc fără pierdere de informaţii, poate fi utilizată o formă
particulară de detecţie şi lecuire, evitarea continuă. Această metodă este folosită pentru sistemele repartizate [18].

7.4. Exerciţii la capitolul 7


Exerciţiul 7.1. Un sistem informatic funcţionează conform schemei de mai jos.

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.10 din 11


Fiecare terminal este o sursă de cereri poissoniene pentru care timpul de servire are repartiţie exponenţială. Calculaţi:
 debitul la intrarea serverului,
 numărul de terminale, care aduce sistemul în starea de saturaţie, presupunând constante ceilalţi parametri.
Exerciţiul 7.2. Un sistem informatic funcţionează conform schemei de mai jos.

Cu aceleaşi ipoteze ca şi în exerciţiul precedent, calculaţi:


 debitele la intrarea celor două servere,
 numărul de terminale, care aduce sistemul în starea de saturaţie, presupunând constante ceilalţi parametri,
 relaţia care ar trebui să existe între parametrii sistemului pentru ca cele două servere să fie echilibrate (acelaşi
grad de încărcare).
Exerciţiul 7.3. Să se arate, că disciplina “Lucrarea cea mai scurtă prima” minimizează timpul mediu de răspuns pentru
o mulţime de lucrări. Indicaţii: Se va stabili timpul total de execuţie pentru o mulţime de lucrări, apoi se vor permuta
două lucrări.
Exerciţiul 7.4. Două procese ciclice p şi q folosesc două resurse comune A şi B. Fiecare proces traversează o fază în
care are nevoie de ambele resurse simultan, cerându-le una după alta, conform necesităţilor (deoarece alt proces poate
avea nevoie de o singură resursă) şi eliberează ambele resurse la sfârşitul fazei. Dacă ordinea de achiziţie a resurselor
este diferită pentru cele două procese, este oare posibil programarea lor pentru evitarea blocării fără retragere sau
rezervare globală?
Exerciţiul 7.5. Considerăm un sistem de prelucrare pe loturi monoprogram, cu tampoane de intrare-ieşire în memorie,
conform schemei din exerciţiul 3.13. Zonele de memorie, care servesc drept tampoane de intrare şi de ieşire sunt alocate
şi eliberate în mod dinamic, la necesitate, pornind de la o zonă comună de lungime constantă.
Identificaţi riscul unei blocări şi propuneţi un algoritm pentru a o evita.
Exerciţiul 7.6. Trei procese partajează trei resurse nebanalizate cu acces exclusiv şi fără retragere. Utilizând procedurile
alocare(resursă) şi eliberare(resursă), elaboraţi algoritmul programelor pentru aceste procese:
 cu risc de blocare globală a celor trei procese,
 cu risc de privaţiune pentru doar unul din procese, fără blocare.
Fiecare proces nu va utiliza mai mult de două resurse.
Exerciţiul 7.7. Demonstraţi, că dacă un sistem nu se află în blocare, este posibil să se construiască o suită completă de
procese.
Exerciţiul 7.8. Demonstraţi, că dacă un sistem se află într-o stare fiabilă, este posibil să se prelungească orice suită
fiabilă de procese într-o suită fiabilă completă.
Exerciţiul 7.9. Să se elaboreze un program detaliat pentru alocarea resurselor conform algoritmului bancherului,
introducând structurile de date necesare.
Exerciţiul 7.10. Arătaţi că, în caz general, complexitatea algoritmului bancherului este de ordinul n2m, unde n este
numărul total al proceselor şi m este numărul total de clase de resurse.
Exerciţiul 7.11. Completaţi algoritmul bancherului presupunând, că procesele pot fi create şi distruse dinamic şi, că un
proces poate modifica anunţul său. Precizaţi, care sunt operaţiile care trebuie să fie supuse unei autorizări a sistemului
de alocare a resurselor.

17.10.11 16:14 E:\Tato\DiskD\PC vechi\d\Catedra\Besliu1\Sisteme_de_operare\Ciclu de prlegeri la SO\final\7.doc p.11 din 11

S-ar putea să vă placă și