Sunteți pe pagina 1din 97

Sisteme de Operare Linux L

CAP. I INTRODUCERE .......................................................... 2


1.1.LINUX scurt istoric ...................................................... 2
1.2.Filozofia Unix&Linux ..................................................... 2
CAP. II SISTEMUL DE FIIERE ........................................ 10
2.1.STRUCTURA DE FIIERE.......................................... 10
2.2.COMENZI SPECIFICE LUCRULUI CU FIIERE ..... 12
CAP. III INTERPRETOARE DE COMENZI ...................... 17
3.1.Introducere ..................................................................... 17
3.2.Faciliti ale interpretoarelor de comenzi ...................... 17
3.3.Sintaxa interpretorului de comenzi. .............................. 21
CAP. IV MAKE...................................................................... 28
4.1.Introducere ..................................................................... 28
4.2.Macro ............................................................................. 30
4.3.Reguli de adugare a sufixelor ...................................... 33
CAP. V Lucrul cu fiiere ........................................................ 39
5.1.Sistemul de fiiere Linux considerente generale........ 39
5.2.Accesul la fiiere............................................................ 40
5.3.Gestionarea directoarelor............................................... 45
CAP. VI PROCESE ................................................................ 54
6.1.Identificatoare de proces PID ..................................... 54
6.2.Crearea proceselor utiliznd fork .................................. 55
6.3.Apelul sistem exec ......................................................... 58
6.4.Apelurile sistem wait i exit .......................................... 60
CAP. VII Comunicarea ntre procese ..................................... 66
7.1.Semnale .......................................................................... 66
7.2.Pipes ............................................................................... 72
CAP. VIII FIRE DE EXECUIE ........................................... 80
CAP. IX Probleme propuse .................................................... 93

1
Sisteme de Operare Linux L

CAP. I INTRODUCERE

1.1. LINUX scurt istoric

Ca i dat de apariie Linux este un sistem de operare


relativ recent dar care are ca i surs de inspiraie sistemul
UNIX. Acesta a fost iniial dezvoltat n anii 70 de
laboratoarele Bell din cadrul corporaiei AT&T, fiind proiectat
ca sistem de operare pentru calculatoarele PDP de la Digital
Equipament. n timp el a devenit popular datorit
caracteristicilor sale sistem multiutilizator i multitasking,
acoperind o gam variat de hardware de la staii de lucru
pn la servere cu mai multe procesoare sau supercalculatoare.
Pornind de la sistemul UNIX original s-au dezvoltat mai
multe clone ale acestuia. Unul dintre cele mai cunoscute este
Solaris care este dezvoltat de ctre Sun i are ca int sistemele
bazate pe procesoare Sparc i Intel. Alte implementri bazate
pe UNIX sunt BSD, SCO i Linux. Datorit acestei
multitudini de sisteme de operare bazate pe UNIX au aprut
probleme legate de compatibiliate, acestea fiind reglementate
prin impunerea unui standard POSIX, acesta a fost dezvoltat i
meninut de IEEE.
Linux este bazat pe un kernel de tip UNIX, prima
versiune a acestuia fiind realizat de Linus Torvalds la
Universitatea din Helsinki fiind dezvoltat n continuare cu
ajutorul a diveri programatori prin Internet. Sursa de
inspiraie a fost Minix un sistem de tip UNIX dezvoltat de
Andy Tanembaum.

1.2. Filozofia Unix&Linux


UNIX i are rdcinile ntr-un sistem care iniial a fost
dezvoltat s fie un sistem de mici dimensiuni si flexibil. Dei
ulterior UNIX s-a extins i a devenit un sistem monolitic i cu
aplicaii de mari dimensiuni totui filozofia iniial a fost
pstrat. Caracteristicile de baz ale acestei filozofii ar fi:
Simplitate sistemele UNIX originale erau de mici
dimensiuni i programatorii ncercau sa profite la maxim de
toate resursele implementnd comenzi de mici dimensiuni,
care ncercau s fac un singur lucru dar bine.

2
Sisteme de Operare Linux L

Conectivitate pentru a permite realizarea de sarcini


complexe utiliznd comenzi era necesar ca aceste comenzi s
poat fi utilizate ca intrare/ieire pentru comenzi.
Flexibilitate multe programe vor fi utilizate prin
conectarea prin pipe-uri cu celelalte, deci nu se poate ti n ce
context vor fi utilizate aplicaiile scrise, astfel c trebuie
evitat impunerea de limitri arbitrare.
Standardizarea formatului de fiiere majoritatea
aplicaiilor Unix&Linux utilizeaz fiiere n format ASCII.
Acest format este avantajos pentru c permite utilizarea
oricrui program prelucrarea oricrui fiier, reversul ar fi c un
program poate utiliza informaiile dintr-un fiier numai dac
cunoate formatul respectivului fiier.

1.3. Distribuii Linux


Sistemul de operare Linux este reprezentat de fapt de
kernelul su, oricine putnd s compileze sursele acestuia i
s-l instaleze mpreun cu diverse programe distribuite liber
obinnd astfel propria sa distribuie Linux.
Sistemul de operare Linux i datoreaz existena
eforturilor conjugate ale unui numr mare de persoane,
deoarece un sistem de operare pentru a putea fi utilizat la
dezvoltarea de aplicaii necesit pe lng nucleu (kernel) i
diverse aplicaii i servicii sistem.
Comunitatea Linux accept conceptul de software liber,
adic ne supus unor restricii, subiect al unei GNU General
Public License. Chiar dac obinerea acestui tip de software
implic anumite costuri acesta poate fi utilizat n mod liber i
de obicei este distribuit sub form de cod surs.
GPL (General Public License) ofer utilizatorului
urmtoarele drepturi:
Dreptul de a rula programul, n orice scop;
Dreptul de a studia cu funcioneaz programul i
de a-l modifica(accesul la surse este o precondiie);
Dreptul de a redistribui copii;
Dreptul de a mbunti programul i de a+l
distribui publicului larg(accesul la surse este o
precondiie).
Iniiatorul micrii Free Software Foundation a fost
Richard Stallman, autor al GNU Emacs. Stallman a fost un
pionier al conceptului de software liber i a nceput proiectul

3
Sisteme de Operare Linux L

GNU n ncercarea de a crea un sistem de operare i un mediu


de dezvoltare compatibile cu UNIX.
Ca i alte sisteme UNIX, Linux este un sistem de operare
multiutilizator i multitasking, adic permite conectarea mai
multor utilizatori i rularea mai multor programe n mod
simultan. Sistemul Linux a fost proiectat astfel nct s fie
compatibil cu standardul IEEE 1003.1/1990(numit i
POSIX.1). Acest standard definete funciile pe care aplicaiile
scrise n limbajul de programare C le pot utiliza pentru accesul
la serviciile sistemului de operare pentru activiti care ncep
de la deschiderea unui fiier i pn la stocarea memoriei.
Sistemul X Window sub Linux ofer un mecanism
standard de afiare a imaginilor bitmap independente de
dispozitiv. X include de asemenea i un sistem de ferestre ,
permind aplicaiilor s i afieze rezultatele n ferestre
separate. Chiar dac X pune la dispoziie mecanismul de
afiare n ferestre separate, aplicaiile sufer prin lipsa unui
aspect specific distinctiv. Acest aspect specific este dat de
interfeele grafice (Graphical User Interface GUI) cum ar fi
OSF/Motif i OPEN LOOK, care utilizeaz sistemul X
Window.
In ceea ce privete interfaa grafic, sistemul Linux
include mai multe sisteme de gestiune a ferestrelor (window
managers), care permit celorlalte programe X s i afieze
rezultatele n ferestre separate(GNOME, KDE, AfterStep,
Window Maker, etc) . Programele de gestiune a ferestrelor
adaug de obicei marginea i bara de titlu la fereastra unei
aplicaii X. Un alt aspect important legat de sistemul X
Window este acela c permite rularea aplicaiilor n reea.
Din toate posibilitile de utilizare, dezvoltarea de
programe este probabil cea mai potrivit. Instrumentele de
dezvoltare de programe, cum ar fi compilatoarele i
bibliotecile, sunt disponibile, acestea fiind oricum necesare
pentru reconstruirea nucleului sistemului.
Pentru o imagine despre suportul oferit de Linux pentru
dezvoltarea de programe se prezint o list a diverselor
faciliti care fac ca Linux s fie un mediu productiv pentru
dezvoltarea de programe :
Compilatorul C GNU gcc poate compila programele
ANSI-C.
Compilatorul C GNU g++ ofer suport pentru
facilitile C++ .

4
Sisteme de Operare Linux L

Depanatorul GNU gdb permite execuia pas cu pas a


unui program pentru determinarea problemelor aprute i
locurile unde programul eueaz.(Imaginea n memorie a unui
program a crui execuie eueaz este salvat ntr-un fiier
numit core ; gdb poate examina acest fiier).
Utilitarul gprof permite determinarea gradului n care
un anumit program utilizeaz timpul procesorului.
Utilitarele GNU make i imake permit compilarea
programelor de mari .
Sistem de control al versiunii RCS, CVS, SVN
memoreaz informaiile referitoare la versiuni i controleaz
accesul la fiierele surs, astfel nct doi programatori s nu
poat modifica inadvertent un anumit fiier surs.
Editorul GNU Emacs permite editare fiierele surs i
chiar lanseaz procesul de compilare pentru a construi un
program.
Limbajul de comenzi Perl utilizat pentru a scrie
programe care leag mai multe programe de dimensiuni reduse
cu comenzile UNIX, in scopul efecturii unei anumite
activiti.
Limbajul Tool Command Language i setul de
instrumente pentru X al acestuia (Tcl/Tk) permit proiectarea
rapid a aplicaiilor X.
Biblioteci dinamice partajate permit micorarea
considerabil a dimensiunilor programelor executabile,
deoarece toate bibliotecile necesare mai multor programe sunt
partajate, o copie a acestora fiind ncrcat n memoria
sistemului.
Fiiere antet i biblioteci POSIX.1 si POSIX.2, care
permit dezvoltarea de programe portabile.

O mare problem cnd vine vorba de Linux este numrul


foarte mare de distribuii, acestea sunt :
RedHat Linux, dezvoltat de RedHat Software, este una
dintre cele mai rspndite distribuii de Linux. Aceast
distribuie, ajuns la versiunea 8.0, confer o mare uurin n
instalare si configurare. n 2003, RedHat a ncetat s mai
dezvolte RedHat Linux, donnd distribuia proiectului Fedora
i punnd astfel bazele distribuiei Fedora Core. Red Hat
sponsorizeaz Fedora Core att financiar ct i cu personal
tehnic. Pe baza acesteia, Red Hat produce acum n regim
comercial sistemele de operare Red Hat Enterprise Linux.

5
Sisteme de Operare Linux L

Debian GNU/Linux, dezvoltat de Debian este una din


cele mai stabile distribuii de Linux ,fiind recomandat
utilizatorilor avansai de Linux. Debian GNU/Linux este o
distribuie gratuit de GNU i Linux. Aceast distribuie este
inut la zi datorit efortului voluntar depus de utilizatorii de
pe ntreg mapamondul. Distribuia este testat foarte mult
nainte de a fi lansat, pentru a asigura cel mai nalt grad de
stabilitate. Nu este foarte uor de configurat, aceast
distribuie fiind orientat n principal ctre utilizatorul
profesionist, dar are un foarte bun sistem de actualizare.
Knoppix este un sistem de operare cu nucleu Linux ce se
bazeaz pe Debian GNU/Linux. A fost creat de Thomas
Knopper. Ruleaz n totalitate de pe CD, aa c poate rula i
pe un calculator fr hard-disk.
Slackware Linux, dezvoltat de The Slackware Linux
Project, este la fel ca si Debian una din cele mai stabile
distribuii de Linux, oferind posibilitatea unei configurri
puternice a sistemului.
Mandriva Linux este o distribuie Linux cunoscut ca
fiind prietenoas i simplu de utilizat de ctre nceptori. A
fost creat n 1998 de compania francez Mandrakesoft sub
numele Mandrake Linux, cu scopul de a face GNU/Linux mai
uor de folosit. La acea vreme, Linux era foarte bine cunoscut
ca fiind un sistem de operare puternic i stabil, care ns cerea
cunotine tehnice foarte bogate i folosirea liniei de comand
n foarte multe situaii; Mandrakesoft a vzut acesta ca pe o
oportunitate de a integra cele mai bune interfee grafice i s
contribuie cu propriile utilitare de configurare.
n 2005 Mandrakesoft a achiziionat firma brazilian
Conectiva, productorul distribuiei Conectiva Linux. n
aprilie 2005 firma i-a schimbat numele n Mandriva
(Mandrake + Conectiva), iar distribuia a devenit cunoscut
sub numele de Mandriva Linux.
SuSE Linux, dezvoltat de S.u.S.E Linux este una din cele
mai bune distribuii de Linux. Folosindu-se de YaST(Yet
another System Tool) i Sax, dou unelte de configurare
deosebit de puternice, SuSE Linux este soluia ideal pentru
un utilizator mediu de Linux. Una din problemele SuSE-ului
este numrul mare de aplicaii comerciale.
Ubuntu Linux, o distribuie relativ recenta aprut ce se
bazeaz pe Debian pstrnd multe din avantajele acestuia,
inclusiv sistemul de actualizare a sistemului de operare, dar al
crui scop declarat este mbuntirea interaciunii cu
6
Sisteme de Operare Linux L

utilizatorul indiferent de gradul de implicare a acestuia n


fenomenul Linux.

1.4. Primul contact


Sistemul de operare Linux fiind un sistem multi-utilizator
prima aciune ntreprins de acesta este identificarea
utilizatorului cu care intr n contact printr-o invitaie:

login:
La aceasta trebuie s se rspund cu un nume de
utilizator cunoscut sistemului. n cazul n care pentru
utilizatorul respectiv a fost prevzut o parol procesul de
identificare va continua prin solicitarea acesteia:

password:

n cazul n care s-a fcut o greeal n introducerea


datelor de identificare sau dac numele utilizatorului nu este
recunoscut sistemul i refuz acestuia accesul.

Atenie! Linux este un sistem de operare case senzitive,


literele mari fiind tratate diferit fa de literele mici.

Dac procesul de autentificare s-a ncheiat cu succes


atunci pentru utilizatorul respectiv sistemul de operare va
executa un interpretor de comenzi numit shell. Programele
lansate n execuie de utilizator poart numele de procese.
Interpretorul de comenzi este responsabil cu afiarea unui
prompt pentru linia de comand, la aceast linie de comand
se pot introduce comenzi mpreun cu parametrii acestora iar
shell-ul le va executa. La ncheierea sesiunii de lucru ieirea
din sistem se va face prin execuia comenzii logout.
Sistemul de operare face deosebirea ntre cel puin dou
categorii de utilizatori:
root este utilizatorul implicit pentru administratorul
sistemului. El este cel care va putea utiliza toate uneltele de
administrare.
utilizatorul obinuit implicit nu are drepturi de
administrare.

7
Sisteme de Operare Linux L

Atenie! Nu este recomandabil lucrul ca i root, dect


dac este necesar. Pentru sarcinile de lucru obinuite este
recomandabil configurarea unui cont de utilizator obinuit.

O caracteristic important Linux este un sistem bine


documentat, de referin este n acest caz comanda man care
este un important punct de plecare n studierea sistemului de
operare Linux.

De studiat!

man man.

Una dintre opiunile deosebit de importante ale


comenzii man este -k aceasta realizeaz cutarea ntr-o baz de
date dup comenzi sau descrieri ale acestora care conin
cuvntul dat ca i argument.
De studiat!

man k print

O alternativ este comanda apropos.

REZUMAT

UNIX, sistemul de operare dezvoltat iniial n cadrul


laboratoarelor Bell (AT&T), reprezint baza de la care s-a
pornit n realizarea mai multor sisteme de operare cum ar fi
Solaris, BSD, SCO, Minix i n final Linux. Proprietile de baz
UNIX, multiutilizator i multitaking, fiind elementele pstrate n
toate clonele dezvoltate ulterior.

Caracteristicile ce au stat la baza UNIX(Linux) sunt: simplitate,


conectivitate, flexibilitate, standardizarea formatului de fiier.

Sistemul de operare Linux i datoreaz existena eforturilor


conjugate ale unui numr mare de persoane, comunitatea
dezvoltat n jurul acestui sistem de operare este adepta, n mare
majoritate, a conceptului de software liber. Iniiatorul acestei
micri a fost Richard Stallman.

Partea de interfa grafic este reprezentat de sistemul X Window


care include un sistem de ferestre ce permite aplicaiilor s afieze
rezultatele n ferestre separate un important aspect legat de acest

8
Sisteme de Operare Linux L

sistem este faptul c permite rularea aplicaiilor n reea.

Linux ofer un mediu prielnic dezvoltrii de programe prin


integrarea de aplicaii destinate programatorilor: compilatore
(gcc,g++), utilitare(gdb, make), sisteme de control al versiunii,
editoare, etc.

O alt caracteristic a sistemului de operare Linux este numrul


mare de distribuii disponibile: Ubuntu, RedHat, Debian, Suse,
Slackware, etc.

NTREBRI

Care sunt bazele Linux?

Unde a fost dezvoltat iniial UNIX?

Care sunt caracteristicile de baz Linux?

Ce ofer GPL?

Enumerai cteva distribuii de Linux.

9
Sisteme de Operare Linux L

CAP. II SISTEMUL DE FIIERE

2.1. STRUCTURA DE FIIERE


Una dintre cele mai importante caracteristici Linux este
modul n care trateaz fiierele. n Linux totul este organizat
sub form de fiier un fiier(aproape totul), adic programele
pot utiliza fiiere de pe discuri, porturile seriale, imprimantele
i alte dispozitive n acelai mod n care utilizeaz fiierele.
Acest fapt faciliteaz programarea deoarece nu mai trebuie
avut grij dac se lucreaz cu un terminal, fiier pe disc sau cu
o imprimant.

Sistemul de operare Linux utilizeaz trei tipuri de fiiere:

Fiiere obinuite sunt doar colecii de octei asupra


crora sistemul nu impune nici o structur particular. Acestea
sunt utilizate pentru fiierele text, fiierele de date pentru
programe i chiar pentru fiierele executabile ale programelor.
Cataloage un catalog este un mecanism care permite
seturilor de fiiere s fie grupate mpreun. Conceptual
reprezint un container n care pot fi plasate alte fiiere i
cataloage, de fapt catalogul conine doar numele fiierelor i
informaii despre locaia acestora. Deoarece un catalog poate
conine subcataloage avem de-a face cu o structur ierarhic.
Dispozitive aceast categorie este alctuit din
anumite tipuri de fiiere, cum ar fi cele asociate comunicaiei
ntre procese sau cele asociate comunicaiei cu diverse
dispozitive hardware ca terminale, CD-ROM, modem, etc.
Toate aceste fiiere sunt organizate ntr-o structur
ierarhic arborescent, avnd ca i vrf un singur catalog care
poart numele de rdcin, el fiind reprezentat prin
urmtorul simbol /. Acest catalog rdcin conine o serie
de alte cataloage ce au destinaii speciale. Aceste destinaii
sunt doar convenii i nu sunt obligatorii.

Semnificaia acestor cataloage:


/bin executabilele comenzilor
/dev fiierele speciale
/etc fiierele de configurare
/home cataloagele utilizatorilor
/lib bibliotecile standard

10
Sisteme de Operare Linux L

/mnt se vor mount-a alte sisteme de


fiiere(partiii)
/sbin comenzi de administrare
/tmp fiiere temporare
/usr date disponibile utilizatorilor
/var fiiere mari n cazuri speciale

bin dev etc home lib mnt sbin tmp usr var

