Sunteți pe pagina 1din 23

Programarea aplicatiilor de timp-real

Laborator 1

Prezentarea sistemului de operare QNX


Sistemul de operare QNX este dedicat dezvoltarii aplicatiilor de timp-real, avand facilitati specifice ca
planificarea multitasking preemptiva pe baza de prioritati, posibilitatea comutarii rapide de context,
mecanisme de comunicare intre procese. QNX poate fi utilizat pentru aplicatii standalone sau pentru
lucrul in retea, fiind extrem de flexibil. Sistemul de operare QNX poate fi "ajustat" in functie de aplicatie.

Arhitectura sistemului de operare QNX are la baza microkernelul Neutrino, care gestioneaza un grup de
procese care coopereaza. Microkernelul Neutrino asigura urmatoarele servicii de baza:
a) servicii asociate firelor de executie. Neutrino furnizeaza primitive pentru crearea firelor de
executie conform standardului POSIX;
b) servicii pentru tratarea semnalelor. Neutrino furnizeaza primitive pentru tratarea semnalelor
conform standardului POSIX;
c) servicii pentru transmiterea mesajelor. Neutrino asigura rutarea tuturor mesajelor intre firele
de executie in intregul sistem;
d) servicii de sincronizare. Neutrino furnizeaza primitive pentru sincronizarea firelor de executie
conform standardului POSIX;
e) servicii de planificare. Neutrino planifica si lanseaza in executie firele de executie utilizand
diversi algoritmi POSIX de planificare in timp-real;
f) servicii pentru gestiunea timpului. Neutrino furnizeaza un set bogat de servicii de timp
conform standardului POSIX;
g) servicii pentru managementul proceselor. Microkernelul Neutrino formeaza impreuna cu
managerul de procese o unitate denumita procnto. Componenta manager de procese asigura gestiunea
proceselor si a memoriei.

Microkernelul Neutrino dispune de apeluri specifice (engl. kernel calls) pentru urmatoarele facilitati: a)
fire de executie; b) transmitere de mesaje; c) semnale; d) ceas (gestiunea timpului); e) timere; f) rutine de
tratare a intreruperilor; g) semafoare; h) lock-uri pentru excludere mutuala (mutex); i) variabile
conditionale (condvars); j) bariere.

I. Comenzi uzuale
Afisarea numelui $ pwd
directorului de lucru
Schimbarea directorului $ cd
de lucru
Listare continut director
curent $ ls
$Listare
ls -l continut director curent cu specificarea
1
drepturilor de acces Afiseaza calea pina la un anumit fisier (de $
which ls exemplu, comanda ls2)

Help si optiunilor de executie ale unei comenzi $ use cmdname Stergerea unui
3
fisier din linia de comanda $ rm fisier Copierea unui fisier din linia de comanda
$ cp sursa destinatie Muta sau redenumeste fisiere din linia de
$ mv

comanda Cauta un fisier din linia de


$ find fisier
comanda
$ mkdir nume_director
Creaza un director din linia de comanda
Sterge un director din linia de comanda $ rmdir nume_director
Accesul la o discheta format MS-DOS. $ mount -tdos /dev/fd0 /fs/floppy Discheta se acceseaza apoi
4
prin intermediul File Manager . In mod analog se instaleaza un CD.

5
Redirectari :
• redirectare rezultat comanda $ ls *.c > temp
• programul preia intrarea dintr-un fisier, in
$ my_prog < file
loc de la tastatura
• adauga iesirea comenzii la sfirsitul $ cmd >> file
fisierului file; daca nu exista, il creeaza si
apoi scrie in el
• listeaza fisierul sursa C in alt fisier (files) si $ ls cici.c > files > errors mesajele de
eroare le trimite in fisierul errors

Afisare drepturi de acces la fisiere $ umask

Schimbarea drepturilor de acces la directoare


/fisiere:
• da drept de executie pentru oricine asupra $ chmod +x file

1
Rezultatul comenzii este de forma urmatoare: tip owner group other links
owner group octeti data_ultima_modificare nume

d rwx rwx r-x 4 frank user 4096 Jan 12 09:53 hello.c


2
Programele executabile si comenzile se afla in directoarele /bin si /usr/bin
3 4
Toate aceste comenzi pot fi executate si prin intermediul interfetei grafice Photon, din utilitarul File Manager In
directorul /dev se afla descriptorii pentru dispozitive de memorare externa: hard-disk (hd0-dos), discheta (fd0), CD-
ROM, etc.
5
Sunt valabile urmatoarele redirectari: < file citeste standard input (0) din fisierul file > file
scrie standard output (2) in file >> file ataseaza standard output (2) la sfirsitul fisierului file <<
s citeste de la standard input (0) pina cind apare o linie care contine doar sirul s c1|c2 pipe -
trimite standard ouput a procesului c1 la standard input a procesului c2
fisierului file
• suprima dreptul de executie
1 $ chmod -x file $ chmod
• da drept de executie ownerului si grupului
u+x,g+x file
sau asupra fisierului file Definirea unui alias
pentru o comanda. Aliasul trebuie definit in
2 $ alias dir=’ls -l’
fisierul .profile care se afla in directorul de login .

