Sunteți pe pagina 1din 7

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 stand-
alone 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 directorului de lucru $ pwd

Schimbarea directorului de lucru $ cd

Listare continut director curent $ ls

1
Listare continut director curent cu specificarea $ ls -l
drepturilor de acces1
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 fisier din linia de comanda3 $ 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 comanda $ find fisier

Creaza un director din linia de comanda $ mkdir nume_director

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 prin intermediul
File Manager4. In mod analog se instaleaza un
CD.
Redirectari5:
• 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
Toate aceste comenzi pot fi executate si prin intermediul interfetei grafice Photon, din utilitarul File Manager
4
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

2
fisierului file
• suprima dreptul de executie $ chmod -x file

• 1
da drept de executie ownerului si grupului $ chmod u+x,g+x file
sau asupra fisierului file
Definirea unui alias pentru o comanda. Alias- $ alias dir=’ls -l’
ul trebuie definit in fisierul .profile care se afla
in directorul de login2.
Gasirea variabilelor de mediu $ echo $PATH

Setarea unei noi cai $ PATH = newpath

Adaugarea unui director la calea curenta $ PATH=$PATH:/usr/local/bin

Compilarea programelor
• compilare in fisier executabil a.out $ qcc ./hello.c
$ qcc ./hello.c -o hello.out
• compilare in fisier executabil hello.out
• compilare in background; se accepta alta $ qcc ./test.c &
comanda
• comanda de compilare se executa in $ nohup qcc ./test.c &
background, chiar daca utilizatorul face
logout. Iesirea programului si mesajele de
eroare sunt redirectate in mod automat intr-
un fisier nohup.out
Forteaza executia unui fisier executabil din $ ./hello.out
directorul curent
Afisarea informatiei despre starea sistemului, $ psin
grafic, in fereastra Photon3
Afisarea informatiei despre starea sistemului, in $ sin
mod text, in ferestra Terminal
Terminarea fortata a unui proces prin trimiterea $ kill pid
1
Pentru specificarea drepturilor de acces se foloseste urmatoarea notatie:

Clasa u user g grup o all other users a all


Operatori + add - remove = replace
Permisiune r read w write x execute

Drepturile 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).

3
unui semnal SIGTERM. Pid este ID-ul
procesului, si poate fi obtinut din fereastra
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


Functia1 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

4
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 thread-
ului, 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 thread-
ului;
• 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

5
joinable si memoria alocata poate fi recuperata in mod automat la terminarea executiei
thread-ului.

2. Crearea proceselor

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


concurente1:
(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);
sau, simplu, doar2:
exit();

Obs:
Programul isi poate termina in mod anomal3 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.

6
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