X11 adm bin lib local man src

bin lib src linux

Fig. 2.1 Ierarhia de cataloage sistem.

Este posibil ca dou fiiere s aib acelai nume atta


timp ct sunt n cataloage diferite, referirea acestor fiiere
fcndu-se prin intermediul numelui de cale. Acesta poate fi:

- absolut ca punct de referin se ia catalogul rdcin,


ex:
/home/user/a
/home/dev/a

- relativ punctul de referin este reprezentat de un


catalog arbitrar:
/user/a
/user/b

La fiecare schimbare a catalogului noul catalog devine


catalogul curent de lucru. Acest lucru este foarte important
deoarece pentru fiecare program executat n Linux va rezulta
un proces care va avea ca parte a strii lui interne i catalogul
curent de lucru. Acesta fiind catalogul utilizat ulterior pentru
referiri bazate pe calea relativ. Dac procesul nu face
aranjamente specifice pentru a utiliza un alt catalog de lucru,
atunci implicit va utiliza catalogul n care a fost utilizatorul
cnd programul a fost pornit.

11
Sisteme de Operare Linux L

rdcin
/

dev bin home

user
a

Fiiere speciale a b

Fiiere obinuite

Fig. 2.2 Ierarhie de cataloage caz general

Atenie! Fiecrui fiier, stocat pe disc, indiferent de tipul


su i se asociaz un numr numit inode care reprezint de fapt
un index al unei intrri ntr-un ir stocat pe disc. Fiecare
element al irului este un inode care stocheaz in formaii
specifice unui anumit fiier (cnd a fost creat, cine i este
proprietarul i unde sunt stocate blocurile de date pentru
fiierul respectiv). Un catalog conine pe lng numele
fiierului i numrul de inode asociat acestuia. Fiecare pereche
nume inode dintr-un catalog poart numele de legtur sau
link.
n acest fel este posibil ca acelai nume de inode s apar
n unul sau mai multe link-uri. Aceasta ar nsemna ca un fiier
poate avea unul sau mai multe nume de cale valide.

Fig. 2.3 Fiiere organizare fizic


12
Sisteme de Operare Linux L

2.2. COMENZI SPECIFICE LUCRULUI CU


FIIERE
Imediat dup intrarea n sistem, implicit utilizatorul va fi
plasat ntr-un catalog asociat cu numele de login numit home.
Acesta va fi catalogul curent de lucru iniial.
Cel mai simplu mod de-a afla unde se afl catalogul
home situat n ierarhia de cataloage este prin comanda:
pwd present working directory(catalog de lucru
prezent)
parametrii fr

$ pwd
/home/user

rezultat afiarea catalogului curent de lucru

Pentru deplasarea catalogului curent de lucru este


disponibil comanda:
cd change directory
parametrii catalogul destinaie
implicit catalogul home al utilizatorului

$ cd /

rezultat catalogul curent de lucru este catalogul


rdcin

Pentru a obine o list a numelor fiierelor i


cataloagelor se utilizeaz comanda: ls
Parametrii l afiare extins

$ ls

De studiat! Utiliznd comenzile mai sus prezentate s se


parcurg i s se afieze coninutul catalogului home.

Comenzi specifice cataloagelor:


mkdir creeaz noi cataloage.
rmdir terge un catalog, dac nu conine nici un fiier.

13
Sisteme de Operare Linux L

De studiat! S se creeze un catalog cu numele work n


catalogul home al fiecrui utilizator.

Comanda de copiere n Linux este cp. Accept ca i


parametrii calea a dou fiiere obinuite realiznd o copie a
primului n al doilea. O alt form este cea n care al doilea
parametru este un catalog.
$cp fis1 fis2
rezultat: fis1 este copiat n fis2

$cp fis2 /home/user


rezultat: fis2 este copiat n /home/user

Dac de dorete actualizarea(crearea) timpului de acces


pentru un fiier se poate folosi comanda touch.

$touch fis1
rezultat: - dac fiierul fis1 exist actualizeaz timpul
acces
- creeaz fiierul dac nu exist pe disc.

n cazul n care se dorete s se tearg un catalog trebuie


ca n primul rnd s se tearg fiierele obinuite coninute n
acel catalog. Pentru tergerea acestor fiiere se poate folosi
comanda rm.

$rm fis1
rezultat: terge fis1

Atenie! n Linux tergerea fiierelor nu este reversibil,


de aceea se recomand utilizarea cu atenie a utilitarelor de
tergere.

Dac se dorete mutarea unuia sau mai multor fiiere se


poate utiliza utilitarul rm efectul este acelai ca i n cazul
utilizrii combinate a comenzilor cp i rm. Comanda rm se
poate folosi i pentru modificarea numelui fiierelor primite ca
i argumente.

De studiat! Pentru toate comenzile prezentate pn acum


s se utilizeze comanda man pentru a se studia posibilele
opiuni.

14
Sisteme de Operare Linux L

O categorie aparte de comenzi pentru lucrul cu fiierele o


reprezint cele destinate prelucrrii acestora. Dintre acestea
cele mai importante sunt:

Cat este prescurtarea pentru concatenate i este folosit


pentru concatenarea a dou sau mai multe fiiere.

$cat fis1 fis2

rezultat fis1 este adugat la sfritul fis2

Cat se poate folosi i fr argumente :

$cat
Acest text este doar un exemplu
Ctrl-d

Rezultatul este afiarea textului pe ecran pentru ca


implicit aceast comanda primete ca i ieire standard
ecranul iar ca i intrare standard tastatura.

De studiat! S se afieze pe ecran utiliznd cat coninutul


fiierului fis1 utilizat n temele anterioare.

Comanda cat se poate utiliza n mod eficient numai


pentru afiarea unor fiiere de mici dimensiuni care s ncap
pe ecran. Pentru cele de dimensiuni mai mari este mai eficient
s se foloseasc more.

Grep permite cutarea unui nume sau a unui format de


nume n fiierul primit ca i argument. Va deschide fiierul
respectiv i va afia fiecare linie din fiier n care se gsete
cuvntul cutat.

$grep root /etc/passwd

Rezultatul este afiarea tuturor liniilor ce conin cuvntul


root din fiierul passwd.

REZUMAT

O caracteristic important a sistemului de operare Linux

15
Sisteme de Operare Linux L

este organizarea unitar a fiierelor de configurare n


format text, ceea ce permite editarea lor direct de utilizator
fr a fi nevoie de utilitare specializate pentru aceast
operaiune.

Sistemul de fiiere Linux utilizeaz trei tipuri de fiiere:


fiiere obinuite, cataloage, fiiere speciale(folosite pentru
comunicarea cu diverse dispozitive).

Sistemul de fiiere are o structur arborescent catalogul din


vrful ierarhiei poart numele de rdcin (simbolizat prin
/).

Cele mai importante cataloage din sistem sunt: /bin, /dev,


/home, /etc, /home, /lib, /mnt, /sbin, /tmp, /usr, /var.

Comenzi folosite pentru vizualizarea cataloagelor: pwd, ls,


cd.
Comenzi folosite pentru gestionarea cataloagelor: mkdir,
rmdir.
Comenzi folosite pentru gestionarea fiierelor: cp, touch, rm.
Comenzi folosite pentru prelucrarea fiierelor: cat, grep.

NTREBRI

n ce catalog se gsesc fiierele executabile n mod uzual?

Dar fiierele de configurare?

Folosind comenzile prezentate creai o structur de directoare pe


3 nivele n catalogul home. Fiecare nivel s conin minim dou
cataloage i doua fiiere text.

De cte comenzi avei nevoie pentru a terge ntreaga ierarhie de


cataloage?

Care este efectul comenzii rm rf ?

S se afieze numrul de cuvinte din fiierul /etc/passwd(indicaie


folosii wc)

16
Sisteme de Operare Linux L

CAP. III INTERPRETOARE DE COMENZI

3.1. Introducere
Interpretorul de comenzi este un program care realizeaz
o interfa ntre utilizator i sistemul de operare, interfa care
preia comenzile utilizatorului i le transmite sistemului de
operare spre execuie. Pentru UNIX i clonele acestuia
(Linux) interpretoarele de comenzi sunt independente fa de
sistemul de operare ceea ce a dus la dezvoltarea unui numr
mare de astfel de interpretoare.
Primul interpretor de comenzi important, numit Bourne
shell, a fost dezvoltat de Steven Bourne i a fost inclus ntr-o
distribuie de UNIX lansat n 1979. Acest interpretor de
comenzi este cunoscut n cadrul sistemului de operare sub
numele de sh. Un alt interpetor de comenzi utilizat pe scar
larg este C shell cunoscut i sub numele de csh. Csh a fost
scris de Billy Joy ca parte integrant a unei distribuii de
UNIX numit BSD (Berkley System Distribution), i a aprut
la civa ani dup sh. Numele de Csh l-a primit datorit
asemnrii sintaxei comenzilor sale cu cea a instruciunilor
limbajului C, fapt ce l face mult mai uor n utilizare celor
familiarizai cu limbajul C. Toate aceste interpretoare au fost
iniial dezvoltate pentru Unix dar s-au dezvoltat versiuni ale
acestora i pentru Linux.
Unul dintre cele mai cunoscute interpretoare de comenzi
pentru Linux este bash (bourne again shell).
Atenie!
La intrarea n sistem fiecare utilizator primete o copie a
interpretorului de comenzi. Acesta pstreaz un mediu distinct
pentru fiecare utilizator din sistem.
n multe sisteme Linux comanda /bin/sh este de multe ori
un link ctre interpretorul de comenzi utilizat de ctre sistemul
de operare.
De studiat! S se determine versiunea curent a
interpretorului de comenzi utilizat de sistemul de operare.
Interpretorul de comenzi din Linux dei are unele
similitudini cu procesorul de comenzi DOS este un instrument
mult mai puternic oferind utilizatorului o multitudine de
faciliti.

17
Sisteme de Operare Linux L

3.2. Faciliti ale interpretoarelor de comenzi


Expandarea numelor de cale n exemplele de pn
acum s-au folosit numai nume de cale complet precizate.
Exist mai multe metode prin care numele de cale s fie
abreviate, iar interpretorul de comenzi va expanda aceste
nume nainte de ale transmite comenzilor. Un astfel de
caracter de abreviere este *. De exemplu