Gasirea variabilelor de mediu Setarea unei $ echo $PATH $ PATH = newpath $


noi cai Adaugarea unui director la calea PATH=$PATH:/usr/local/bin
curenta Compilarea programelor

• compilare in fisier executabil a.out


• compilare in fisier executabil hello.out $ qcc ./hello.c $ qcc ./hello.c -o hello.out
• compilare in background; se accepta alta
comanda $ qcc ./test.c & $ nohup qcc ./test.c &
• comanda de compilare se executa in background,
chiar daca utilizatorul face logout. Iesirea programului si
mesajele de eroare sunt redirectate in mod automat intrun
fisier nohup.out

Forteaza executia unui fisier executabil din


directorul curent
$ ./hello.out $ psin
Afisarea informatiei despre starea sistemului,
3
grafic, in fereastra Photon $ sin $ kill pid
Afisarea informatiei despre starea sistemului, in
mod text, in ferestra Terminal
Terminarea fortata a unui proces prin trimiterea
1
Pentru specificarea drepturilor de acces se foloseste urmatoarea notatie:
Clas u o all a all
g
a us other
grup
er users
Ope + - =
rato ad rem replace
ri Drepturile
d ove de acces pot fi specificate si octal:
chmod 0 file suprima toate drepturile de acces
chmod 777 file seteaza toate drepturile de acces
chmod 440 file seteaza read pentru user si grup
chmod 2 file seteaza write pentru others
2
Directorul de login este directorul in care este directionat utilizatorul dupa verificarea parolei. Fisierul .profile se
executa dupa fiecare operare de login realizata in mod corect. Fisierul .profile se executa din linia de comanda cu
comanda:
$ . .profile
3
Acelasi rezultat de obtine accesand meniul Launch/Utilities/System Information. Se deschide fereastra System
Process Inspector, in care sunt disponibile informatii despre procesele care ruleaza in sistem (Name, Pid, Code, Data,
Stack, CPU), respectiv informatii despre firele de executie asociate fiecarui proces (Tid, Priority, State, Blocked, IP,
CPU).
unui semnal SIGTERM. Pid este ID-u
l
procesului, si poate fi obtinut din fereastr
a
System Process Inspector
.
Crearea proceselor si firelor de executie in QNX

Diferitele sisteme de operare dau adeseori intelesuri diferite unor termeni ca "proces", "fir de executie",
"task", "program", etc. In QNX se folosesc in mod tipic doar termenii "proces" si "fir de executie". O
"aplicatie" inseamna in mod tipic o colectie de procese, iar termenul "program" este in mod uzual
echivalent cu "proces". Un proces va contine intotdeauna cel putin un fir de executie.

In functie de natura aplicatiei, microkernelul Neutrino si managerul de procese pot fi configurate astfel
incat sa permita executia unei combinatii de fire de executie si procese (conform standardului POSIX).

1. Crearea firelor de executie

Firele de executie dintr-un proces impart datele comune din spatiul de adresa al procesului. Fiecare fir de
executie beneficiaza si de anumite date private. Unele dintre aceste date sunt protejate de nucleu (de
exemplu, identificatorul firului de executie, tid), altele putand exista neprotejate in spatiul de adresa al
procesului (de exemplu, stiva asociata fiecarui fir de executie).

Datele specifice firelor de executie, implementate in biblioteca pthread si memorate in TLS, furnizeaza un
mecanism prin care se asociaza o valoare (cheie) intreaga globala a procesului cu o valoare unica asociata
firului de executie.

Firele de executie pot fi create si distruse in mod dinamic in cadrul unui proces. La crearea unui fir de
executie (cu ajutorul functiei de biblioteca pthread_create()) se aloca si se initializeaza resursele necesare in
spatiul de adresa al procesului. Terminarea executiei firului de executie (cu functii specifice de biblioteca
pthread_exit(), pthread_cancel()) implica oprirea firului de executie si eliberarea resurselor alocate acestuia.

Interfata C pentru crearea firelor de executie sub standardul POSIX se numeste Pthread si furnizeaza o
serie de functii pentru crearea si manipularea firelor de executie. Pentru utilizarea acestor functii,
programele utilizator vor include header-ul pthread.h. Se utilizeaza un nou tip de data, pthread_t, care
reprezinta descriptorul thread-ului.

typedef … pthread_t; typedef …


pthread_attr_t; typedef … size_t;

Interfata C / POSIX pentru fire de executie Functia


1
Descriere
int pthread_attr_init(pthread_attr_t *attr);
Initializeaza la valori default atributele thread-ului specificate de attr.
int pthread_attr_destroy(pthread_attr_t *attr);
Sterge atributele thread-ului specificate de attr.
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

1 Toate functiile returneaza 0 in caz de succes, altfel returneaza un cod de eroare