$ cp text/* backup

Aici prin * se nelege toate fiierele (cu excepia celor


ce ncep cu .) din catalogul text. Sensul comenzii este toate
fiierele din catalogul text vor fi copiate n catalogul backup.
Un alt caracter special utilizat n numele fiierelor pe care
interpretorul de comenzi le va expanda este semul ntrebrii ?.
Rolul acestuia este de a substitui un singur caracter :

$ ls /dev/tty?
/dev/tty0 /dev/tty2 /dev/tty4
/dev/tty6 /dev/tty8
/dev/tty1 /dev/tty3 /dev/tty5
/dev/tty7 /dev/tty9

De asemenea este posibil precizarea unei liste de


caractere, i numai caracterele coninute n aceast list s
poat fi expandate. Aceast list este delimitat de paranteze
drepte ([]).Ex:

$ ls /dev/tty[pq][235]
/dev/ttyp2 /dev/ttyp3 /dev/ttyp5
/dev/ttyq2 /dev/ttyq3 /dev/ttyq5

O ultim form de expandare pentru numele de cale este


prin precizarea unei liste de cuvinte, cuvintele vor fi separate
prin virgul i cuprinse ntre paranteze {}.
Ex:
$ mkdir /usr/tmp/{bin,doc}

Atenie! Toate numele de cale sunt expandate de


interpretorul de comenzi nainte a fi transmise ctre comenzi.

18
Sisteme de Operare Linux L

n cazul n care se dorete utilizarea caracterelor


speciale cu sensul lor iniial se poate utiliza unul din
urmtoarele trei mecanisme de marcare:
- caractere escape(\) caracterul backslash indic
interpretorului de comenzi s ignore sensul special al
caracterelor de dup marcaj. Ex: \*.
- ghilimele orice ir de caractere cuprins ntre aceste
marcaje i pierde sensul special al tuturor caracterelor
cuprinse n el. Ex: a*?
- ghilimele duble un ir de caractere pierde sensul
special al caracterelor cuprinse n el (este valabil numai pentru
caracterele prezentate pn acum) , cu excepia caracterelor $
i \.
Ex:
`cmd`
Executa comanda cmd. De exemplu: $ cale=`pwd`
atribuie variabilei cale rezultatul comenzii pwd.

Redirectarea ieirii i a intrrii Filosofia de baz Linux


este aceea de ine lucrurile ct mai simple posibil, prin
punerea la dispoziia utilizatorului a unui numr mare de
funcii simple. Iar prin gruparea acestor funcii mpreun se
pot obine comenzi mai complexe. Implicit, majoritatea
comenzilor Linux sunt configurate astfel nct intrarea
acestora s o reprezinte tastatura iar datele de ieire sunt
trimise ctre monitor. n unele situaii ar fi util dac intrarea ,
respectiv ieirea unei comenzi ar fi altele dect cele implicite.
Unele comenzi au aceast facilitate, dar dac pentru fiecare n
parte s-ar prevedea acest lucru dimensiunea executabilelor ar
crete, de aceea aceast sarcin i-a asumat-o sistemul de
operare prin intermediul acestui mecanism de redirectare.
Un exemplu clasic este cel de creare a unui nou fiier
prin care ieirea standard a comenzii cat este redirectat ctre
fiierul care urmeaz a fi creat:

$ cat > text


Un text de exemplu
Ctrl-d
$

Se observ c n aceast situaie se folosete caracterul


>. Acesta are rolul de a indica redirectarea ieirii standard
ctre o alt comand. Dac este urmat de un nume de fiier

19
Sisteme de Operare Linux L

atunci acest fiier este creat dac nu exist, iar dac exist
atunci va rescris. Un alt simbol utilizat de acest mecanism de
redirectare este >>. n cazul n care ieirea este reprezentat
de un fiier datele redirectate vor fi concatenate la sfritul
fiierului. Ex:

$ ls l /usr/bin >>text

Rezultat: toate numele fiierele din /usr/bin, mpreun cu


informaiile despre acestea sunt adugate la fiierul text.
Tot la fel cu redirectarea ieirii se poate redirecta i
ieirea de eroare:

$ ls /usr/bin 2>text.err

La fel cum se poate realiza redirectarea ieirii standard, la


fel se poate redirecta i intrarea standard:

$ wc l < /etc/passwd
12

Rezultat: numrul de intrri din fiierul de parole.

Pipes sau conectarea proceselor prin redirecionarea


ieirii standard a unei comenzi ntr-un fiier, iar apoi
redirecionarea aceluiai fiier ca i intrare standard pentru alt
comand se pun practic n legtur dou procese prin
intermediul unui fiier temporar. Acest lucru se poate face
implicit de ctre sistemul de operare prin intermediul unui
pipe. Pentru aceasta se folosete operatorul |.

De exemplu seria de comenzi:


$ ls /usr/bin > /tmp/temp.txt
$ wc w </tmp/temp.txt
500
$ rm /tmp/temp.txt

poate fi nlocuit prin:


$ ls /usr/bin | wc w
500

Controlul proceselor Permite ntreruperea unui proces


i de asemenea reluarea execuiei acelui proces la un moment
de timp ulterior. ntreruperea execuiei unui proces se poate
20
Sisteme de Operare Linux L

face direct de la tastatur prin secvena Ctrl-z, dup care


procesul va fi ntrerupt iar utilizatorul reprimete controlul
putnd executa alte comenzi.

$ cat > file.txt


Ctrl-z
[1]+ Stopped
$

Pentru gestionarea proceselor interpretorul de comenzi


are implementate o serie de comenzi:
fg este comanda prin care este reluat execuia unui
proces, aceasta poate primi ca i parametru numrul de ordine
al procesului ntrerupt. Pentru a relua execuia ultimului
proces ntrerupt avem:

$fg %1
cat >file.txt

bg se folosete pentru suspendarea unui proces,


echivalent cu Ctrl-z
jobs afieaz procesele suspendate.

Alte faciliti ale interpretorului de comenzi Linux:


- history posibilitatea de rechemare rapid a ultimilor
comenzi executate.
- command complition afiarea posibilelor comenzi
pornind de la primele caractere ale numelor acestora.
De studiat! Pagina de manual pentru comenzile
prezentate.

3.3. Sintaxa interpretorului de comenzi.


Programarea n cazul interpretorului de comenzi se face
n acelai mod ca i n cazul altor limbaje de programare. i n
acest caz vom avea:

Variabile n mod normal nu sunt declarate dect atunci


cnd este nevoie de ele. Implicit variabilele sunt memorate i
considerate drept iruri de caractere, chiar i atunci cnd
primesc valori numerice.

21
Sisteme de Operare Linux L

Variabilele pot fi de mai multe tipuri: variabile


predefinite sau speciale, parametrii poziionali sau variabile
utilizator.
Variabile predefinite sau speciale la pornirea sistemului
o serie de variabile sunt iniializate cu valorile implicite
mediului de operare. Cele mai importante sunt urmtoarele:

$HOME catalogul gazd a utilizatorului curent


$PATH o list de cataloage n care interpretorul caut
pentru fiierul executabil asociat unei comenzi.
$SHELL numele interpretorului de comenzi curent.
$PS1 definete prompterul interpretorului, implicit
acesta este $.
$IFS Internal Field Separator utilizat pentru separarea
cuvintelor i a liniilor .
$0 numele fiierului de comenzi.
$# numrul de parametri transmii fiierului de
comenzi.
$$ numrul de identificare prin care sistemul identific
scriptul n momentul execuiei.

Parametrii poziionali Dac la apelarea unui fiier de


comenzi (script) sunt folosii parametrii atunci sunt create
cteva variabile suplimentare. Chiar dac nu se folosesc
parametrii tot se creeaz variabila $# dar va avea valoarea 0.
Variabile de acest tip sunt:
$1, $2, .. parametrii transmii scriptului.
$* - lista cu parametrii transmii scriptului.
$@ -
Accesarea coninutului variabilei se face prin prefixarea
acesteia cu caracterul $.
Ex:
$ salut=Hello
$ echo $salut
Hello

Pentru ca o variabil s fie cunoscut unui subshell


aceast comand trebuie s fie exportat. Aceasta se realizeaz
cu ajutorul comenzii export.

Structuri de control i n acest caz se ntlnesc structuri


de control la fel ca i n cazul altor limbaje de programare.

22
Sisteme de Operare Linux L

If testeaz rezultatul unui comenzi i n funcie de


rezultatul acesteia se execut una dintre ramurile de declaraii.
Format:

if condiie
then declaraii
[ elif condiie
then declaraii]
[ else declaraii]
fi

Se executa condiie; daca codul returnat este zero se


executa declaraiile ce urmeaz primului then. In caz contrar,
se executa condiia de dup elif si daca codul returnat este
zero se executa declaraiile de dup al doilea then.
Ex:

if test -f $1
then echo $1 este un fiier obinuit
elif test -d $1
then echo $1 este un catalog
else echo $1 este altceva
fi

for folosit pentru trecerea printr-un anumit numr de


valori(pot fi i iruri de caractere). Sintaxa:

for nume [in valori]


do declaraii
done

Variabila nume ia pe rnd valorile din lista ce urmeaz lui


in. Pentru fiecare valoare se executa ciclul for. Daca in valori
este omis, ciclul se executa pentru fiecare parametru
poziional. Condiia poate fi si in * , caz in care variabila
nume ia pe rnd ca valoare numele intrrilor din directorul
curent.

while n cazul n care se dorete trecerea printr-un


numr mai mare de valori este util folosirea acestei structuri
de control. Sintax:

while condiie
do declaraii

23
Sisteme de Operare Linux L

done

until ciclu identic cu for dar n acest caz testarea


condiiilor se face la sfrit. Sintax:

until lista_1
do lista
done

case aceast structur are sintaxa:

case condiie in
ablon_1) declaraii;;
ablon_2) declaraii;;
...
esac

Se compara condiie cu fiecare din abloanele prezente


si se executa lista de comenzi unde se constata potrivirea.

Proceduri shell reprezint o modalitate de a grupa mai


multe comenzi shell la un singur loc n vederea execuiei lor
ulterioare. Forma general a unei astfel de proceduri este:

nume() { lista; }

Unde nume este numele procedurii (sau funciei), iar lista


este o list de comenzi, i pipe-uri care urmeaz s fie
executate.
Ex:

$ lsl() { ls l; }

Rezultatul este o funcie care are acelai rezultat ca i ls -l

Cteva comenzi specifice interpretoarelor de comenzi:


Test este folosit pentru a pentru a testa o expresie
dac este adevrat atunci test va returna 0, n caz contrar va
returna 1. Uzual test este folosit pentru a verifica tipul unor
fiiere:
test e fiier adevrat dac fiierul exist
test f fiier adevrat dac fiierul este unul obinuit
test f fiier adevrat dac fiierul este catalog

24
Sisteme de Operare Linux L

Atenie! Comenzile test condiie i [ condiie ] sunt


echivalente.

Export face disponibile variabilele primite ca i


argument n subshell-urile viitoare. Implicit variabilele create
ntr-un shell nu sunt disponibile ntr-un shell creat ulterior.

Echo afieaz argumentele la ieirea standard

Eval realizeaz evaluarea i apoi execuia


argumentelor

Exit foreaz ntreruperea procesului curent care va


returna ca i cod de ieire valoarea primit ca i argument.
Ex: Exit n

Read citete o linie din fiierul standard de intrare.

Break Comanda de prsire a celei mai interioare bucle


for, while sau until ce conine break. Daca n este specificat se
iese din n bucle.

Continue comanda permite trecerea la o nou iteraie a


buclei for, while sau until.

Return revenirea dintr-o funcie cu valoarea n, unde n


este valoarea transmis ca i argument. Dac aceast valoare
nu este precizat atunci codul returnat este cel al ultimei
comenzi executate.

Set folosit pentru activarea sau dezactivarea unor


opiuni sau pentru poziionarea unor parametrii poziionali.

Sleep suspend execuia pentru un numr n de secunde


primit ca i argument.
De studiat!
man bash
pentru fiecare din comenzile precizate mai sus s se
studieze pagina de manual.

25
Sisteme de Operare Linux L

REZUMAT

Un interpretor de comenzi realizeaz interfaa ntre utilizator


i sistemul de operare, interfa prin intermediul creia se
preiau comenzile utilizatorului i sunt transmise
sistemului de operare pentru execuie.

Dintre cele mai folosite interpretoare de comenzi primul


important este Bourne shell, a fost iniial inclus ntr-o
distribuie de UNIX lansat n 1979. O alt versiune este C
Shell (csh) i a fost lansat pe BSD(sintax asemntare cu
limbajul de programare C). Unul dintre cele mai folosite
interpretoare de comenzi este bash, o versiunea mbuntit
a sh, acesta fiind folosit i n lucrarea de fa.

Caracteristici:

Expandarea numelui de cale putem ntlni patru situaii:


* - nlocuiete un numr variabil de caractere.
? nlocuiete un singur caracter.
[] sunt folosite doar caracterele din lista(list de
caractere).
{} sunt folosite doar cuvintele din list(list de cuvinte).

Caractere speciale, avem trei mecanisme de marcare:


Caractere escape se folosete caracterul backslash \,
interpretorul ignor sensul special al caracterelor ce
urmeaz.
Ghilimele - interpretorul ignor sensul special al
caracterelor cuprinse ntre ghilimele.
Ghilimele duble - interpretorul ignor sensul special al
caracterelor cuprinse ntre ghilimelele duble, excepie fac
urmtoarele marcaje $ i \.

Redirectarea intrrii i a ieirii unui program permite


gruparea n serie a dou sa mai multe comenzi, ieirea
primeia reprezentnd intrare pentru a doua, de exemplu
putndu-se realiza o filtrare a mesajului iniial. Simboluri
speciale folosite pentru redirectare: >, >>, |.

Unul dintre avantajele interpretoarelor de comenzi este


posibilitatea de a realiza programe ntr-o manier
asemntoare altor limbaje de programare.
26
Sisteme de Operare Linux L

Variabilele nu trebuie declarate nainte de utilizare, spaiul


de memorie va fi alocat la prima utilizare a variabilei
respective. Tipuri de variabile: speciale($HOME, $PATH,
$SHELL, $0, $#, $$, etc), parametrii poziionali($1, $2, )

Structuri de control folosite n cadrul interpretoarelor de


comenzi: if, for,while, until.

O alt structur de control implementat n interpetoarele de


comenzi este procedura(funcia). Parametrii
procedurii(funciei) sunt tratai n acelai mod n care sunt
tratai parametrii scriptului.

Comenzi specifice: test, export, echo, eval, exit, read, break,


continue, return, set, sleep.

NTREBRI

Ce este un interpretor de comenzi?

Ce interpretoare de comenzi cunoatei?

Cum se realizeaz expandarea numelui?

Cum filtra fiierele text folosind facilitile oferite de


interpretoarele de comenzi?

Ce variabile bash predefinite cunoatei?

Cum se poate afla numrul de parametrii transmii unui script?

Realizai un script care s parcurg un catalog, primit ca i


argument, si pentru fiecare intrare din catalogul respectiv sa se
afieze tipul (fiier sau catalog) i numele intrrii respective.

Extindei scriptul scris la pasul anterior astfel nct, parcurgerea


coninutului catalogului s se realizeze n mod recursiv (s
parcurg si afieze tipul pentru ntreaga ierarhie de cataloage).

27
Sisteme de Operare Linux L

CAP. IV MAKE

4.1. Introducere

Make este una dintre uneltele care mbuntesc eficiena


n medii de lucru de genul Linux/UNIX. n principiu este un
generator de comenzi care pe baza unui fiier de descriere
creeaz o secven de comenzi ce trebuie executate de ctre
interpretorul de comenzi Linux. Make este o unealt folosit
n general pentru determinarea relaiilor de dependen ntre
fiiere. n situaia n care se lucreaz la un proiect ce implic
utilizarea mai multor fiiere surs, dac unul sau mai multe
fiiere surs sunt modificate atunci procesul de recompilare
trebuie reluat, dar n general nu este necesar ca acest proces s
fie reluat n ntregime de obicei fiind necesar recompilarea
doar a acelor surse ce au fost modificate. n acest context
make este o unealt esenial putnd determina dependene ce
pot aprea ntre diverse fiiere. Ca i concept de programare n
ansamblu make este non-procedural, dei intrrile individuale
se execut. Comenzile ce trebuie executate sunt determinate
printr-un proces iterativ de determinare a dependenelor
fiierelor ce trebuie prelucrate. Forma general de apelare a
acestui utilitar este:

$make program

Aceast sintax indic faptul c se dorete executarea


tuturor operaiilor de determinare a dependinelor ntre fiiere
i de compilare a acestora necesare pentru crearea
executabilului program. n aceast situaie apare noiunea de
int care este reprezentat de program, totodat acesta este
construit din una sau mai multe dependine, fiecare dintre
acestea putnd avea la rndul lor inte pentru alte dependine.
Caracteristica esenial a acestui utilitar este aceea c fiecare
nou apelare a acestuia va determina evaluarea n lan tuturor
dependinelor i prelucrarea n final doar a celor pentru care s-
au constatat modificri. Funcionarea utilitarului make se
bazeaz pe structur ierarhic de tipul surs-obiect i obiect-
executabil. Programatorul este responsabil pentru precizarea
unor dependene prin intermediul unui fiier numit makefile,
restul fiind determinate pe baza timpului ultimei modificri i
a unui set de reguli.
28
Sisteme de Operare Linux L

Fiierul de descriere:
S presupunem c avem un program destinat unor
prelucrri de date alctuit din trei fiiere: main.c, interfata.c,
prelucrari.c. O compilare manual a programului arat astfel:

$ gcc main.c
$ gcc interfata.c
$ gcc prelucrare.c
$ gcc o exemplu main.o interfata.o
prelucrari.o /usr/lib/my_lib.a

n acest caz particular ntreaga compilare a programului


se poate face ntr-o singura linie de comand, dar n cazul
proiectelor de mari dimensiuni la care lucreaz mai multe
persoane acest lucru este practic imposibil. Pentru a putea
utiliza make trebuie creat un fiier de descriere numit makefile
care n acest caz are urmtoare structur:

exemplu : main.o interfata.o


prelucrari.o /usr/lib/my_lib.a
gcc o exemplu main.o interfata.o
prelucrari.o /usr/lib/my_lib.a
main.o : main.c
gcc c main.c
interfata.o : interfata.c
gcc c interfata.c
prelucrari.o : prelucrari.c
gcc o prelucrari.c

n cazul acestui fiier de descriere se pot observa patru


intrri, fiecare intrare constnd din dou elemente distincte o
linie numit linie de dependene i una sau mai multe linii de
comenzi. Pentru acest exemplu intele sunt: exemplu, main.o,
interfata.o, prelucrari.o.
Atenie! Liniile de comenzi trebuie s nceap cu un
caracter tab.
ntr-un fiier makefile comentariile sunt delimitate de
caracterul # i continu pn la sfritul liniei.
O alt caracteristic este flexibilitatea ntr-un fiier de
descriere se pot preciza mai multe programe executabile care
s fie realizate. Astfel la fiierul de descriere anterior se pot
aduga urmtoarele linii:

29
Sisteme de Operare Linux L

exemplu_text : main_text.o
prelucrari.o
gcc o exemplu_text main_text.o
prelucrari.o

main_text.o : main_text.c
gcc c main_text.c

Vom avea dou interfee diferite pentru acelai program.


Pentru make exemplu vom avea un program cu o interfa
grafica, pe cnd pentru make exemplu_text, vom avea aceeai
aplicaie de prelucrri de date dar care va opera din linia de
comand. Cel mai simplu mod de apelare make este fr nici
un parametru:

$ make

n acest caz se va realiza prima int gsit n fiierul de


descriere makefile, bineneles mpreun cu toate dependinele
sale.
O ultim observaie este faptul c putem avea inte fr
dependine, iar multe dintre acestea nu sunt nici mcar fiiere.
De exemplu multe fiiere de descriere conin inta clean
destinat eliminrii fiierelor temporare obinute n urma
procesului de compilare.

clean :
/bin/rm f *.o

Iar apelul va fi de forma:

$ make clean

4.2. Macro
n cazul aplicaiilor de dimensiuni mai mari i nu numai
la realizarea fiierelor de descriere se poate observa repetarea
unui anumit numr de elemente putndu-se ajunge la
dimensiuni relativ mari ale acestor fiiere. Pentru a preveni
aceast situaie se vor utiliza macrouri i sufixe.
Definiiile de macrouri din cadrul fiierelor de descriere
vor arta astfel:

nume = sir de caractere.

30
Sisteme de Operare Linux L

Iar referirea acestora se va face prin construcii de genul:

$(nume) sau ${nume}

Reguli de sintax:
O definiie macro este o linie care conine semnul egal.
Make asociaz numele din stnga semnului egal cu secvena
de caractere care urmeaz n partea dreapt. Pentru ca make s
fac deosebirea ntre o linie de comand i un macro, naintea
acestuia nu este permis un caracter tab. De asemenea pentru a
diferenia un macro de o linie de dependine nu este permis
apariia caracterului ; naintea semnului egal. Alt caracter cu
semnificaie special este \ care indic faptul c linia curent
se continu pe linia urmtoare, acest caracter este nlocuit de
ctre make cu un spaiu. Toate spaiile, tab-urile i linie nou
sunt nlocuite cu un singur spaiu.
Prin convenie numele de macrouri se scriu cu caractere
mari. n acestea pot aprea orice combinaie de caractere mari
mici dar se recomand evitarea caracterelor speciale n special
\ i >.
Pentru referirea unui macro se utilizeaz de obicei
notaia n paranteze sau n acolade precedat de semnul $.
Cele a cror nume este alctuit dintr-un singur caracter nu cer
utilizarea n mod obligatoriu a unei paranteze. De exemplu
considernd urmtorul macro:
A=cpp
Acesta poate fi referit astfel: $A, $(A), ${A}.
Aceste structuri sunt flexibile permind utilizarea de
macro-uri n noi definiii:
ABC = cpp
file = text.$(ABC)
Prin referirea acestui macro $(file) vom avea text.cpp.
Unei definiii macro, care dup semnul egal nu are nici
un caracter, i se va atribui irul nul.
O alt caracteristic a acestui utilitar este faptul c nu
trebuie inut cont de ordinea n care aceste macro sunt definite,
uurnd definirile imbricate. Ex:

SOURCES = ${MY_SRC} ${SHARED_SRC}


MY_SRC = analizeaza.c
prelucreaza.c
SHARED_DIR = /home/proiect/src

31
Sisteme de Operare Linux L

SHARED_SRC = ${SHARED_DIR}/depend.c

Indiferent de ordinea definiiilor de mai sus


${SOURCES} va avea urmtoarea form:
analizeaza.c prelucreaza.c /home/proiect/src/depend.c
Atenie! Orice definire de macro trebuie s aib loc
nainte de linia de dependene n care acesta apare.
Aceast libertate de declarare implic totui o limitare:
un macro nu poate definit ntr-o parte a fiierului i apoi
redefinit deoarece make utilizeaz ultima definiie pentru toate
referirile acestuia.
Pe lng macrourile definite de ctre utilizatori exist o
serie predefinite, cele mai cunoscute sunt ${CC} utilizat
pentru a defini compilatorul de C curent i ${LD} indic
linker-ul utilizat.
Utilitatea utilizrii unui macro pentru a indica
compilatorul de C utilizat pentru proiectul curent se poate
observa n mediile de dezvoltare volatile n care
compilatoarele sunt frecvent schimbate. Ex:

CC = cc
HelloWorld.o : HelloWorld.c
${CC} c HelloWorld.c

va avea acelai efect ca i:

HelloWorld.o : HelloWorld.c
cc c HelloWorld.c

n general fiecare macro care definete o comand (Ex


CC) necesit nc un macro care s defineasc opiunile pentru
comanda respectiv. Astfel pentru a preciza diverse opiuni
pentru compilatorul de C (CC) vom avea macroul CFLAGS,
iar pentru LD vom avea LDFLAGS.

Un alt mod de definire de macro este din linia de


comand:

$ make refext DIR=/usr/proj

De asemenea trebuie inut cont de variabilele


intrepretorului de comenzi care fac parte din mediul de lucru,
n momentul apelrii make acestea vor fi considerate ca fiind

32
Sisteme de Operare Linux L

macro-uri din fiierul de descriere i pot fi utilizate ca atare.


Dac considerm urmtoarea secven de comenzi:

$ DIR = /home/student/proiect
$ export DIR
$ make refext

n acest context variabila DIR poate fi utilizat n cadrul


fiierului de descriere:

SRC = ${DIR}/src
refext :
cd ${DIR}/src

Dup cum se poate observa un macro poate fi definit n


mai multe moduri: prin intermediul variabilelor mediului de
lucru, din linia de comand, n interiorul fiierului de descriere
sau pot fi macrouri predefinite. Pentru un anumit macro pot
aprea conflicte ntre definiiile provenite din diverse surse. n
aceast situaie se pune problema unei structuri de prioriti
care s fie urmrit n cazul unor astfel de conflicte. n ordinea
prioritilor vom avea:
Definiii introduse din linia de comand.
Definiiile din fiierul de descriere.
Variabilele de mediu din aferente interpretorului de
comenzi.
Definiiile interne (implicite).

Un alt element important ce apare n cadrul definiiilor de


macro este substituirea de irurilor de caractere. S
presupunem c avem urmtoarele definiii:

SRCS = def.c cauta.c calc.c


ls ${SRCS:.c=.o}

rezultatul va fi: def.o cauta.o calc.o


Algoritmul utilizat pentru substituie este urmtorul este
urmtorul: se evalueaz expresia ${SRCS} apoi se caut irul
de caractere ce urmeaz n definiie dup caracterul : i este
nlocuit cu irul de caractere de dup semnul =. Aceast
facilitate este aplicabil grupurilor de fiiere care difer doar
printr-un sufix.

33
Sisteme de Operare Linux L

Atenie! Asupra substituirilor irurilor de caractere se


aplic o serie de restricii se pot face doar la sfritul unui
macro sau naintea unui spaiu.

4.3. Reguli de adugare a sufixelor

n sistemele Linux(UNIX) fiierele surs C au


ntotdeauna extensia .c, o cerin impus de compilatorul de
cc. Similar fiierele surs Fortran au extensia .f cele pentru
limbajul de asamblare au extensia .s, iar compilatoarele de C
i Fortran i plaseaz modulele obiect n fiiere cu extensia .o.
Acest tip de convenii fac posibil utilizarea unor reguli
de adugare a sufixelor pentru simplificarea fiierelor de
descriere utilizate de make. Primul exemplu va avea
urmtoarea form:

CC = gcc
OBJS = main.o interfata.o
prelucrari.o
LIB = /usr/lib/my_lib.a

exemplu : ${OBJS} ${LIB}


${CC} o $@ ${OBJS} ${LIB}

unde prin $@ se specific inta curent pentru make.


Atenie! Un alt macro des utilizat este $?, are rolul de a
determina dependinele ce au fost actualizate n urma intei
curente.
Pentru a obine executabilul exemplu utilitarul make
verific mai nti dac main.o este up to date(actual).
Realizeaz acest lucru verificnd dac sunt actuale toate
fiierele care conform fiierului de descriere sunt folosite
pentru compilarea lui main.o. Dac descoper de exemplu c
fiierul main.c a fost modificat va apela compilatorul de C
pentru acel fiier, dac descoper un fiier main.f mai recent
dect main.o atunci va apela compilatorul de Fortran. Dac
regulile de adugare a sufixelor nu sunt precizate, atunci make
va utiliza regulile de adugare implicite. Pentru exemplu
precizat acestea sunt:

.SUFFIXES : .o .c .s
.c.o :
$(CC) $(CFLAGS) c $<
.s.o :
34
Sisteme de Operare Linux L

$(AS) $(ASFLAGS) c $@ $<

Linia ce conine .SUFFIXES are forma unei linii de


precizare a dependenelor, dar apare o diferen. irurile
coninute n aceast linie sunt sufixele care vor fi considerate
de make ca fiind semnificative. Dac o dependin se termin
cu un astfel de sufix, i nu are nici o comand definit n mod
explicit de ctre utilizator, make va cuta o regul ce poate fi
aplicat dependenei respective. S considerm exemplul
anterior. La construirea executabilului, make va urma paii:
Va cuta fiecare fiier dependin dat de expresiile
${OBJS} i ${LIB}, care va deveni la rndul lui int. Aceste
operaii sunt realizate pentru a se stabili care fiier trebuie
recompilat nainte de a realiza executabilul final.
Executabilul exemplu depinde printre alte fiiere i de
prelucrari.o. Cnd make va cuta dependenele pentru
prelucrari.o va verifica prima dat sunt definiii date de
utilizator care prelucrari.o ca i int. Negsind niciuna va
nota ca sufixul semnificativ este .o i va cuta un alt fiier din
directorul curent care s poat fi folosit pentru a construi
fiierul prelucrari.o. Acest fiier trebuie:
- s aib acelai nume(n afar de sufix) cu prelucrari.o.
- s aib un sufix semnificant.
- S poat fi folosit la construcia lui prelucrari.o pe baza
unei reguli de adugare a sufixelor existent.

n cazul exemplului de mai sus toate aceste reguli sunt


satisfcute de fiierul prelucrari.c. Regula care va fi folosit
este:

.c.o :
$(CC) $(CFLAGS) c $<

Unde $< are un sens nrudit cu $? dar este valabil doar n


cazul regulilor de generare a sufixelor. Evalueaz care
dependen a determinat utilizarea acelei reguli i este
fiierul prelucrari.c. Fiierul cu extensia .o poate fi considerat
inta acestei reguli, iar fiierul cu extensia .o dependina.
n continuare make va aplica regula de creare a
fiierului prelucrari.o numai dac:
- numai sunt alte dependene care trebuie s fie verificate
nainte.
- prelucrari.o este anterior lui prelucrari.c

35
Sisteme de Operare Linux L

n final dup ce s-a realizat acest proces pentru fiecare


fiier din ${OBJS} i ${LIB}, make va executa comanda ld
pentru a crea fiierul exemplu dac n ierarhia de dependene
exist cel puin un fiier cu o dat de modificare mai recent
dect exemplu.

Atenie! n lista de sufixe ce urmeaz dup .SUFFIXES


trebuie s fie cte un spaiu i trebuie s lipseasc dintre cele
dou sufixe care ncep o regul de adugare de sufixe.

ntr-un fiier de descriere se pot preciza i comenzi ale


sistemului de operare, iar make le va trata identic cu
interpretorul de comenzi. Astfel fiierului de descriere va avea
acces la toate caracteristicile interpretorului de comenzi ca de
exemplu redirectarea ieirii sau expandarea numelor de cale.
Singura restricie este ca toat secvena de comenzi s fie ntr-
o singur linie. Astfel secvena de comenzi:

cd tmp
rm *

nu va funciona, dar puse pe o singur linie vom obine


rezultatul dorit:

cd tmp; rm *

pentru secvene mai mari de comenzi se poate utiliza


caracterul \ care permite comenzilor s aparin teoretic unei
singure linii.

Make, pe lng intele obinuite(fiiere) mai poate avea i


inte simple, nume de convenien, pentru diverse activiti,
numite inte vide. Putem avea astfel de inte n momemtul n
care se dorete utilizarea lui make ca i unealt de instalare a
unor programe:

INSTALLDIR = /usr/local/exemplu

install : disp trac plot


cp f disp ${INSTALLDIR}
cp f trac ${INSTALLDIR}
cp f plot ${INSTALLDIR}
cd ${INSTALDIR};\
chmod 755 disp trac plot
36
Sisteme de Operare Linux L

Practic aceste inte vide sunt n afara lanului normal de


dependene ntre fiiere i foreaz ntr-un fel realizarea unei
aciuni. Dac pentru fiierele reale verific timpul ultimei
modificri pentru aceste tipuri de inte se utilizeaz alte reguli:

O int vid este tot timpul out of date, astfel


comenzile asociate ei se execut tot timpul.
O dependen vid este tot timpul mai actual dect
inta ei provocnd tot timpul reconstruirea intei.

Atenie! Dac se utilizeaz ca i dependen un nume vid,


acesta trebuie s apar ca i int altfel make se va opri cu
eroare.
REZUMAT

Make este o uneal ce urmrete mbuntirea eficienei


lucrului, make fiind un generator de comenzi ce pe baza unui
fiier de descriere genereaz o serie de comenzi ce trebuie
executate de interpretorul de comenzi.

Din punctul de vedere al programrii make este un limbaj de


programare nonprocedural, comenzile ce trebuie executate
sunt determinate printr-un proces iterativ de determinare a
dependinelor. Funcionarea bazndu-se pe o structur
ierarhic de tipul surs-obiect i obiect-executabil, acestea
fiind stabilite prin intermediul unui fiier numit Makefile, iar
comenzile care vor fi executate se stabilesc pe baza timpului
ultimei modificri.

O caracteristic important a acestui utilitar este


flexibilitatea, fiierul de configurare (Makefile) putnd
conine mai multe inte pentru care se pot genera comenzi, n
cazul n care make este apelat fr parametrii va fi realizat
prima int gsit n Makefile.

Pentru o mai mare flexibilitate i pentru a elimina elemente


repetitive se pot folosi macro i sufixe.

Macro este o definiie prin care un nume este asociat cu o


secven de caractere, cu ajutorul semnului egal. Make
asociaz numele din stnga semnului egal cu secvena de
caractere din dreapta, n continuare numele fiind nlocuit cu
37
Sisteme de Operare Linux L

secvena de caractere.

Pentru a accesa un macro se folosete notaia ntre


paranteze: $A, $(A), ${A}.

Macro pot fi definite prin mai multe surse: variabile de


mediu, linia de comand, n Makefile sau pot fi macro
predefinite. Pentru a elimina conflictele n cazul redefinirii
unui macro ordinea prioritilor este urmtoarea: linia de
comand, fiierul de descriere(Makefile), variabile de mediu,
definiii interne.

Make ofer posibilitatea de a controla tipurile de fiiere


utilizate prin intermediul unui mecanism de control al
sufixelor. Pe baza acestui mecanism se pot preciza tipurile
fiierelor ce pot fi folosite n procesul de compilare.

n afar de intele obinuite, make, poate avea i inte vide


(non-fiiere), astfel make putnd fi folosit i n procesul de
instalare al unui program. Aceste inte vide sunt tot timpul
aut of date, comenzile asociate unei astfel de inte vor fi
executate n orice situaie.

NTREBRI

Ce este make?

Cum se stabilesc comenzile ce urmeaz a fi executate?

Ce este macro?

Cum se poate defini un macro i unde se poate defini un macro ?

Care este ordinea de prioriti a surselor macro n cazul unui


conflict?

Ce sunt intele vide i cum pot fi folosite?

Cum pot fi controlate tipurile de fiiere folosite de make i care


sunt paii de aplicare?

Presupunnd c avei de realizat un program care trebuie s


creeze un mediu virtual ce const din mai multe obiecte scriei

38
Sisteme de Operare Linux L

fiierul Makefile necesar generrii executabilului.


Mediul virtual va consta n urmtoarele fiiere:
Mediu virtual vr.cc
Camera camera.cc, camera.h
Birou birou.cc, birou.h
Dulap dulap.cc, dulap.h
Scaun scaun.cc, scaun.h

Executabilul va fi generat prin compilarea fiierul vr.cc, iar acesta


va depinde de toate fiierele ce descriu obiectele din mediu
(Camera Scaun, .cc, .h), toate fiierele obiect depind la rndul
lor de biblioteca sistem libQt.so

39
Sisteme de Operare Linux L

CAP. V Lucrul cu fiiere


5.1. Sistemul de fiiere Linux considerente
generale
Sistemul de fiiere din UNIX este caracterizat prin:

o structur ierarhic
tratare consistent a fiierelor de date
protejarea fiierelor

n cazul sistemului de fiiere din Linux se urmresc


aceleai principii de baz ca i n cazul UNIX, adic se
ncearc ca intrarea i ieirea pentru diverse dispozitive ca
discuri, terminale, imprimate s se realizeze la fel ca i lucrul
cu fiiere obinuite.
Fiecare fiier este reprezentat de o structur numit
inode. Fiecare inode conine descrierea fiierului: tipul
fiierului, drepturile de acces, proprietarul, informaii
referitoare la dat, dimensiune, referine ctre blocurile de
date. Adresele blocurilor de date alocate fiierului sunt de
asemenea stocate n cadrul inode-ului. Cnd un utilizator
solicit o operaie de intrare/ieire asupra fiierului, kernel-ul
sistemului de operare convertete indexul curent ntr-un numr
de bloc i utilizeaz acest numr ca i index n tabela adreselor
de bloc i scrie sau citete un bloc.

40
Sisteme de Operare Linux L

5.2. Accesul la fiiere


n Linux fiierele sunt accesate prin intermediul unor
descriptori de fiiere. Fiecare proces putnd avea deschise un
anumit numr maxim de fiiere la acelai moment de timp,
implicit acest numr este 256. Prin convenie descriptorii 0, 1
i 2 sunt alocai de ctre sistem la pornire:
descriptorul 0 este utilizat ca i intrare standard
descriptorul 1 este ieire standard
descriptorul 2 este ieirea standard de eroare.

Fiecare descriptor de fiiere alocat este asociat cu un


descriptor de fiiere deschis. Un descriptor de fiiere conine
informaii referitoare la un anumit fiier, un index care
precizeaz unde va avea loc urmtorul acces n fiier, modul
de acces la fiier, i alte informaii legate de acesta.
Este posibil ca mai muli descriptori de fiiere, chiar i
aparinnd unor procese separate s indice n acelai timp spre
acelai descriptor de fiier deschis, adic informaia dintr-o
structur de decriptor deschis va fi utilizat simultan de mai
muli descriptori de fiiere.
Exist cinci apeluri care genereaz descriptori de fiiere:
creat, open, fcntl, dup i pipe. n continuare vor fi descrise
primele dou iar restul vor fi prezentate n capitolele
urmtoare.

Apelul sistem open:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int


flags);
int open(const char *pathname, int
flags, mode_t mode);

Returneaz: descriptorul de fiier sau -1 in caz de eroare.

Numrul de argumente al acestei funcii poate fi doi sau


trei. Argumentul al treilea este folosit doar la crearea de fiiere
noi. Apelul cu doua argumente este folosit pentru citirea i
scrierea fiierelor existente. Funcia returneaz cel mai mic
descriptor de fiier disponibil. Acesta poate fi utilizat in
41
Sisteme de Operare Linux L

apelurile sistem: read, write, lseek i close. IDU efectiv sau


GIDU efectiv al procesului care execut apelul trebuie s aib
drepturi de citire/scriere, funcie de valoarea argumentului
flags.
Pointerul din fiier este poziionat pe primul octet din
fiier.
Argumentul flags se formeaz printr-un SAU pe bii intre
constantele:

- O_RDONLY - Fiierul este deschis in citire.


- O_WRONLY - Fiierul este deschis in scriere.
- O_RDWR - Fiierul este deschis n adugare
(citire+scriere).
Acestea sunt definite in fiierul antet fcntl.h.

Urmtoarele constante simbolice sunt opionale:


- O_APPEND - Scrierile succesive se produc la sfritul
fiierului.
- O_CREAT - Dac fiierul nu exist el este creat.
- O_EXCL - Dac fiierul exist si O_CREAT este
poziionat, apelul open eueaz.
- O_NDELAY - La fiiere pipe i cele speciale pe bloc
sau caracter cauzeaz
trecerea n modul fr blocare att pentru apelul open ct
i pentru operaiile viitoare de I/E. In versiunile noi System V
nlocuit cu O_NONBLOCK.
- O_TRUNC Dac fiierul exist ii terge coninutul.
- O_SYNC Foreaz scrierea efectiv pe disc prin write.
ntrzie
mult ntregul sistem, dar e eficace n cazuri critice.

Argumentul al treilea, mod, poate fi o combinaie de


SAU pe bii ntre constantele simbolice:
- S_IRUSR, S_IWUSR, S_IXUSR User: read, write,
execute
- S_IRGRP, S_IWGRP, S_IXGRP Group: read, write,
execute
- S_IROTH, S_IWOTH, S_IXOTH Other: read, write,
execute
Acestea definesc drepturile de acces asupra unui fiier i
sunt definite n fiierul antet sys/stat.h.

Apelul sistem creat:


42
Sisteme de Operare Linux L

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int creat( const char *path, mode_t


mod);

Returneaz: descriptorul de fiier sau -1 in caz de eroare.

Apelul este echivalent cu:

open( path, O_WRONLY | O_CREAT |


O_TRUNC, mod);

Argumentul path specific numele fiierului, iar mod


drepturile de acces.
Dac fiierul creat nu exist, este alocat un nou inode si o
legtur spre el este plasat n directorul unde acesta a fost
creat. Proprietarul (IDU efectiv si GIDU efectiv) procesului
care execut acest apel trebuie s aib permisiunea de scriere
in director. Fiierul deschis va avea drepturile de acces
specificate de argumentul al doilea din apel. Apelul ntoarce
cel mai mic descriptor de fiier disponibil. Fiierul este
deschis n scriere iar dimensiunea sa iniiala este 0. Timpii de
acces si modificare din inode sunt actualizai.
Dac fiierul exist (este nevoie de permisiunea de
cutare n director) coninutul lui este pierdut i el este deschis
n scriere. Nu se modific proprietarul sau drepturile de acces
ale fiierului. Argumentul al doilea este ignorat.

Apelul sistem read:

Pentru a citi un numr de octei dintr-un fiier, de la


poziia curent, se folosete apelul read. Sintaxa este:

#include <unistd.h>

ssize_t read( int fd, void *buf,


size_t noct);

Returneaz: numrul de octei citii efectiv, 0 la EOF, -1


in caz de eroare.

43
Sisteme de Operare Linux L

Citete n oct octei din fiierul deschis referit de fd si i


depune n tamponul referit de buf. Pointerul n fiier este
incrementat automat dup o operaie de citire cu numrul de
octei citii. Procesul care execut o operaie de citire ateapt
pan cnd kernel-ul depune datele de pe disc in bufferele
cache. In mod uzual, kernel-ul ncearc s accelereze
operaiile de citire citind n avans blocuri de disc consecutive
pentru a anticipa eventualele cereri viitoare.

Apelul sistem write

Pentru a scrie un numr de octei ntr-un fiier, de la


poziia curent, se folosete apelul write. Sintaxa este:

#include <unistd.h>

ssize_t write( int fd, const void


*buf, size_t noct);

Returneaz: numrul de octei scrii i -1 n caz de


eroare.

Apelul scrie noct octei din tamponul buf n fiierul a


crui descriptor este fd.
Interesant de semnalat la acest apel este faptul c scrierea
fizic pe disc este ntrziat. Ea se efectueaz la iniiativa
nucleului fr ca utilizatorul s fie informat. Dac procesul
care a efectuat apelul, sau un alt proces, citete datele care
nc nu au fost scrise pe disc, kernel-ul le citete napoi din
bufferele cache. Scrierea ntrziat este mai rapid, dar are trei
dezavantaje:
a) o eroare disc sau cderea kernelului produce
pierderea datelor;
b) un proces care a iniiat o operaie de scriere nu
poate fi informat n cazul apariiei unei erori de scriere;
c) ordinea scrierilor fizice nu poate fi controlat.

Pentru a elimina aceste dezavantaje, n anumite cazuri, se


folosete fanionul O_SYNC. Dar cum aceasta scade viteza
sistemului si avnd n vedere fiabilitatea sistemelor UNIX de
astzi se prefer mecanismul de lucru cu tampoane cache.

Apelul sistem close

44
Sisteme de Operare Linux L

Pentru a disponibiliza descriptorul ataat unui fiier n


vederea unei noi utilizri se folosete apelul close.

#include <unistd.h>

int close( int fd);

Returneaza: 0 in caz de succes si -1 in caz de eroare.

Apelul nu golete bufferele kernel-ului i deoarece


fiierul este oricum nchis la terminarea procesului apelul se
consider a fi redundant.

Apelul sistem lseek

Pentru poziionarea absolut sau relativ a pointerului de


fiier pentru un apel read sau write se folosete apelul lseek.

#include <sys/types.h>
#include <unistd.h>

off_t lseek( int fd, off_t offset,


int interp);

Returneaza: un deplasament n fiier sau -1 n caz de


eroare.

Nu se efectueaz nici o operaie de I/O i nu se trimite


nici o comand controlerului de disc. Dac interp este
SEEK_SET poziionarea este fa de nceputul fiierului
(primul octet din fiier este la deplasament zero). Dac interp
este SEEK_CUR poziionarea este relativ la poziia curent.
Dac interp este SEEK_END poziionarea este fa de sfritul
fiierului.
Apelurile open, creat, write i read execut implicit lseek.
Daca un fiier este deschis folosind constanta simbolica
O_APPEND se efectueaz un apel lseek la sfritul fiierului
naintea unei operaii de scriere.

De studiat! Studiai paginile de manual pentru funciile


prezentate anterior, precum i pentru funciile nrudite cu
acestea.

45
Sisteme de Operare Linux L

De studiat! Programul urmtor realizeaz copierea unui


fiier.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc,char*argv[]){


struct stat buf;
int fdr,fdw,rv;
char buff[256];

if((argv[1] == NULL)||(argv[2] ==
NULL)){
printf("Utilizare: %s sursa
destinatie\n", argv[0]);
exit(0);
}

stat(argv[1],&buf);
if(!S_ISREG(buf.st_mode)){
perror(argv[1]);
exit(0);
}

fdr = open(argv[1], O_RDONLY);


fdw = open(argv[2],
O_CREAT|O_WRONLY, S_IREAD|S_IWRITE);
while(rv = read(fdr, &buff, 128)){
write(fdw, &buff, rv);
}

return 0;
}

Pentru compilarea programului se folosete urmtoarea


sintax:

$gcc o copiere copiere.c

Exemplul de mai sus presupune c numele fiierului ce


conine codul surs este copiere.c, numele executabilului va fi
copiere. Pentru a lansa n execuie programul vom scrie:

46
Sisteme de Operare Linux L

$./copiere fisier1 fisier2

5.3. Gestionarea directoarelor


Citirea unui director se poate face de oricine are drept de
citire asupra directorului respectiv. Scrierea unui director
poate fi fcut numai de ctre kernel.
Pentru obinerea de informaii despre fiierele nedeschise
se folosesc apelurile sistem stat, fstat i lstat:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct


stat *buf);
int fstat(int filedes, struct stat
*buf);
int lstat(const char *path, struct
stat *buf);

Returneaz: 0 in caz de reuit si -1 in caz contrar.

Pentru fiierul specificat prin path sau filedes se


completeaz o structur de informaii care poate fi accesat
prin intermediul lui buf. Cele trei funcii produc acelai
rezultat deosebirea constnd n modul de specificare a
fiierului la care se refer. Astfel stat primete ca i argument
calea ctre fiierul respectiv, fstat un descriptor de fiier, iar
lstat se refer la un link.

Structura prin care se obin informaii referitoare la


fiiere are urmtoarea form:
struct stat {
dev_t st_dev; /* numr de dispozitiv
*/
ino_t st_ino; /* inode */
mode_t st_mode; /* tip fiier-
drepturi */
nlink_t st_nlink; /* numr de
legturi */
uid_t st_uid; /* ID proprietar*/
gid_t st_gid; /* ID grup*/

47
Sisteme de Operare Linux L

dev_t st_rdev; /* tip dispozitiv


fiiere speciale */
off_t st_size; /* dimensiune
fiier*/
unsigned long st_blksize; /* dimensiunea
blocului pentru I/E */
unsigned long st_blocks; /* numrul de
blocuri alocate */
time_t st_atime; /* data ultimului
acces*/
time_t st_mtime; /* data ultimei
modificri */
time_t st_ctime; /* data ultimei
modificri a strii */
};

Tipul de fiier codificat in cmpul st_mode poate fi


determinat folosind macrourile:

- S_ISREG() Fiier obinuit (REGular file).


- S_ISDIR() Fiier director.
- S_ISCHR() Dispozitiv special in mod caracter.
- S_ISBLK() Dispozitiv special in mod bloc.
- S_ISFIFO() Fiier pipe sau fifo.
- S_ISLNK() Legtura simbolica.
- S_ISSOCK() socket?

Apelul sistem opendir

#include <sys/types.h>
#include <dirent.h>

DIR *opendir( const char *pathname);

Returneaz pointer dac este OK, NULL n caz de eroare.

struct dirent *readdir( DIR *dp);

Returneaza pointer daca este OK, NULL in caz de eroare.

int closedir( DIR *dp);

Returneaza -1 n caz de eroare.