Seteaza dimensiunea stivei pentru atributele thread-ului.
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t stacksize);
Citeste dimensiunea stivei pentru atributele thread-ului.
int pthread_attr_setstackaddr( pthread_attr_t *attr, void *stackaddr);
Stabileste adresa stivei pentru atributele thread-ului.
int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr);
Citeste adresa stivei pentru atributele thread-ului
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void
*arg);
Creaza un nou thread cu atributele date si apeleaza rutina start_routine cu
argumentul specificat
int pthread_join(pthread_t thread, void **value_ptr);
Suspenda thread-ul apelant pana cand thread-ul specificat se termina
int pthread_exit(void *value_ptr);
Termina executia thread-ului apelant
int pthread_detach(pthread_t thread);
Memoria alocata thread-ului poate fi revendicata la terminarea thread-ului
pthread_t pthread_self(void);
Returneaza id-ului thread-ului apelant
int pthread_equal(pthread_t t1, pthread_t t2);
Compara id-urile a doua fire de executie

Firele de executie POSIX au atribute (de exemplu, dimensiunea stivei), care pot fi manipulate prin
intermediul unui obiect de tip atribut (de tip pthread_attr_t) cu ajutorul unor functii specifice. Fiecare fir de
executie creat are asociat un identificator unic (de tip pthread_t) in raport cu toate celelalte fire de executie
care apartin aceluiasi proces.

Un fir de executie poate fi lansat in executie imediat ce a fost creat cu functia pthread_create, care are ca
argumente patru variabile de tip pointer: un identificator al threadului, un set de atribute, o functie care
reprezinta codul thread-ului, si un set de parametri care va fi transmis acestei functii.

Firul de executie se poate termina normal prin iesirea din functia start_routine, apeland pthread_exit sau la
primirea unui semnal. Firul de executie isi poate termina executia fortat printr-un apel pthread_cancel. Un
fir de executie poate astepta terminarea altui fir de executie utilizand functia pthread_join.

Activitatea de "curatare" dupa terminarea unui thread si de recuperare a memoriei utilizate de acesta se
numeste detaching. Exista doua modalitati de realizare a acestei operatii:
• se face un apel de pthread_join si se asteapta pana cand se termina executia threadului;
• se seteaza atributul detache al firului de executie (fie la momentul crearii thread-ului, fie
prin apelul functiei pthread_detach). Daca acest atribut este setat, thread-ul nu este
joinable si memoria alocata poate fi recuperata in mod automat la terminarea executiei
thread-ului.
2. Crearea proceselor

1
Standardul de timp-real POSIX furnizeaza trei mecanisme pentru crearea proceselor concurente :

(a) crearea unui proces complet nou, care poate fi independent de procesul care l-a creat sau poate fi
un sub-proces ("child" - fiu). In cel de-al doilea caz, procesul parinte se poate bloca pina cand fiul isi
termina executia (face o operatie de tip wait()). Daca parintele este cel care se termina primul, fiul se
va termina si el in mod automat (operatie de tip spawn;
Are ca efect incarcarea si executia fisierului executabil specificat ca parametru. Noul
proces va fi pus in starea ready (gata de executie) si se va putea executa in functie de
metoda de planificare specificata.
Noul proces va primi parametri default, i.e. va rula in acelasi nod ca si procesul parinte,
cu acceasi prioritate si dupa aceeasi metoda de planificre.
Procesul fiu poate obtine ID-ul procesului parinte:
parent_pid - getppid();
(b) se poate inlocui procesul curent cu un nou proces (operatie de tip exec);
(c) se imparte procesul curent in doua procese = procesul curent se cloneaza (operatie de tip fork)

Procesul parinte se imparte in doua procese aproape identice. Noul proces va rula in mod
concurent cu procesul original cu care imparte zona de cod, dar nu si zona de date. Noul
proces va fi initializat ca sa fie o copie a procesului original.
Functia fork nu are argumente si returneaza noul pid catre procesul parinte. Procesul fiu
incepe sa se execute imediat dupa apelul lui fork, si este identificat de o valoare returnata
zero.

Obs: Metoda UNIX / POSIX traditionala de creare a unui nou proces: se face intai fork si apoi exec,
astfel incat se va clona procesul fiu in procesul dorit.

Obs: In momentul in care se termina, un proces face:

exit(0); 2
sau, simplu, doar :
exit();

3
Obs: Programul isi poate termina in mod anomal executia prin:

abort();

1
Un proces poate contine mai multe fire de executie, care au acces la acelasi spatiu de memorie (pot fi comparate cu
firele de executie in Java, taskurile Ada, procesele occam).
2
exit (functie care nu returneaza nimic) este o functie care curata resursele alocate procesului (fisiere deschise, etc),
termina procesul si returneaza catre procesul parinte un cod de stare (status code) pe care fiul il genereaza in momentul
in care isi termina executia.
3
Isi trimite singur un semnal SIGABRT.
Desfasurarea lucrarii:
a) crearea firelor de executie Pentru compilarea programului se executa

urmatoarea comanda:
$ qcc ./creare.c -o ./creare.out

Programul executabil, creare.out, poate fi lansat in executie astfel: $

./creare.out

b) crearea proceselor Pentru compilarea programului se executa

urmatoarea comanda:
$ qcc ./ex_proces.c -o ./ex_proces.out $ qcc ./hello.c -
o ./hello.out

Executia programului:
$ ./ex_proces.out

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