48
Sisteme de Operare Linux L

Structura dirent definit in fiierul antet dirent.h este


dependenta de implementare. SVR4 si 4.3+BSD definesc
structura astfel nct ea conine cel puin doi membri:

struct dirent {
ino_t d_ino;
char d_name[NAME_MAX +1];
}

Structura DIR este o structur intern folosit de aceste


patru funcii pentru a pstra informaii despre directorul citit.
Primul apel readdir citete prima intrare dintr-un director.
Ordinea intrrilor dintr-un director este dependent de
implementare. De regul nu este alfabetic.

De studiat! S se realizeze un program care pentru un


director dat afieaz informaiile referitoare la toate intrrile
coninute n acel director(fiiere obinuite-fiiere speciale).

Apelul sistem link

Pentru a aduga o nou legtura la un director se


folosete apelul:

#include <unistd.h>

int link(const char *oldpath, const


char newpath);

Returneaz: 0 in caz de reuit si -1 in caz contrar.

Argumentul oldpath trebuie s fie o legtur existent, ea


furnizeaz numrul inode-ului.
Dac legturile . i .. din fiecare director sunt ignorate
structura sistemului de fiiere este arborescent. Programe
care parcurg structura ierarhica (de exemplu, comanda find)
pot fi uor implementate fr probleme de traversare multipl
sau bucla infinit. Pentru a respecta aceast cerin doar
superuser-ul are dreptul sa stabileasc o nou legtura la un
director. Crearea celei de a doua legturi la un director este
util pentru a-l putea muta n alt parte a arborelui sau pentru
a-l putea redenumi.

Apelul sistem unlink


49
Sisteme de Operare Linux L

Pentru a terge o legtur (cale) dintr-un director se


folosete apelul:

#include <unistd.h>
int unlink( const char *path);

Returneaza: 0 n caz de reuit i -1 n caz contrar.

Apelul decrementeaz contorul de legturi din inode i


terge intrarea director. Dac acesta devine 0 spaiul ocupat de
fiierul n cauz devine disponibil pentru o alt utilizare, la fel
i inode-ul. Doar superuser-ul poate s tearg un director.

De studiat! Programul urmtor listeaz coninutul unui


catalog(director).

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

int main(int argc,char*argv[]){


struct stat buf;
struct dirent *entry;
DIR *dr;

if(argv[1] == NULL){
printf("Utilizare: %s director\n
" , argv[0]);
exit(0);
}

stat(argv[1],&buf);
if(!S_ISDIR(buf.st_mode)){
perror(argv[1]);
exit(0);
}
dr = opendir(argv[1]);
while(entry = readdir(dr)){
printf("%s\n",entry->d_name);
}

return 0;
50
Sisteme de Operare Linux L

5.4. Atributele fiierelor

Pentru o gestionare eficient a fiierelor este necesar nu


numai cunoaterea unui n umr ct mai mare de date
referitoare la acestea dar i posibilitatea modificrii acestor
date.
n paragraful urmtor vor fi prezentate o serie de funcii
folosite pentru modificarea atributelor fiierelor.
Una dintre caracteristicile eseniale ale sistemului de
operare Linux este securitatea. Implementarea acesteia la nivel
de structur de fiiere se face prin precizarea pentru fiecare
fiier n parte a drepturilor de citire, scriere i execuie pentru
proprietarul fiierului, pentru grupul proprietarului i pentru
toate celelalte clase de utilizatori. Aceste drepturi pot fi
modificate cu ajutorul apelurilor sistem chmod i fchmod:

#include <sys/types.h>
#include <sys/stat.h>

int chmod(const char *path, mode_t


mode);
int fchmod(int fildes, mode_t mode);

Returneaz: 0 in caz de succes i -1 n caz contrar.


Pentru a modifica drepturile de acces la fiiere este
necesar ca procesul s aib cel puin UID(user id) efectiv
efectiv egal cu al proprietarului fiierului, dac nu drept de
superuser.
Parametrii mode pot fi precizai att n form octal ct si
sub forma unor constante simbolice de forma:
- S_ISUID suid la execuie (04000)
- S_ISGID sgid la execuie (02000)
- S_ISVTX bitul sticky (01000)
- S_IRUSR, S_IWUSR, S_IXUSR drepturile de citire,
scriere i execuie pentru proprietarul fiierului.
- S_IRGRP, S_IWGRP, S_IXGRP pentru grupul
utilizatorului.
- S_IRO, S_IWO, S_IXO pentru toi ceilali utilizatori.

Un alt element de securitate n ceea ce privete sistemul


de fiiere este apelul sistem umask:

51
Sisteme de Operare Linux L

#include <sys/types.h>
#include <sys/stat.h>

mode_t umask(mode_t mask);

Returneaz: valoarea mtii anterioare.

n momentul n care se ncearc modificarea drepturilor


de acces asupra unui fiier automat se ine cont i de valoarea
atributului mask al funciei umask dup formula mode &
~(mask).
Ex.:
int fd;
umask(0222);
if((fd=creat("tmp",0666)==-1))
printf("creat error");
system("ls -l tmp");

Rezultat: -r--r--r-- 1 student user 0 Mar 24 11:05


tmp
Drepturile de acces la fiierul tmp precizate prin
intermediul apelului sistem creat erau 0666(r w - r w - r w - )
dar prin luarea n considerare a mtii s-a obinut ca i rezultat
0222(r - - r - - r - -).
Fiecare utilizator primete la intrarea n sistem o masc,
valoarea implicit a acesteia este 022, dar interpretorul de
comenzi permite modificarea acesteia prin intermediul
comenzii umask.

Apelul sistem chown:

#include <sys/types.h>
#include <unistd.h>

int chown(const char *path, uid_t


owner, gid_t group);

Returneaz: 0 n caz de succes 1 n caz contrar.

Efecte vizibile la aplicarea acestui apel sistem se pot


obine numai dac utilizatorul are drepturi de superuser, sau
este proprietarul fiierului dar n acest caz poate modifica doar
grupul cu unul din care face parte.

52
Sisteme de Operare Linux L

REZUMAT

Caracteristicile sistemelelor de fiiere folosite n


UNIX/Linux sunt: structur ierarhic, tratare consistent a
fiierelor de date, protejarea fiierelor.

Fiierele sunt reprezentate fizic pe disc printr-o structur de


inode, structur ce conine: tipul fiierului, drepturi de
acces, numele proprietarului, informaii referitoare la dat,
dimensiune, referine ctre blocurile de date.

Accesul proceselor la fiiere se face prin intermediul unor


descriptori de fiiere, descriptori reprezentai prin
intermediul unor numere. Prin convenie descriptorii 0,1,2,
sunt alocai de ctre sistem la pornire i reprezint intrare
standard, ieire standard, ieire standard de eroare.

Funcii sistem pentru accesul la fiier:

open deschide un fiier, poate chiar crea un fiier n


anumite situaii, ntoarce un descriptor de fiier.
creat creeaz un fiier pe disc i ntoarce
descriptorul corespunztor.
read citete un numr de octei din fiierul indicat
de descriptor ntr-o zon de memorie i ntoarce
numrul de octet fizic citii.
write scrie un numr de octei n fiierul indicat de
descriptor dintr-o zon de memorie i ntoarce
numrul de octei fizic scrii.
close nchide fiierul indicat prin descriptor.
lseek poziioneaz cursorul de citire/scriere din
fiier la poziia indicat.

Funcii pentru gestionarea directoarelor:

stat/lstat/fstat completeaz o structur de date de


tip stat cu informaii referitoare la fiierul primit ca
i argument.
opendir deschide directorul primit ca i argument,
ntoarce o referin ctre directorul respectiv.
closedir nchide directorul indicat prin referin.

53
Sisteme de Operare Linux L

readdir citete informaiile referitoare la directorul


indicat prin referin i completeaz o structur de
tip dirent.
link,unlink adaug/terge o legtur ctre
directorul primit ca i argument.

Funcii sistem pentru accesul la atributele fiierelor:


chmod/fchmod modific drepturile de acces la
fiierul primit ca i argument.
chown schimb proprietarul fiierului primit ca i
argument.

NTREBRI

Descriei modul de organizare pe disc a informaiilor


aferente unui fiier.

Ce sunt descriptorii de fiiere?

Ce descriptori de fiiere speciali cunoatei?

S se realizeze un program care permite modificarea


drepturilor de acces, respectiv a proprietarului pentru un
fiier sau un director, n cazul directorului se vor face
modificrile i pentru fiierele i subdirectoarelor
coninute.

S se realizeze un program care s permit copierea unui


director, acesta presupunnd copierea inclusiv a
coninutului directorului primit ca i argument(fiiere i
subdirectoare). Apelul va fi de forma: cp_dir nume nume1.

54
Sisteme de Operare Linux L

CAP. VI PROCESE

Linux este unul din sistemele de operare cu adevrat


multi-tasking. Procesele reprezint o parte fundamental a
acestui sistem de operare, practic ele controleaz toate
activitile care se desfoar n sistem.
UNIX, sistemul iniial din care a derivat Linux, definea
un proces ca i un spaiu de adrese cu unul sau mai multe fire
de execuie care se execut n cadrul acelui spaiu de adrese i
care solicit resurse sistem pentru acele fire de execuie.
Firele de execuie vor fi tratate n capitolele urmtoare.
Deocamdat vom considera procesul ca un program care
ruleaz.
Un sistem de operare multi-tasking este un sistem de
operare care permite execuia simultan a mai multor procese.
Fiecare instan a unui program n execuie constitue un
proces.
Ca i sistem de operare multi-user, Linux permite accesul
simultan al mai multor utilizatori. Fiecare utilizator poate rula
mai multe programe sau mai multe instane ale aceluiai
program, toate la acelai moment de timp. Simultan sistemul
de operare ruleaz alte programe de gestionare a resurselor
sistemul i de control a accesului utilizatorilor la sistem.
Un program, sau un proces, care ruleaz este constituit
din urmtoarele elemente: codul program, date, variabile,
fiiere deschise si mediul de rulare. De obicei un sistem Linux
va avea biblioteci si coduri surs mprite ntre mai multe
procese, deci la un orice moment de timp pentru aceste resurse
utilizate n comun va exista o singur copie n memoria
sistem.

6.1. Identificatoare de proces PID


Fiecare proces ce ruleaz sub Linux are asociat un
identificator de proces unic numit PID (Process Identity
Numbers) prin care este cunoscut n sistem. Fiecare proces din
sistem ncepnd cu procesul 1 init are un printe a crui PID i
este cunoscut i l poate accesa.
Fiecare proces aparine unui grup de procese, fiecare
grup avnd la rndul lui un numr de identificare care este de
fapt identificatorul de proces(PID-ul) procesului printe al
grupului.

55
Sisteme de Operare Linux L

Cnd se pune problema drepturilor de acces a proceselor


la diverse fiiere se folosete un set de patru numere de
identificare. Aceste sunt cunoscute sub numele de utilizatorul
real i identificatorul de grup, i utilizatorul efectiv i
identificatorul lui de grup. Identificatorul real al unui proces
este de fapt UID(user ID) i GID(group ID) ale utilizatorului
care ruleaz procesul. Identificatorul efectiv este de obicei
acelai cu cel al utilizatorului real cu excepia cazului n care
sunt setate opiunile setuid i setgid. Dac una sau amndou
opiunile sunt activate atunci UID sau GID efectiv al
procesului vor primi valorile UID sau GID asociate fiierului
din care ruleaz procesul.
S presupunem c avem un utilizator cu UID 200 i GID
20 care dorete s ruleze programul /usr/bin/passwd. Acest
program are UID 0 (root) i GID 1 i are de asemenea set bitul
setiud. Cnd este rulat programul procesul asociat va avea ID-
ul utilizatorului real 200, ID-ul grupului real la 20, ID-ul
utilizatorului efectiv 0, iar ID-ul grupului efectiv 20.
Id-ul real est folosit pentru a identifica utilizatorul pentru
care este rulat un proces. ID-urile efective sunt folosite pentru
a putea realiza o sortare a permisiunilor i privilegiilor pe care
procesele le au la accesarea unui fiier. Acest lucru se
realizeaz pe baza urmtorului algoritm:
1. Dac ID-ul utilizatorului efectiv al procesului
este 0 (root) atunci procesului nu i se aplic nici o restricie, n
caz contrar treci la pasul 2.
2. Dac ID-ul utilizatorului efectiv al procesului
este acelai cu ID-ul utilizator al fiierului atunci procesului i
se acord accesul la fiier n conformitate cu drepturile de
acces ale proprietarului acelui fiier. Dac nu treci la pasul 3.
3. Dac ID-ul grupului efectiv al procesului este
acelai cu ID-ul de grup al fiierului atunci procesului i se
acord accesul la fiier n conformitate cu drepturile de acces
ale grupului fiierului. Dac nu treci la pasul 4.
4. Accesul la fiier este acordat pe baza drepturilor
de acces ale celorlali utilizatori (others).
Toate aceste numere de identificare se pot obine cu
ajutorul urmtoarelor funcii:
uid_t getuid(void) // obine ID-ul utilizatorului real
uid_t getgid(void) // obine ID-ul grupului real
uid_t geteuid(void) // obine ID-ul utilizatorului efectiv
uid_t getegid(void) // obine ID-ul grupului efectiv
uid_t getpid(void) // obine ID-ul procesului
56
Sisteme de Operare Linux L

uid_t getppid(void) // obine ID-ul procesului printe


uid_t getpgrp(void)// obine ID-ul de grup al procesului

6.2. Crearea proceselor utiliznd fork


Vom considera c un proces este construit din trei pri
separate conform figurii urmtoare:

Segmentul de
text
Program

Proces Segmentul cu
date utilizator

Segmentul de
date sistem

Segmentul de text conine instruciunile n cod main


care urmeaz s fie executate. Acest segment poate fi accesat
numai pentru citire(deci codul surs din aceast parte nu poate
fi modificat), ceea ce permite utilizarea acestui segment de
ctre dou sau mai multe procese din sistem care ruleaz
acelai program. De exemplu dac mai muli utilizatori ruleaz
aceeai versiune de interpretor de comenzi (de ex. bash), n
memoria principal va fi o singur copie a programului pe
care o folosesc n comun toi utilizatorii.
Segmentul de date utilizator conine toate datele cu care
opereaz un proces pe parcursul execuiei sale, aceste date
includ i variabilele ce vor fi utilizate de proces. Datele din
acest segment sunt modificabile i n plus fiecare proces are
cte un segment de date unic.
Segmentul de date sistem conine elementele
caracteristice mediului de lucru n care ruleaz un program.
Acest segment realizeaz distincia ntre programe i procese.
Programul are un caracter static, este localizat pe disc, i este
constituit dintr-un set de instruciuni i date folosite pentru
iniializarea segmentelor text i de date ale proceselor.
Procesul are un caracter dinamic iar execuia sa necesit
interaciunea ntre segmentele de date,text i sistem.

57
Sisteme de Operare Linux L

Sub Linux, pentru crearea de noi procese se folosete


apelul sistem fork:

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

Practic acest apel realizeaz un nou proces, numit proces


fiu, iar procesul care a apelat fork devine proces printe a
noului proces creat. Cele dou procese sunt identice n termeni
de coninut al segmentelor lor de date i text i aproape
identice n ceea ce privete segmentele sistem. Singurele
diferene ntre astfel de procese apar la nivelul unor atribute
care trebuie s fie diferite (cum ar fi PID care trebuie s fie
unic pentru fiecare proces n parte). Odat ce procesul fiu a
fost creat, ambele procese,printe i fiu, i continu execuia
din interiorul apelului fork. Adic urmtoarea aciune pentru
fiecare proces n parte este s prseasc fork, fiecare
returnnd o valoare diferit.

Procesul iniial

fork()

ntoarce ntoarce
un nou PID 0

Procesul Procesul
printe fiu

Fig 6.1 Fork

58
Sisteme de Operare Linux L

Dou procese virtual identice care ruleaz simultan se pot


dovedi utile numai n situaia n care acestea realizeaz aciuni
diferite. n aceast situaie este nevoie de un mecanism prin
care s se realizeze diferenierea ntre cele dou procese. Acest
lucru se realizeaz relativ simplu prin faptul c fork returneaz
valori diferite celor dou procese. Astfel procesului printe i
returneaz PID-ul noului proces fiu creat, n timp ce
procesului fiu i returneaz 0. n mod normal alocarea ID-
urilor pentru procese ncepe cu 1 pentru procesul init. Vom
avea n continuare un exemplu de program care creeaz un
nou proces:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

main(){
pid_t val;
printf("PID inainte de fork:
%d\n",(int)getpid());
if(val=fork())
printf("PID parinte:
%d\n",(int)getpid());
else
printf("PID fiu:
%d\n",(int)getpid());
}

La rularea programului se vor genera trei linii de ieire.


Prima va afia valoarea PID-ului procesului nainte de apelul
fork, a doua valoarea PID a procesului printe dup apelul
fork, iar a treia va afia valoarea PID a procesului fiu. Un
exemplu de ieire obinut la rularea programului:
PID nainte de fork: 16953
PID printe: 16953
PID fiu: 16954
Dup execuia apelului fork majoritatea atributelor
procesului printe sunt disponibile nemodificate procesului
fiu. Principalele atribute sunt:
- apartenena la grupul de procese.
- terminalul n care ruleaz(dac acesta exist).
- UID i GID reale i efective.
- directorul de lucru curent.
- masca pentru crearea fiierelor(umask).

59
Sisteme de Operare Linux L

n puls toi descriptorii de fiiere care n procesul printe


sunt asociai cu fiiere deschise vor fi duplicai n procesul fiu.
Adic att descriptorii de fiiere ai procesului fiu ct i ai
procesului printe vor indica spre aceeai descriptori de fiiere
deschise.

6.3. Apelul sistem exec

Dac se utilizeaz interpretorul de comenzi pentru a rula


o comand (ex. ls) pentru rularea ei acesta va apela la un
anumit moment fork. Se pune problema cum se poate ca n
procesul fiu n loc de o copie a interpretorului de comenzi s
fie rulat ls?
Soluia n acest caz este utilizarea apelului sistem exec.
De fapt sunt mai multe versiuni ale acestui apel sistem dar
toate realizeaz n esen acelai lucru. Acest apel sistem
reprezint de fapt modalitatea de rulare de programe sub
Linux. Acest lucru l realizeaz prin nlocuirea segmentelor de
date i text ale procesului care apeleaz exec cu cele ale
programului a crui nume a fost transmis ca i argument. O
alt problem ce ar putea aprea este faptul c majoritatea
programelor ce sunt rulate n mod curent din linia de comand
primesc i parametrii sau argumente, deci apelul exec trebuie
s acopere i aceste aspecte. Acest lucru se poate realiza n C
prin argumentele argc i argv, deci i exec trebuie s i le
transmit programului ntr-o form asemntoare.
Cea mai simpl versiune de exec este execl. Prototipul
acestei funcii este:

#include <unistd.h>
int execl( const char *path, const
char *arg, ...);

unde path este calea complet ctre programul care


urmeaz s fie executat, acesta este urmat de o list variabil
de argumente ce trebuie transmise programului. Aceast list
trebuie terminat cu NULL(0). n continuare vom avea un
exemplu de program care s ruleze comanda ls l:
#include <stdio.h>
#include <unistd.h>

main(){
execl("/bin/ls","ls","-l",0);

60
Sisteme de Operare Linux L

printf("terminat cu erori.");
}

Primul parametru pentru execl este calea complet pentru


programul ce urmeaz a fi rulat, acesta este fiierul care va fi
rulat, de aici se obin i drepturile de acces la fiier(dac are
sau nu drept de execuie) restul parametrilor sunt folosii
pentru lista de argumente argv. n exemplu ls va fi argv[0], iar
l argv[1].
Atenie! Din apelurile exec nu se revine. Deci mesajul
terminat cu erori din exemplu nu va fi afiat. Singura excepie
este cazul n care a aprut o eroare la apelul exec n aceast
situaie se revine la vechiul proces i se returneaz i codul de
eroare (n aceast situaie va fi afiat mesajul terminat cu
erori).
n plus pentru a face toi aceti parametrii disponibili
noului program apelurile exec transmit o valoare i pentru
variabila:

extern char **environ;

Aceast variabil are acelai format ca i variabila argv


diferena fiind c prin variabila environ se transmit valori ale
variabilelor aparinnd mediului de lucru ale procesului
original.
Acest apel sistem mai conine i alte versiuni singurele
diferene constnd n modul de apelare, funcional toate se
comport la fel:

int execlp( const char *file, const


char *arg, ...);
int execle( const char *path, const
char *arg , ..., char* const envp[]);
int execv( const char *path, char
*const argv[]);
int execvp( const char *file, char
*const argv[]);
int execve (const char *filename,
char *const argv [],char *const envp[]);
n cazul ultimelor trei apeluri argumentele ce trebuie
transmise programelor sunt organizate sub forma unei liste.
Ca i n cazul apelului fork majoritatea atributelor sunt
pstrate n urma unui apel exec. Acest lucru se datoreaz
faptului c segmentul sistem rmne intact n urma unui apel

61
Sisteme de Operare Linux L

exec. Cel mai important aspect este acela c descriptorii de


fiiere asociai cu descriptorii de fiiere deschise rmn
valabile i dup apelul lui exec. Singura excepie este un
marcaj (flag) asociat descriptorilor de fiiere (nu este asociat
descriptorilor de fiiere deschise) numit close on exec. Dac
acest flag nu este activat atunci descriptorul de fiier respectiv
este valabil i dup apelul exec. Modificarea acestui flag se
poate face prin intermediul apelului sistem fcntl.

6.4. Apelurile sistem wait i exit


Se poate pune problema ce face procesul printe n timp
ce procesul fiu ruleaz. Pe parcursul rulrii procesului fiu
procesul printe fie ateapt ca acesta s i termine execuia,
fie i continu execuia.
n cazul interpretorului de comenzi de exemplu, alegerea
rmne la latitudinea utilizatorului. n mod normal
interpretorul de comenzi ateapt, pentru fiecare comand
introdus din linia de comenzi, pn la terminarea execuiei
acesteia. Dar utilizatorul are posibilitatea indica
interpretorului de comenzi s nu mai atepte terminarea
comenzii i s i reia execuia imediat prin adugarea
caracterului & la sfritul comenzii.
Pentru ca procesul printe s atepte terminarea execuiei
unui proces fiu, procesul printe trebuie s execute apelul
sistem wait(). Prototipul acestui apel sistem este urmtorul:

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status)

Apelul sistem wait returneaz PID-ul procesului fiu ce i-


a ncheiat execuia. Parametrul care l primete apelul sistem
wait este o referin ctre o locaie care va primi valoarea
strii de terminare a procesului fiu.
Cnd un proces i-a terminat execuia el va executa
apelul sistem call fie n mod explicit fie indirect prin
intermediul unei biblioteci. Prototipul apelului sistem exit este
urmtorul:

#include <stdlib.h>
void exit(int status)

62
Sisteme de Operare Linux L

Acest apel sistem primete ca i argument un parametru


de stare care va fi transmis procesului printe prin intermediul
unei locaii referit de parametrul apelului wait.
Apelul sistem wait poate mai multe informaii referitoare
la starea procesului fiu la terminare prin intermediul valorii de
stare. Pentru extragerea acestor informaii se poate folosi un
macro numit WEXITSTATUS. Ex:

#include <sys/wait.h>
int statval, exstat;
pid_t pid;
pid = wait(&statval);
exstat = WEXITSTAUS(statval);

Schema bloc care descrie funcionarea a dou procese,


unul printe care ateapt terminarea execuiei procesului fiu
i a procesului fiu care folosete apelul sistem exec i a crui
execuie se termin cu apelul exit, arat astfel:

fork

exec wait

Noul program
Execuia printelui
ruleaz
este suspendat

exit

Execuia procesului
printe este reluat
Fig 6.2 Proces printe n ateptare

O alt versiune a apelului sistem wait este waitpid cu


urmtorul prototip:

#include <sys/types.h>

63
Sisteme de Operare Linux L

#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status,
int options);

Prin parametrul options ofer faciliti suplimentare. De


exemplu n urma unui apel waitpid procesul printe nu i
suspend execuia dac nici un proces fiu nu are disponibil
starea de ieire.
Pentru parametrul pid avem urmtoarele posibiliti:
- < -1 ateapt ncheierea execuiei oricrui proces fiu a
crui ID de grup este egal cu pid.
- -1 comportament identic cu pid.
-0 ateapt ncheierea execuiei oricrui
proces fiu a crui ID de grup este egal cu ID-ul de grup al
procesului.
- > 0 ateapt ncheierea execuiei procesului fiu a
crui PID este egal cu pid.
Exist posibilitatea ca un proces fiu s i ncheie
execuia nainte ca procesul printe s apeleze wait. n aceast
situaie procesul fiu va intra ntr-o stare numit zombie, n
care toate resursele ocupate de procesul fiu au fost eliberate cu
excepia structurii de date care conine starea sa de ieire.
Cnd procesul printe efectueaz apelul wait, starea de ieire
este transmis procesului printe iar resursele ocupate cu
structura de date a procesului fiu pot fi eliberate.

REZUMAT

n cadrul UNIX/Linux un proces este un spaiu de adrese


cu unul sau mai multe fire de execuie n cadrul acelui
spaiu de adrese i care solicit resurse sistem pentru acele
fire de execuie.

Un sistem de operare multitasking este un sistem de operare


ce permite execuia simultan a mai multor procese, fiecare
instan a unui program n execuie constitue un proces.

Un proces este constituit din urmtoarele componente:


codul program, date, variabile, descriptori de fiiere, mediu
de rulare.

Fiecare proces ce ruleaz n sistemul de operare are


asociat un identificator de proces unic numit PID. PID-ul

64
Sisteme de Operare Linux L

unui grup de procese este dat de PID-ul procesului printe.

Pentru a se stabili dreptul de acces la diverse resurse


pentru un proces se folosesc patru identificatori: numele
utilizatorului real, identificatorul de grup, utilizatorul
efectiv si identificatorul lui de grup.

Putem considera c un proces este constituit din trei


segmente: text, date utilizator, date sistem. Pentru a crea un
nou proces se folosete apelul fork, pentru noul proces
segmentele de date utilizator i text sunt identice cu cele
originale singurele diferene vor apare la segmentul de date
sistem(ex PID).

Dup execuia apelului fork majoritatea atributelor


procesului printe sunt disponibile nemodificate procesului
fiu. Principalele atribute sunt:
apartenena la grupul de procese.
terminalul n care ruleaz(dac acesta exist).
UID i GID reale i efective.
directorul de lucru curent.
masca pentru crearea fiierelor(umask).

n puls toi descriptorii de fiiere care n procesul printe


sunt asociai cu fiiere deschise vor fi duplicai n procesul
fiu. Adic att descriptorii de fiiere ai procesului fiu ct i
ai procesului printe vor indica spre aceeai descriptori de
fiiere deschise.

Apelul sistem exec permite rularea unor comenzi (alte


programe) prin nlocuirea segmentelor de date utilizator i
text curente cu cele ale programului ce urmeaz a fi rulat.

Apelurile sistem wait i exit permit exercitarea unui control


asupra cursului normal al execuiei programului. Prin
apelul wait procesul printe va atepta ncheierea execuiei
unui fiu, i va prelua starea de ieire i i va continua
execuia la rndul lui. Prin apelul exit programul i poate
ncheia execuia la momentul dorit.

NTREBRI

Ce este un proces?
65
Sisteme de Operare Linux L

Ce este PID?

Prin ce se difereniaz procesele rezultate n urma apelului fork?

Cum se poate lansa n execuie un program sistem?

Poate afla procesul printe dac execuia procesului fiu s-a


terminat cu succes sau nu?

Descriei modul de organizare pe disc a informaiilor


aferente unui fiier.

Ce sunt descriptorii de fiiere?

S se realizeze un program in C care s creeze trei procese


(inclusiv printele). Fiecare proces i afieaz PID-ul, iar
procesul printe numr de la 1-50, primul proces fiu de la
50-100, iar al doilea proces fiu afieaz literele din alfabet.

S se realizeze un program C care citete un fiier de pe


disc (numele fiierului este primit ca i argument din linia
de comand) n fiier se gsete numele unei comenzi,
programul va executa comanda respectiv prin pornirea
unui nou proces cu fork. (vezi exec)

66
Sisteme de Operare Linux L

CAP. VII Comunicarea ntre procese

Fiecare proces opereaz n propriul su spaiu de adrese


virtuale, iar de evitarea interferenelor dintre procese se ocup
sistemul de operare. Implicit un proces nu poate comunica cu
un alt proces numai dac face uz de diverse mecanisme de
comunicare gestionate de kernel(nucleul sistemului de
operare). Exist totui diverse situaii n care procesele trebuie
s coopereze, s mpart resurse comune sau s i
sincronizeze aciunile. Exist mai multe metode de
comunicare ntre procese:
fiiere este cel mai simplu mecanism de comunicare
interproces. Un proces scrie ntr-un fiier iar cellalt
proces citete din fiier.
semnale sunt utilizate pentru a semnala asincron
evenimente ntre procese
pipes un pipe conecteaz ieirea standard a unui
proces cu intrarea standard a altuia.
cozi de mesaje este o list legat de spaiul de
adresare a kernel-ului
semafoare sunt contoare utilizate pentru a gestiona
accesul la resursele utilizat n comun de mai multe
procese Cel mai des sunt folosite ca i mecanism de
blocare a unei resurse pentru a preveni accesul simultan
a mai multor procese la o anumit resurs.
Sockets- permit realizarea de conexiuni ntre procese
locale sau n reea.
7.1. Semnale
Una dintre cele mai vechi metode de comunicare ntre
procese n sistemele de tip UNIX(Linux) se bazeaz pe
semnale. O caracteristic important a acestor semnale este c
ele sunt asincrone, adic un proces poate primi un semnal la
orice moment i trebuie s fie pregtit s i rspund. Dac un
semnal survine pe perioada execuiei unui apel sistem, acesta
se ncheie prin returnarea unui cod de eroare(EINTR) i este
sarcina procesului s refac apelul ntrerupt. Exist mai multe

67
Sisteme de Operare Linux L

tipuri semnale i fiecare putnd fi accesat utiliznd pe baza


unui nume simbolic. Fiecare nume unic reprezint o abreviere
ce ncepe cu SIG (de ex. SIGINIT). O list complet a setului
de semnale din sistem se poate obine prin intermediul
comenzii kill l. n continuare se prezint o list cu numrul i
numele simbolic a semnalelor folosite n mod uzual:
1) SIGHUP terminal nchis (oprete procesul).
2) SIGINT ntrerupere de la tastatur (oprete
procesul).
3) SIGQUIT oprete procesul (oprete procesul i
creeaz un fiier core).
4) SIGILL aciune ilegal (oprete procesul i
creeaz un fiier core).
5) SIGTRAP 6) SIGIOT 7) SIGBUS 8) SIGFPE
9) SIGKILL termin procesul.
10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM
17) SIGCHLD procesul fiu oprit sau terminat
18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO
30) SIGPWR

De studiat! Consultai pagina de manual pentru signal din


seciunea 7.

Fiecare tip de semnal are asociat o aciune ce va fi


executat de nucleul sistemului de operare (kernel) asupra
procesului cnd procesul primete semnalul respectiv.
Implicit un proces poate trata un semnal n urmtoarele
moduri:
i ncheie execuia
Ignor semnalul dou semnale nu pot fi ignorate:
SIGKILL care termin execuia procesului i SIGSTOP care
i oprete execuia.
Reface aciunea implicit a semnalului.

La primirea unui semnal un proces poate alege modul de


tratare a acestuia, o alternativ este s rmn la aciunea
implicit, iar tratarea va fi fcut de kernel. De exemplu
68
Sisteme de Operare Linux L

semnalul SIGSTOP va modifica starea curent a procesului


care l primete n STOPED i apoi va solicita
kernelului(schedulerului) sau ruleze un alt proces. Alternativ
procesul poate specifica pentru un anumit semnal propria
rutin de tratare. Aceast rutin va fi apelat de fiecare dat
cnd este generat semnalul respectiv, iar adresa acestei este
reinut n structura sigaction. Apelul acestei rutine va fi fcut
de ctre kernel, deci procesul va rula n mod kernel pe
parcursul tratrii semnalului.
Nu orice proces din sistem poate trimite semnal oricrui
alt proces, acest lucru este valabil numai pentru procesele ce
aparin kernelului sau superutilizatorului (root). Procesele
normale pot trimite semnale numai proceselor cu acelai UID
i GID, sau proceselor din acelai grup.
Generarea unui semnal se realizeaz prin setarea bit-ului
corespunztor din structura task_struct. Dac procesul nu a
blocat semnalul i se afl n ateptare dar este ntreruptibil
atunci starea acestuia este modificat n Running, iar procesul
este trecut n coada de execuie. n acest fel procesul va fi luat
n calcul ntre procesele care vor primi timp de procesor.
Semnalele nu sunt transmise proceselor imediat ce sunt
generate, ele trebuie s atepte pn n momentul n care
procesul ruleaz din nou. De fiecare dat cnd un proces
prsete un apel sistem sunt verificate cmpurile sale signal
i blocked , iar dac pentru respectivul proces sunt semnale
neblocate ele pot fi acum transmise procesului.
La nivel de interpretor de comenzi o modalitate de
trimitere a semnalelor ctre procese este prin intermediul
comenzii kill. Un exemplu clasic de terminare forat a
execuiei unui proces este urmtorul:

ps | grep processname
kill -9 PID

n cele ce urmeaz se va face o scurt prezentare a celor


mai importante apeluri sistem folosite pentru lucrul cu
semnale.

Apelul sistem signal:


n Linux sunt disponibile mai multe apeluri sistem ce
pot fi utilizate pentru gestionarea semnalelor. Apelul sistem
signal poate fi ntlnit i la celelalte versiuni de UNIX.
Prototipul acestui apel sistem este urmtorul:

69
Sisteme de Operare Linux L

#include <signal.h>
void (*signal(int signum, void
(*sighandler)(int)))(int);

La prima vedere acest prototip pare complicat dar la o


analiz mai atent se poate observa c sunt necesari doar doi
parametrii:
signum un numr ntreg care indic semnalul a crui
tratare va fi rescris.
handler o referin ctre o funcie care va fi folosit ca
rutin de tratare pentru semnalul respectiv.
Valoarea returnat de signal() este o referin ctre o
funcie care primete ca i parametru un singur ntreg i nu
returneaz nimic (void). Un exemplu de utilizare a acestui apel
sistem

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig){


printf("CTRL-C\n");
(void)signal(SIGINT,handler);
}

void main(void){
(void)signal(SIGINT,handler);
while(1){
printf("Hello World!\n");
sleep(1);
}
}

Acest segment de cod afieaz la terminal, n bucl


infinit, mesajul Hello World!. La orice tentativ de a opri
programul de la tastatur prin secvena CTRL-C semnalul
SIGINT va fi prins de program, ca rutin de tratare a
semnalului va fi folosit funcia handler.
Legtura ntre semnal (SIGINT) i rutina de tratare
(handler) se realizeaz la apelul din funcia main. Dup
realizarea acestei legturi orice semnal SIGINT primit de
proces va determina execuia rutinei de tratare (handler).
Aceast funcie doar afieaz mesajul CTRL-C, totodat

70
Sisteme de Operare Linux L

reface legtura ntre semnal i funcie. Aceast refacere a


legturii ntre semnal i rutina de tratare este necesar datorit
faptului c dup primirea unui semnal se revine la tratarea
implicit (terminarea execuiei programului)., ceea ce nu este
de dorit.
Pentru acest tip de apel sistem apare o problem legat
de un scurt interval de timp n care tratarea semnalului se face
n mod implicit, i dac pe parcursul acestui interval de timp
survine un semnal acesta va fi tratat n mod implicit, adic va
determina ncheierea execuiei programului.

Apelul sistem sigaction:


Acest apel sistem este conform standardelor POSIX,
este mai complex, dar nltur problema aprut anterior.
Conform acestor specificaii fiecare proces are asociat
cte o masc, care precizeaz setul de semnale care nu pot fi
livrate procesului la momentul curent. Dac totui procesul
primete un semnal ce aparine acestei liste el va fi pus ntr-o
coad de ateptare i va fi transmis procesului atunci cnd
blocajul este nlturat.
Cnd un semnal este generat, el este automat adugat la
masca de semnale a procesului int, astfel nct orice instan
viitoare a acestui semnal va fi blocat pn la servirea
semnalului curent.
Prototipul pentru acest apel sistem este urmtorul:

#include <signal.h>
int sigaction(int signum,const
struct sigaction *act, struct sigaction
*oldact);

n locul referinei ctre o funcie n acest caz se transmite


ca i parametru o referin ctre o structur numit struct
sigaction. Aceasta are urmtoarea structur:

struct sigaction {
void (*sa_handler)(int);
void(*sa_sigaction)(int,
siginfo_t *,void*);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}

71
Sisteme de Operare Linux L

Dup cum se poate observa referina ctre rutina de


tratare a fost introdus n aceast structur. Totodat structura
mai conine i un cmp sa_mask acesta funcioneaz ca i o
masc de semnale suplimentar, i este valabil pe parcursul
execuiei rutinei de tratare a semnalului. Cmpul sa_flags se
interpreteaz la nivel de bit. Dintre aceste flag-uri cele mai
semnificative sunt:
SA_ONESHOT semnalul va fi tratat n mod implicit.
SA_NOMASK - ignor cmpul sa_mask din structura
sigaction.
Ambele flag-uri vor fi active dac pentru se folosete
apelul signal n loc de sigaction. Pentru obinerea de
informaii adiionale s-a introdus un parametru suplimentar
siginfo_t.
Spre deosebire de signal, valoarea returnat de sigaction
nu include o referin ctre vechea rutin de tratare. n schimb
primete un nou parametru. Acesta este o alt referin ctre o
structur de tipul sigaction, iar completarea acestei structuri o
va face apelul sigaction() bazndu-se pe vechea structur
sigaction.

Apelul sistem kill:


n marea majoritate a cazurilor mai importante sunt
semnalele generate de apariia unor evenimente: erori
hardware, modificarea strii unui proces sau intervenia
utilizatorului de la consol. n afar de aceste situaii exist
posibilitatea ca un proces s trimit semnale n mod deliberat
unui alt proces, utiliznd apelul sistem kill, dac are
permisiunile corespunztoare. Prototipul acestui apel sistem
este urmtorul:

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

Unde prin sig se precizeaz semnalul care va fi trimis, iar


pid are urmtoarele sensuri:
pid > 0 semnalul sig va fi trimis procesului pentru
care PID = pid.
pid = 0 semnalul sig va fi trimis tuturor proceselor cu
acelai PID ca i procesul ce a fcut apelul.

72
Sisteme de Operare Linux L

pid = -1 semnalul sig va fi trimis tuturor proceselor


din sistem cu excepia procesului init i a procesului ce a fcut
apelul.
pid < -1 trimite semnalul sig tuturor proceselor pentru
care GID=pid.

Apelul sistem alarm:

#include <unistd.h>
unsigned int alarm(unsigned int
seconds);

Fiecare proces are asociat un ceas pe care l poate folosi


pentru a-i trimite semnale de tipul SIGALRM dup depirea
unui anumit interval de timp. Apelul sistem alarm() primete
un singur parametru care este intervalul de timp, n secunde,
dup care se va genera semnalul.

7.2. Pipes
n Linux, majoritatea intrepretoarelor de comenzi accept
redirectarea. Un exemplu clasic n acest sens este secvena de
comenzi:

$cat /etc/passwd | wc -l

Rezultatul acestei secvene de comenzi este c ieirea


standard a comenzii cat devine intrare standard pentru
comanda wc. Deci un pipe este o metod prin care se poate
realiza conectarea ieirii standard a unui proces cu intrarea
standard altuia. Pipe-urile sunt una dintre cele mai vechi
metode utilizate la comunicarea ntre procese. Comunicaia
realizat ntre dou procese se poate realiza ntr-o singur
direcie, de unde i denumirea de unidirecionale (half-
duplex). Nici unul dintre procesele implicate nu sunt
contiente de aceste redirectri i este sarcina intrepretorului
de comenzi s gestioneze aceste pipe-uri.
Cnd un proces creeaz un pipe, nucleul (kernelul) va
genera doi descriptori de fiiere care urmeaz s fie utilizai
mpreun cu pipe-ul. Unul dintre descriptori este folosit pentru
a crea o cale de intrare (scriere) n pipe, iar cellalt pentru a
crea o cale de ieire. n acest punct utilizarea unui pipe nu are
o utilitate practic prea mare atta vreme ct procesul poate

73
Sisteme de Operare Linux L

comunica numai cu el nsui. O reprezentare a procesului i a


kernelului dup ce a fost creat un pipe:

intrare
Proces Nucleu
iesire (kernel)

Fig. 7.1 Comunicare proces nucleu.

Din diagrama anterioar se poate observa modul de


conectare a descriptorilor de fiiere. Un proces poate trimite
date (scrie) prin fd0, i le poate obine prin fd1. La nivel de
pipe transferul datelor se face n interiorul kernelui, iar pipe-
ul este reprezentat prin intermediul unui inode, care la rndul
lui aparine tot kernel-ului i nu este legat de nici un sistem
fizic de fiiere. Din ceea ce s-a prezentat pn acum utilizarea
pipe-urilor nu ar avea nici un sens deoarece n aceast situaie
un pipe ar fi folosit doar pentru comunicarea in cadrul unuia i
acelai proces. Dar situaia se schimba daca dup crearea pipe-
ului are loc i crearea unui proces prin intermediul apelului
sistem fork. n aceast situaie procesul printe va moteni toi
descriptorii de fiiere deschii pentru procesul printe, i
bazndu-ne pe acest mecanism avem bazele comunicrii
intreproces (mai precis ntre procese aflate n relaia printe-
fiu).
Ceea ce s-a prezentat pn acum a fost doar o
prezentare de ansamblu, iar exemplul a fost la nivelul
interpretorului de comenzi. Pentru a utiliza facilitile oferite
de pipe-uri n cadrul limbajului de programare C.
Apelul sistem pipe
Este utilizat pentru crearea unui fiier de tip pipe.

#include<unistd.h>
int pipe(int pfd[2]);

Returneaz 0 n caz de succes i -1 n caz de eroare.


Argumentul pfd este un tablou cu dou elemente care
dup execuia funciei va conine:
Descriptorul de fiier pentru citire pfd[0];

74
Sisteme de Operare Linux L

Descriptorul de fiier pentru scriere pfd[1];


Rolul acestui apel sistem este de a crea o cale de
comunicaie, de citire i scriere, ntre dou procese. Aceast
cale de comunicaie se bazeaz pe cei doi descriptori de fiier
care sunt returnai, de apelul sistem pipe, n tabloul pfd. Astfel
din pfd[0]se citesc datele, iar n pfd[1] se scriu datele.
Aa cum s-a mai precizat comunicarea prin intermediul
pipe-urilor este specific comunicrii ntre procese, deci n
conjuncie cu apelul sistem fork. Un exemplu clasic este
situaia n care se dorete ca procesul printe s transmit un
mesaj procesului fiu. Programul C corespunztor va realiza
urmtorii pai:
Apelul sistem pipe creeaz descriptorii de
citire/scriere.
Apelul sistem fork se creeaz procesele printe i fiu,
cei doi descriptori se vor regsi n ambele procese.
Procesul printe va nchide pfd[0] descriptorul de citire.
Procesul fiu va nchide pfd[1] descriptorul de scriere.
Se realizeaz transferul mesajului prin intermediul
descriptorilor de fiier rmai deschii.
nchiderea descriptorilor neutilizai este necesar din
cauz c descriptorii de fiiere sunt aceeai att n procesul
printe ct i n procesul fiu, situaie datorat apelului sistem
fork. Programul C corespunztor este prezentat n cele ce
urmeaz.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>

int main(void){

int pfd[2], nr_bytes, status;


pid_t pid_fiu;
char mesaj[] = "Hello world!";
char readbuffer[80];

pipe(pfd);

if((pid_fiu = fork()) == -1)

75
Sisteme de Operare Linux L

{
perror("fork");
_exit(1);
}

if(pid_fiu == 0)
{

//procesul fiu nchide


descriptorul de scriere
close(pfd[1]);

//citete mesajul din pipe


nr_bytes = read(pfd[0], readbuffer,
sizeof(readbuffer));

//i l afiseaz
printf("Received string: %s\n",
readbuffer);

}else{

//procesul printe nchide


descritorul de citire
close(pfd[0]);

//trimite mesajul prin descriptorul


de scriere
write(pfd[1], mesaj, (strlen(mesaj) +
1));
wait(status);
sleep(1);
_exit(0);
}

return(0);

Apelul sistem dup i dup2


Este utilizat pentru a duplica un descriptor de fiier.

#include <unistd.h>
int dup(int fd);
int dup2(int fd, int nfd);

76
Sisteme de Operare Linux L

Returneaz noul descriptor n caz de succes, sau -1 n caz


de eroare.
Atenie! Cu dup2 vechiul descriptor este nchis.
Acest apel sistem creeaz un nou descriptor de fiier pe
lng cel existent, descriptorul (numrul) returnat este cel mai
mic disponibil. O utilizare imediat a acestui apel sistem ar fi
posibilitatea redirectrii intrrii/ieirii standard.
Apelul dup dei vechiul i noul descriptor pot fi
utilizate pe rnd, de obicei una dintre cile de comunicare
standard sunt nchise.
Dac vom considera:

.
.
pid_fiu = fork();

if(pid_fiu == 0)
{
//nchide intrarea standard a procesului
fiu
close(0);

//duplic partea de intrare a pipe-ului cu


intrarea standard
dup(pfd[0]);
execlp("sort", "sort", NULL);
.
.
}

Deoarece descriptorul de fiier 0 (intrarea standard) a fost


nchis, apelul dup foreaz descriptorul de intrare a pipe-ului
ca intrare standard, apoi se realizeaz apelul sistem execlp()
care suprascrie segmentul de cod a procesului fiu cu
programul de sortare. Pentru c noul program executat
motenete cile de comunicare ale procesului din care a fost
creat el motenete de fapt ca i cale de intrare standard
descriptorul de citire din pipe. Astfel tot ce trimite procesul
printe iniial prin pipe ajunge la programul de sortare.
Apelul dup2 acest apel include, att apelul de
duplicare a cii de comunicare standard ct i operaia de
nchidere a cii de comunicare standard, ntr-un singur apel
sistem. n plus acest apel sistem este garantat a fi atomic, adic
nu va fi acceptat nici o cerere de ntrerupere (semnal) din

77
Sisteme de Operare Linux L

partea sistemului pe parcursul execuiei acestui apel. n cazul


apelului sistem dup() trebuia realizat operaia close nainte.
Adic aveam dou apeluri sistem, ceea ce crea un anumit grad
de vulnerabilitate, dat de intervalul dintre cele dou apeluri.
Dac sosete un semnal ntre cele dou apeluri operaia de
duplicare nu mai are loc.
n acest caz vom avea:

.
.
pid_fiu = fork();

if(pid_fiu == 0)
{
//nchide i duplic
intrarea standard
dup2(0, pfd[0]);
execlp("sort", "sort",
NULL);
.
.
}
REZUMAT

Fiecare proces opereaz n propriul su spaiu de adrese


virtuale, de evitarea interferenelor ntre procese se ocup
sistemul de operare. Implicit un proces poate comunica cu alt
proces numai prin intermediul nucleului. Metode de
comunicare ntre procese:
Fiiere.
Semnale.
Pipes.
Cozi de mesaje.
Semafoare.
Sockets.

Semnalele sunt metode asincrone de comunicare, un proces


poate primi un semnal n orice moment al execuiei li trebuie
s fie pregtit s i rspund.

Fiecare tip de semnal are asociat o aciune ce va fi


executat de nucleul sistemului de operare asupra procesului
n momentul n care procesul primete semnalul respectiv. Un
proces poate trata un semnal n urmtoarele moduri: ncheie
78
Sisteme de Operare Linux L

execuia, ignor semnalul (excepie fac SIGKILL i


SIGSTOP), reface aciunea implicit a semnalului.

Rescrierea aciunii implicite a unui semnal se realizeaz cu


apelul sistem signal, primete ca i parametrii semnalul a
crui tratare va fi rescris i o referin ctre funcia ce va fi
apelat la apariia semnalului respectiv. Adresa rutinei de
tratare a unui semnal poate fi rescris i printr-un alt apel
sistem sigaction.

Exist posibilitatea ca un proces s trimit un semnal unui


alt proces, acest lucru se poate realiza prin intermediul
apelului sistem kill, de asemenea exista posibilitatea ca un
semnal de tip SIGALRM s fie generat la depirea unui
interval de timp prin intermediul apelului sistem alarm.

O alt modalitate de comunicare ntre dou procese este prin


intermediul pipe. Cnd un proces creeaz un pipe va genera
doi descriptori de fiier asociai pipe-ului, unul pentru
scriere i unul pentru citire.

Pentru a crea un astfel de canal de comunicaie se folosete


apelul sistem pipe. Paii ce trebuie urmai pentru a crea un
pipe ntre dou procese:
Apelul sistem pipe creeaz descriptorii de
citire/scriere.
Apelul sistem fork se creeaz procesele printe i fiu,
cei doi descriptori se vor regsi n ambele procese.
Procesul printe va nchide pfd[0] descriptorul de
citire.
Procesul fiu va nchide pfd[1] descriptorul de scriere.
Se realizeaz transferul mesajului prin intermediul
descriptorilor de fiier rmai deschii.

Pentru a duplica un descriptor de fiier se pot folosi


apelurile sistem dup si dup2.

NTREBRI

Prin ce metode pot comunica dou procese?

Cum poate reaciona un proces la primirea unui semnal?

79
Sisteme de Operare Linux L

Cum poate fi rescris tratarea implicit a unui semnal pentru un


proces?

Cum se poate genera un semnal la expirarea unui interval de


timp?

Cum poate un proces s genereze semnale ctre alte procese?

Care sunt etapele ce trebuie urmate pentru a crea un pipe ntre


dou procese?

S se scrie un program C care conine dou procese (printe + fiu


), procesul printe citete un fiier text i l trimite printr-un pipe
procesului fiu care numr literele i n final va afia o statistic
cu numrul de apariii pentru fiecare liter n parte.

S se scrie un program C care conine dou procese (printe +


fiu), procesul printe trimite printr-un pipe ctre procesul fiu timp
de 5s caracterul a , procesul fiu va numra caracterele primite
iar dup expirarea intervalului de timp va afia numrul de
caractere primite i i va ncheia execuia.

80
Sisteme de Operare Linux L

CAP. VIII FIRE DE EXECUIE

O caracteristic esenial a unui sistem de operare de tip


UNIX/Linux este execuia concurent a mai multor procese, la
fel ca i procesele, firele de execuie par a rula concurent,
responsabil de aceast concuren este nucleul, kernel-ul,
sistemului de operare care ntrerupe rularea thread-urilor la
anumite intervale de timp oferind i altora ansa de a fi rulate.
Conceptual, thread-ul este o subdiviziune, el exist
doar n cadrul unui proces. La execuia unui program, sistemul
de operare creeaz un nou proces i n cadrul procesului
respectiv va crea un singur thread n care programul apelat se
execut secvenial, opional, din thread-ul iniial se pot crea
thread-uri suplimentare, ansamblul acestor thread-uri
reprezentnd programul apelat, fiecare thread executnd pri
diferite ale programului la momente diferite de timp.
Dac n cazul crerii unui nou proces, procesul fiu
execut programul procesului printe dar cu resursele
printelui, memorie virtual, descriptori de fiiere, etc.,
copiate procesul fiu putnd modifica oricare resurs fr a
afecta procesul printe, i viceversa, la crearea unui thread
nimic nu este copiat. Ambele thread-uri vor utiliza resursele
sistem n comun, dac un thread nchide un descriptor de
fiier, celelalte thread-uri nu vor mai putea efectua operaii
asupra acelui descriptor de fiier. De asemenea datorit
faptului ca un proces, respectiv thread-urile asociate unui
proces, poate excuta doar un singur program la un moment
dat, dac un thread apeleaz una dintre funciile exec execuia
celorlalte thread-uri este ntrerupt.
Comutarea execuiei ntre dou procese implic un
numr relativ mare de operaii. Aceste operaii sunt necesare
pentru a se asigura faptul c nu apar interferene ntre
diferitele resurse ale unor procese diferite, aceast condiie
fiind necesar n cadrul unui sistem multiutilizator. n situaia
n care se dorete ca dou sau mai multe procese s coopereze,
pentru atingerea unui scop comun, acest obiectiv se poate
realiza prin utilizarea mecanismelor de comunicare
interproces. Totui i n cazul utilizrii acestor mecanisme sunt
necesare operaiile de comunicare ntre procese care impun
operaii suplimentare. Dac se dorete eliminarea acestor
operaii suplimentare atunci procesele pot fi nlocuite cu fire
de execuie.
81
Sisteme de Operare Linux L

Firele de execuie mai sunt numite i procese uoare (light


weight procesess LWPs). Un proces, n general, are mai
multe pri componente cod, date, stiv, i de asemenea un
anumit timp de execuie pe procesor. n cazul firelor de
execuie vom avea mai multe procese care au alocate propriile
lor intervale de timp de procesor dar folosesc n comun
segmentele de cod, date, memoria i structurile da date.
n acest caz operaiile necesare pentru comutarea ntre dou
fire de execuie implic un efort semnificativ mai mic dect n
situaia unor procese. Deoarece firele de execuie au fost
proiectate astfel nct s fie cooperative, nucleu sistemului de
operare nu trebuie s ia msuri suplimentare de protecie a
resurselor acestora n cadrul unui proces. Din acest motiv
firele de execuie au primit denumirea de procese uoare. La
polul opus se afl procesele ca atare, care comparativ cu firele
de execuie implic un efort de comutare mai mare i ca
urmare se mai numesc i procese grele (heavy weight
processes HWPs)
n general procesele pot fi implementate n dou moduri:
n spaiul nucleului de obicei aceste procese sunt
implementate n nucleul sistemului de operare, implementare
ce se bazeaz pe controlul, n nucleu, a tabelelor de semnale
asociate firului de execuie. n acest caz nucleul sistemului de
operare este rspunztor de programarea execuiei fiecrui fir,
iar intervalul de timp alocat firului este sczut din timpul
alocat, global, procesului din care face parte firul.
Dezavantajul acestei metode de control al timpului de execuie
este dat de apariia unui efort suplimentar la comutarea
utilizator-nucleu-utilizator. Avantajul major este dat de
planificarea controlat a firelor de execuie (la expirarea
cuantei de timp de procesor nucleul i va ntrerupe execuia i
va transmite controlul firului urmtor), deci este exclus
blocarea procesului datorat unor operaii de I/E, iar n cazul
sistemelor de calcul cu mai multe procesoare performana
poate crete proporional cu numrul de procesoare adugate
sistemului.
n spaiul utilizatorului n acest caz este evitat controlul
nucleului asupra firului de execuie pentru o astfel
implementare,numit i multitasking cooperativ, se definesc
un set de rutine ce sunt responsabile de comutarea execuiei
ntre fire. Tipic un fir de execuie cedeaz controlul n mod
explicit procesorul, prin apelul explicit a unei rutine,
trimiterea unui semnal. O problem major ce poate apare este
82
Sisteme de Operare Linux L

acapararea de ctre un fir a ntregului timp de procesor asociat


unui proces (ex. dac procesul execut o operaie de I/E), o
posibil rezolvare este utilizarea unui semnal de timp care s
determine comutarea ntre fire.
n paragrafele ce urmeaz discuia se va baza pe fire de
execuie POSIX numite i pthreads (firele ce nu se
conformeaz acestui standard se numesc cthreads).
n cadrul unui proces un thread este recunoscut pe baza unui
identificator, iar la creare fiecare thread execut o funcie.
Acesta este o funcie obinuit ce conine codul ce trebuie
rulat de thread, iar la ieirea din funcie se termin i execuia
thread-ului.
Apelul sistem de baz pentru crearea de noi thread-uri este
pthread_creat.

#include <pthread.h>
int pthread_create(pthread_t *thread,
pthread_attr_t *attr, void *
(*start_routine)(void *), void *arg);

Funcia pthread_creat creeaz noi thread-uri i trebuie s i se


transmit urmtoarele argumente:
O referin ctre o variabil de tip pthread_h, n care este
salvat identificatorul thread-ului.
O referin ctre un obiect de tip thread attribute. Prin acest
argument se controleaz modul n care thread-ul
interacioneaz cu restul programului. Dac argumentul
transmis este NULL atunci se vor folosi setrile implicite.
O referin ctre funcia ce urmeaz a fi executat de thread.
Referina ctre funcie trebuie s fie de tipul: void* (* ) (void
*).
Argument ctre thread. Acesta trebuie s fie de tip void *, i
este transmis funciei thread-ului.
La apelul funciei phtread_creat are loc crearea thread-ului, iar
revenirea din funcie se face imediat. Rularea celor dou
thread-uri (printe i fiu) are loc asincron, iar execuia unui
program nu trebuie s se bazeze pe o anumit ordine de rulare
a thread-rilor.
Un exemplu clasic de program este Hello World, de aceast
dat realizat cu thread-uri:

#include <stdio.h>
#include <stdlib.h>

83
Sisteme de Operare Linux L

#include <pthread.h>
#include <unistd.h>

//funcia ce va fi executat de
thread-uri
void* print_message( void *ptr ){
char *message;
message = (char *) ptr;
printf("%s ", message);
return NULL;
}

int main(){
pthread_t thread1, thread2;
char *message1 = "Hello";
char *message2 = "World\n";

// creearea primului thread


tiprete Hello
if (pthread_create( &thread1, NULL,
&print_message, (void*)message1)){
fprintf(stderr,"first thread
error\n");
exit(1);
}

// adoarme procesul printe pentru


o secund.
sleep(1);

// creearea celui de al doilea thread


tiprete World
if(pthread_create( &thread2, NULL,
&print_message, (void*)message2)){
fprintf(stderr,"second thread
error\n");
exit(1);
}

sleep(1);
exit(0);
}

Compilarea programului se realizeaz cu urmtoarea


comand:

84
Sisteme de Operare Linux L

$ gcc -o hello_thread hello_thread.cc


-D_REENTRANT -lpthread

Opiunea lpthread trebuie specificat la compilarea


programului datorit faptului c suportul pentru thread-uri este
adugat sub forma unei biblioteci.
O problem ce suport dou moduri de tratare, n cazul
thread-urilor, este cea a terminrii execuiei i a valorii
returnate de thread. O prim modalitate este cea prezentat n
exemplul anterior n care funcia tratat de thread se ncheie
prin apelul return, iar valoarea transmis este considerat ca
fiind valoare returnat de thread. O alt modalitate este prin
intermediul apelului sistem pthread_exit.

#include <pthread.h>

void pthread_exit(void *retval);

Aceast funcie poate fi apelat direct din funcia thread-ului


sau din alt funcie apelat direct sau indirect din funcia
thread-ului. Valoarea primit ca i argument este valoarea ce
va fi returnat de thread.
Tot din exemplul anterior se poate observa c transmiterea
parametrilor ctre thread se realizeaz prin ultimul parametru
al apelului pthread_creat. Dac nu se dorete transmiterea unui
parametru funciei thread-ului atunci argmentul respectiv
primete valoare NULL. Valoarea acestui parametru poate fi o
referin ctre orice structur de date.

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>

// definirea structurii de date ce va


fi transmis ca argument thread-ului
struct chars {
char val;
int count;
};

// funcia thread-ului
void *char_print(void *ptr){

85
Sisteme de Operare Linux L

struct chars* c = (struct


chars*)ptr;
for(int i=0;i<c->count;i++)
putchar(c->val);
pthread_exit(0);
}

int main(){
pthread_t thread1, thread2;
struct chars
thread1_arg,thread2_arg;

// stabilirea parametrilor pentru


thread-uri
thread1_arg.val='a';
thread1_arg.count=100000;

thread2_arg.val='b';
thread2_arg.count=150000;

// creearea thread-urilor

pthread_create(&thread1,NULL,&char_print,&
thread1_arg);

pthread_create(&thread2,NULL,&char_print,&
thread2_arg);

// ncheierea execuiei
exit(0);
}

Exemplul de mai sus creeaz dou thread-uri fiecare afind


cte un caracter de cte un anumit numr de ori, totodat este
i un exemplu ce ilustreaz modul n care se pot transmite
funciei thread-ului argumente mai complexe. Totui acest
program ascunde o problem de funcionare. Funcia thread-
ului primete ca i argumente referine ctre structuri de date
definite ca i variabile locale n thread-ul principal al
programului. Datorit faptului c nu exist nici o regul
asupra ordinii de executare a thread-urilor este posibil ca
thread-ul principal s i ncheie execuia naintea celor dou
thread-uri de afiare a caracterelor. O consecin este faptul c
este dealocat memoria rezervat structurilor de date transmise
ca i parametrii thread-urilor. O rezolvare a acestei probleme
este apelul sistem pthread_join:
86
Sisteme de Operare Linux L

#include <pthread.h>
int pthread_join(pthread_t th, void
**thread_return);

Acest apel sistem suspend execuia thread-ului apelant pn


la ncheierea execuiei thread-ului identificat prin ID-ul th.
Pthread_join primete dou argumente primul este ID-ul
thread-ului dup care thread-ul apelant trebuie s atepte s i
ncheie execuia, iar al doilea este o referin ctre o locaie de
memorie n care se va reine valoarea returnat de thread-ul th.
Dac valoarea returnat de thread-ul th nu intereseaz, atunci
al doilea argument va fi NULL.
n consecin pentru ca exemplul anterior s fie funcional
trebuie completat cu urmtorul cod:

.
.
.
// crearea thread-urilor
pthread_create(&thread1,NULL,&char_pr
int,&thread1_arg);
pthread_create(&thread2,NULL,&char_print,&
thread2_arg);

// thread-ul printe ateapt


ncheierea execuiei thread-urilor fiu.
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);

// ncheierea execuiei
exit(0);
}

Observaie: Trebuie avut grij ca orice tip de date ce este


transmis unui thread prin referin s nu fie dealocat, de
thread-ul printe sau de oricare alt thread.

Uneori este util de determinat care este thread-ul care execut


un anumit cod. Pentru a determina ID-ul unui thread, avem la
dispoziie apelul sistem pthread_self, care are ca i rezultat
ID-ul thread-ului care l apeleaz. De asemenea putem
compara dou thread-uri pe baza ID-urilor cu apelul
pthread_equal.

87
Sisteme de Operare Linux L

#include <pthread.h>

pthread_t pthread_self(void);
int pthread_equal(pthread_t thread1,
pthread_t thread2);

De exemplu este o eroare ca un thread s apeleze pthread_join


pentru el nsui. Pentru a evita o astfel de eroare se poate
utiliza urmtoarea secven de cod:

if(!pthread_equal(pthread_self(),
alt_thread))
pthread_join(alt_thread, NULL);

Un alt aspect important n ceea ce privete crearea i utilizarea


thread-urilor atributele thread-urilor ce pot fi transmise ca i
argument funciei pthread_create. De fapt acest apel sistem
primete ca i argument o referin ctre un obiect de tip
thread attribute. Dac referina este NULL, atunci se vor folosi
atributele implicite pentru crearea thread-ului.
Dac se dorete creare unui thread pe baza unor atribute
particulare este nevoie de crearea unui obiect de tip thread
attribute.Relativ la acest tip de obiecte sunt definite mai multe
apeluri sistem dintre care cele mai importante sunt:
pthread_attr_init - iniializeaz obiectul primit ca i argument
cu valorile implicite, i pthread_attr_destroy dealoc
resursele ocupate de obiectul primit ca i argument.

#include <pthread.h>

int pthread_attr_init(pthread_attr_t
*attr);
int
pthread_attr_destroy(pthread_attr_t
*attr);

Pentru a defini un thread cu atribute particulare se aplic


urmtorii pai:
1.Se creeaz un obiect de tipul thread attribute se declar o
variabil de acest tip.
2.Obiectul creat este transmis ca i parametru funciei
pthread_attr_init obiectul este iniializat cu atributele
implicite.
3.Se modific atributele dorite.

88
Sisteme de Operare Linux L

4.Se crea un thread pe baza apelului pthread_create cruia i se


transmite ca i argument nou creatul thread attribute.
5.Resursele ocupate de thread attribute trebuie eliberate se
folosete pthread_attr_destroy.

Observaie: Un singur obiect de tip thread attribute poate fi


utilizat pentru crearea mai multor thread-uri, dup care
prezena acestui nu mai este necesar i obiectul poate fi
dealocat.

# include<pthread.h>

void* thread_function(void *arg){

.....
}

int main(){
pthread_attr_t attr;
pthread_t thread;

pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTH
READ_CREATE_DETACHED);
pthread_create(&thread,&attr,&thread_
function,NULL);
pthread_attr_destroy(&attr);
....
exit(0);
}

Pentru majoritatea programelor un singur atribut al thread-ului


este important, restul atributelor se utilizeaz doar n cazul
programelor de timp real. Acest atribut este detach state.
Conform acestui atribut un thread poate fi creat fie joinable
(implicit), fie detached. n primul caz, joinable, starea thread-
ului nu este preluat de ctre sistemul de operare automat i
rmne n sistem, ca i n cazul proceselor zombie, pn cnd
un alt thread apeleaz pthread_join. n cazul n care thread-ul
creat are atributul detached, starea de ieire a thread-ului este
automat preluat de sistemul de operare. Dezavantajul n acest
caz este dat de dispariia posibilitii de sincronizare ntre
thread-uri prin intermediul funciei pthread_join.

89
Sisteme de Operare Linux L

Observaie:Chiar dac un thread a fost creat iniial ca i


joinable ulterior poate fi detached prin intermediul apelului
sistem ptheread_detach.
n condiii normale un thread i ncheie execuia fie prin
terminarea rulrii funciei thread-ului returnnd o valoare, fie
prin apelul sistem pthread_exit. Mai exist i o a treia
posibilitate n care un thread solicit unui alt thread
ncheierea execuiei. n acest caz este folosit apelul sistem
pthread_cancel:

#include <pthread.h>
int pthread_cancel(pthread_t thread);

Deseori execuia normal a unui thread implic alocarea unor


resurse, utilizarea lor i n final dealocarea lor. Dac execuia
unui thread este anulat n mijlocul unui astfel de proces,
resursele alocate iniial se vor pierde.
n concluzie din acest punct de vedere un thread se poate afla
n una din urmtoarele stri:
Asincron anulabil i poate ncheia execuia n orice
moment.
Sincron anulabil se poate solicita din exterior ncheierea
execuiei, dar nu n orice moment. Cererile de ncheiere a
execuiei vor fi puse ntr-o coad de ateptare i vor fi luate n
considerare doar n anumite momente ale execuiei.
Neanulabil toate cererile de ncheiere a execuiei sunt
ignorate.

Observaie:Implicit toate thread-urile sunt sincron anulabile.


Acest mecanism de terminare a execuiei unui thread pe baza
unor cereri externe se bazeaz pe urmtoarele apeluri sistem:

#include <pthread.h>
int pthread_setcancelstate(int state,
int *oldstate );
int pthread_setcanceltype(int type,
int *oldtype);
void pthread_testcancel(void);

Aa cum am s-a artat anterior unui thread asincron anulabil i


se poate solicita n orice moment s i ncheie execuia, n
timp ce un thread sincron anulabil i poate ncheia execuia
doar n anumite momente numite puncte de anulare.

90
Sisteme de Operare Linux L

Pentru ca un thread s fie asincron anulabil (implicit este


sincron) se folosete apelul pthread_setcanceltype unde primul
argument este PTHREAD_CANCEL_ASYCHRONOUS
(PTHREAD_CANCEL_DEFFERD pentru a reveni la cazul
sincron), al doilea argument este o referin ctre o variabil
care conine vechea stare, dac lipsete NULL:

pthread_setcanceltype(
PTHREAD_CANCEL_ASYCHRONOUS , NULL);

Pentru a testa dac un thread este anulabil ntr-un anumit


punct se utilizeaz pthread_testcancel. Utilizarea acestui
apel sistem este valabil n cazul threa-urilor asincrone.
Se poate indica din interiorul thread -ului seciunile
neanulabile prin apelul pthread_setcancelstate:

...
int old_cancel_state;
...
pthread_setcancelstate(PTHREAD_CANCEL
_DISABLE,&old_cancel_state)
...
pthread_setcancelstate(old_cancel_sta
te, NULL);
...

Pe baza acestui apel se pot implementa seciuni critice, care


fie se execut n ntregime, fie nu se execut de loc. Dac un
thread ncepe execuia unei astfel de seciuni atunci trebuie s
o continue pn la sfritul seciunii fr a fi anulat.
Implementarea thread-urilor POSIX este diferit de
implementarea din multe alte sisteme de operare de tip UNIX.
Diferena este dat de faptul c n Linux thread-urile sunt
implemntate ca i procese. Fiecare apel pthread_create creeaz
un nou proces ce ruleaz thread-ul nou creat. Oricum acest
proces este diferit de cel creat cu fork, el utilizeaz n comun
spaiul de adrese i resursele cu procesul original.
O problem ce se poate pune n cazul programelor
implementate multithread este gestionarea semnalelor. S
presupunem c un astfel de program primete un semnal din
exterior, se pune ntrebarea care thread va apela funcia de
tratare a semnalului (handler-ul)? n cazul sistemelor de
operare de tip Linux problema este rezolvat chiar de
implementarea acestora de tip proces semnalul va fi tratat de
91
Sisteme de Operare Linux L

thread-ul ce ruleaz programul principal. De asemenea, n


interiorul unui program multithread este posibil, ca un thread
s poat trimite un semnal unui alt thread, pentru aceasta se
folosete apelul sistem pthread_kill.

REZUMAT

Thread-ul este o subdiviziune, el existnd doar n cadrul unui


proces. La execuia unui program, sistemul de operare
creeaz un nou proces i n cadrul procesului respectiv va
crea un fir de execuie n care programul apelat se execut
secvenial, opional, din thread-ul iniial se pot crea thread-
uri suplimentare, ansamblul acestor thread-uri reprezentnd
programul apelat, fiecare thread executnd pri diferite ale
programului la momente diferite de timp.

n cazul proceselor, procesul fiu copia resursele procesului


printe(memorie virtual, descriptori de fiiere, etc.). n
cazul firelor de execuie, ambele thread-uri vor folosi
resursele sistem n comun, dac un thread deschide un
descriptor de fiier, celelalte thread-uri nu vor mai putea
efectua operaii asupra acelui descriptor de fiier, de
asemenea datorit faptului c un proces (thread-urile
componente) poate executa un singur program, dac un
thread component apeleaz una dintre funciile exec, execuia
celorlalte thread-uri componente este ntrerupt.

Firele de execuie mai sunt numite i procese uoare, n


cazul lor vom avea mai multe procese ce au alocate propriile
lor intervale de timp de procesor dar folosesc n comun
segmentele de cod, date, memoria i structurile de date.
Deoarece au fost proiectate s fie cooperative nucleul
sistemului de operare nu trebuie s ia msuri suplimentare de
protecie a resurselor acestora n cadrul unui proces.

Din punctul de vedere al gestionrii firelor de execuie vom


avea dou tipuri de procese:
n spaiul nucleului nucleul este responsabil pentru
controlul execuiei fiecrui fir.
n spaiul utilizatorului controlul execuiei se
realizeaz la nivelul fiecrui fir n parte.

Firele de execuie ce se conformeaz standardului POSIX se


92
Sisteme de Operare Linux L

numesc pthreads. n cadrul unui proces un fir de execuie


este recunoscut pe baza unui identificator, la creare un fir de
execuie execut funcia ce conine codul ce trebuie rulat.
Apelul sistem pentru crearea unui nou thread este
pthread_creat.

Neexistnd nici o regul asupra ordinii de executare a firelor


de execuie este posibil ca thread-ul principal s i ncheie
execuia naintea thread-urilor fiu, deci se va dealoca
memoria rezervat structurilor de date transmise ca
parametrii thread-urilor, aceast problem se poate rezolva
prin apelul sistem pthread_join.

Apeluri sistem pentru gestionarea firelor de execuie:


pthread_self ntoarce id-ul thread-ului curent.
pthread_equal compar id-urile a doua threa-uri.

Apeluri sistem pentru gestionarea atributelor:


pthread_attr_init iniializeaz un obiect de tip
atribut.
attr_destroy elibereaz resursele ocupate de un
obiect de tip atribut.

Din punctul de vedere al atributelor asociate unui thread cel


mai important este detach_state. Poate avea urmtoarele
valori:
joinable starea thread-ului nu este preluat automat
de sistemul de operare.
detached starea thread-ului este preluat automat de
sistemul de operare.

Dac un thread este detached dispare posibilitatea de


sincronizare prin intermediul apelului pthread_join. Pentru a
solicita unui alt thread ncheierea execuiei se folosete
apelul sistem pthread_cancel.
Un thread poate fi n urma din urmtoarele stri:
asincron anulabil execuia se poate ncheia n orice
moment.
sincron anulabil se poate solicita ncheierea
execuiei din exterior, dar nu n orice moment.
neanulabil cererile de ncheiere a execuiei vor fi
ignorate.

93
Sisteme de Operare Linux L

Semnalele primite de proces vor fi trimise firului de execuie


principal urmnd ca acesta s le trateze, eventual s le
transmit thread-urilor fiu prin apelul sistem pthread_kill.

NTREBRI

Ce este un thread ?

Care este diferena dintre un thread i un fir de execuie?

De ce firele de execuie se numesc procese uoare?

Prin ce metod poate fi sincronizat thread-ul principal cu thread-


urile fiu?

Cum sunt tratate semnalele primite de proces din punctul de


vedere al firelor de execuie?

n ce stri se poate afla un thread i ce reprezint fiecare?

Cum pot comunica dou fire de execuie?

Implementai o noua versiune a funciei fgets(ex timed_fgets). La


apelul funciei timed_fgets aceasta va ntoarce un pointer, dac
utilizatorul nu scrie nimic la tastatur ntr-un interval de 3s va
indica ctre un ir vid, altfel va indica ctre irul scris la
tastatur. Pentru implementare se vor folosi thread-uri.

94
Sisteme de Operare Linux L

CAP. IX Probleme propuse

1. Shell

Cerinte:
un proces ce poate accepta si lansa in execuie comenzi.
facilitatea history (sgeata sus va permite
vizualizarea/lansarea in execuie a comenzilor rulate anterior).
va conine un fiier log (numele comenzii lansate in
execuie, data si timpul curent, numele utilizatorului).
va menine o lista a comenzilor care au generat erori la
rulare.

2. Copiere

Cerine:
unul sau mai multe fiiere/directoare (recursiv).
afiarea progresului global/per fiier.
opiunea de mutare.
posibilitate de reluare a procesului de copiere din
punctul in care a fost ntrerupt (resume).

3. Cron

Cerine:
un proces care va lansa in execuie comenzi pe baza
unui fiier de configurare.
in fiier se va preciza:
o numele comenzii.
o parametrii.
o data + ora execuiei.
o va conine un fiier de log in care pentru fiecare
comanda lansata in execuie se salva codul de ieire returnat la
ncheierea execuiei.

4. TaskManager

Cerine:
pentru fiecare proces sa se afieze (vezi /proc):
nume.
stare (status).
PID - numr de identificare proces.

95
Sisteme de Operare Linux L

numele utilizatorului ce a lansat in execuie


procesul(vezi /etc/passwd).
afiarea proceselor sa se realizeze periodic, dup un
anumit interval de timp (secunde) ce poate fi modificat
dinamic in timpul rulrii.
unui anumit proces, identificat prin PID, sa ii poat fi
trimise semnale.

5. Game Master

Se cere sa se creeze un program care sa serveasc drept


platforma pentru o clasa larga de jocuri.
Specificatii:
* Programul principal -GM- si juctorii -J- sunt procese ale
aceleiai aplicaii
* GM gestioneaz plana de joc, juctorii, si eventuale resurse
comune, colecteaz date statistice despre jocuri pe care le
afieaz
utilizatorului
* Comunicaia are loc bidirecional, numai ntre GM si J, prin
pipe-uri (recomandat GM->J) si semnale (recomandat J->GM)
* Aplicaia va implementa cel puin 3 jocuri, dintre care 2
impuse (regulile complete ale celor 3 jocuri trebuiesc
confirmate prealabil
cu coordonatorul proiectului)
* Jocurile vor avea cel puin 3 niveluri de dificultate pentru J

a) Fotbal
-- Toi Juctorii au poziii mobile
-- Cooperativ: DA
-- Resurse suplimentare comune: mingea
-- Scop: gol
-- Rol GM: transmite informaii cu privire la poziiile J

b) Tancuri
-- Toi Juctorii au poziii fixe
-- Cooperativ: NU
-- Resurse suplimentare comune: N/A
-- Scop: supravieuirea
-- Rol GM: transmite informaii topografice cu privire la teren
si poziiile J

* Opiuni
96
Sisteme de Operare Linux L

-- Mod text sau grafic


-- Interaciunea cu utilizatorul se face n timp real sau la
momente discrete

6. Detecie

Se cere sa se creeze o aplicaie cu 2 componente: un program


Virus (V) si un program Detector (D)
Specificaii:
* 2 programe diferite, fr interaciune directa cu utilizatorul
* Aplicaia va avea cel puin 3 niveluri de dificultate pentru D
(timpul de execuie al D si V fiind unul dintre parametri)
* Spaiul de lucru (SdL): un director transmis ca parametru la
rulare
* V:
-- Scaneaz SdL de semne ale activitii D
-- i scrie periodic, codificat, PID-ul n diferite fiiere text din
SdL
* D:
-- Scaneaz SdL de semne ale activitii V
-- La o decodificare cu succes, executa comanda KILL pentru
procesul V
-- Poate crea periodic nc un exemplar de D, care sa asiste la
detecie, ntr-o limita ce depinde de gradul de dificultate
-- Afieaz statistici

97

S-ar putea să vă placă și