|
Politica de confidentialitate |
|
• domnisoara hus • legume • istoria unui galban • metanol • recapitulare • profitul • caract • comentariu liric • radiolocatia • praslea cel voinic si merele da aur | |
Shell-ul Unix | ||||||
|
||||||
Orice utilizator al unui calculator interactioneaza la un moment dat cu shell-ul. Fie ca apare sub forma unor iconite mititele, fie sub forma unui j8v9vg 1. Ce este un shell ? Cuvintul SHELL inseamna in limba engleza SCOICA sau carapace. Asta este si programul care se numeste shell pentru sistemul de operare: un invelis care imbraca sistemul, primul lucru pe care il vedem dintr-un sistem de operare. ------------------------------------------------------ utilizator 1.1.Bucla principala Misiunea unui shell este de a citi de la utilizator comenzi pe care apoi le interpreteaza si le executa. Executarea comenzilor se face folosind apelurile de sistem. Pe scurt, orice shell are structura urmatoare: ------------------------------------------------------ while (1) A Apelurile de sistem sunt folosite pentru: a*i A scrie utilizatorului mesaje (prompt); ------------------------------------------------------ Red Hat Linux release 4.2 (Biltmore) 2. Cel mai simplu exemplu Iata probabil cel mai simplu exemplu posibil de shell pentru sistemul Unix, care este pe deplin functional! (Incercati-l!) Shell-urile moderne ofera o paleta de functionalitati suplimentare care fac viata utilizatorului mai simpla, dar la rigoare exemplul din codul de mai jos este perfect suficient, desi nu intotdeauna foarte convenabil de folosit. O virtute incontestabila insa are, si anume simplitatea, lucru care il si face subiectul nostru de studiu. ------------------------------------------------------ /* smallest shell */ a,ba99i,*c,da99i;main()Awhile(printf(">"),c=d,*c=a=gets(b))A for(;*++c=strtok(a," ");a=0);fork()?wait(0):execvp(*d,d+1);SS Puteti compila si executa acest program pe orice platforma Unix care poseda un compilator de C. Daca fisierul se numeste "shell.c", puteti sa
o faceti in urmatorul fel: (Nu trebuie sa va ingrijoreze eventuale WARNING-uri; programul este corect.) Semnul `> este prompt-ul. Puteti tasta orice comanda: Puteti tasta CONTROL-d pentru a termina interactiunea cu el. Sa vedem cum functioneaza acest mic shell. 2.1 Functiile de biblioteca Inainte de a incerca sa intelegem cum procedeaza, sa analizam fiecare din functiile C folosite. O parte din functii sunt C standard si este oferita de orice compilator (printf(), gets(), strtok()), altele sunt apeluri de sistem 2.2.2 printf() Prima si cea mai simpla functie folosita este printf(). Ea este folosita pentru a tipari prompt-ul. Aceasta functie este o functie de biblioteca, dar care este implementata la rindul ei in termenii apelului de sistem write(), prin care in Unix se pot trimite date spre un periferic (in acest caz ecranul). 2.3.3 gets() Functia gets() este opusa lui printf(): este folosita pentru a citi o linie de la utilizator. Argumentul ei este un array de caractere, unde va pune rezultatul citirii (un sir de caractere). Rezultatul apelului functiei este chiar argumentul ei (sau 0 daca s-a intilnit sfirsitul de fisier, ceea ce in cazul utilizatorului in general inseamna ca acesta a apasat CONTROL-d). In plus, gets() schimba sfirsitul de linie (\n) cu un sfirsit de sir (\0). Ca si printf(), gets() se bazeaza pe apelul de sistem read(), care (opusul lui write()), citeste date de la un periferic sau fisier. 2.4.4 strtok() Functia strtok() este standard C. Declaratia ei se gaseste in headerul ------------------------------------------------------ char *strtok(char * text, const char * separatori); Functionarea ei este speciala daca "text == NULL". Scopul ei este
de a imparti sirul "text" in bucatele care sunt despartite de caractere
din sirul ------------------------------------------------------ #include <string.h> cuvint = strtok(text, separator); Daca executati acest program veti obtine: ------------------------------------------------------ sir de separat in bucati Prima oara cind apelez strtok(text, separator), aceasta testeaza daca "text" nu e 0 (NULL), deci il memoreaza undeva intr-un buffer intern functiei. Dupa aceasta cauta prima aparitie a unui caracter din "separator", pe care o inlocuieste cu un caracter 0 (sau \0, sfirsit de sir). La intrare vom avea: ------------------------------------------------------ text = |s|i|r| | |d|e| |s|e|p|a|r|a|t| | | |i|n| |b|u|c|a|t|i|\0| si la iesire: Cu alte cuvinte sirul "text" a fost modificat, rezultatul "cuvint" puncteaza la primul cuvint, care a fost separat cu un 0 de restul sirului, iar strtok() tine minte unde a ramas. A doua oara cind apelez strtok() va avea un argument 0 in locul lui "text". Asta inseamna: continua de unde s-a ramas. Asa ca rezultatul va fi: ------------------------------------------------------ text = |s|i|r|\0| |d|e|\0|s|e|p|a|r|a|t| | | |i|n| |b|u|c|a|t|i|\0| Data viitoare se va obtine: ------------------------------------------------------ text = |s|i|r|\0| |d|e|\0|s|e|p|a|r|a|t|\0| | |i|n| |b|u|c|a|t|i|\0| Dupa inca doua apeluri se va obtine rezultat 0, pentru ca s-a ajuns la sfirsitul sirului: ------------------------------------------------------ text = |s|i|r|\0| |d|e|\0|s|e|p|a|r|a|t|\0| | |i|n|\0|b|u|c|a|t|i|\0| Iata cum strtok() desparte un sir de caractere. strtok() este o functie care poate fi implementata fara ajutorul vreunui apel de sistem, pentru ca manipuleaza simple array-uri de caractere. 2.5 Apeluri de sistem Ultimele 3 functii sunt apeluri de sistem tipice Unix, care au de-a face cu crearea de noi procese. 2.6.6 fork() fork() este singura metoda prin care in Unix se poate crea un nou proces (vezi lab socn6.txt). Cind un proces executa fork(), el da nastere unui alt proces absolut identic cu el insusi, care se numeste fiul lui, si care isi continua executia in paralel cu tatal. Amindoua procesele isi continua executia ca si cum tocmai ar fi executat instructiunea fork(); singura diferenta dintre ele este ca tatal va primi ca rezultat al executarii lui fork() un numar nenul, care identifica fiul, iar fiul va primi un 0. Figura explica si numele: "fork" inseamna "furculita". ------------------------------------------------------ ------------- | | proces=12 inainte | r = fork() | de | | fork() -------------- ___________ In figura de mai sus, parintele (cu numarul de proces 12) creaza un copil, care intimplator capata numarul 13. Dupa instructiunea fork() avem 2 procese, 2.7.7 wait() Cu apelul de sistem wait() un proces parinte asteapta terminarea unui copil. 2.8.8 execvp() Rezultatul compilarii unui program este un fisier executabil (de exemplu, mai sus cind ati compilat shell.c ati obtinut shell). Apelul de sistem exec() determina nucleul sa citeasca un fisier executabil in memorie, sa-l transforme in imaginea unui proces si sa-l execute, furnizind si argumentele care vor fi trecute noului proces. Procesul care executa apelul acesta de sistem este complet inlocuit cu imaginea noului fisier. Exista mai multe variante ale apelului de sistem exec() (vezi socn3.txt). execvp() este exec cu un vector de pointeri spre argumentele procesului. Declaratia din <unistd.h> este: ------------------------------------------------------ int execvp(const char *fisier, char * const argumenteai); Primul parametru este numele fisierului executabil. Al doilea parametru este un array in care fiecare obiect este un pointer la un argument pasat procesului. Argumentele sunt simple siruri de caractere. Argumentele sunt primite de functia main() a procesului exec-utat in parametrul argv: ------------------------------------------------------ int main(int argc, char * argvai) 2.9 Programul shell.c Iata inca odata programul de mai sus, cu headerele incluse, indentat si comentat: ------------------------------------------------------ #include <stdio.h> int a, /* char oarecare din sirul citit */ ba99i, /* comanda tastata; folosit ca un char ai */ int main() In primul rind programul foloseste numere intregi pentru a memora atit caractere cit si pointeri. Variabila a puncteaza la sirul citit de la utilizator, pentru a-l imparti in felii cu strtok(). Variabila b contine chiar comanda tastata (e folosita ca un array de caractere). Variabila d va contine la sfirsitul executarii lui strtok() pointerii catre argumente dati lui execvp(). Situatia la inceput arata astfel: ------------------------------------------------------- | | | | | | | | | | | | | ....| b | | | | | | | | | | | | | ....| d |e|c|h|o|\0|a|1|\0|a|2|\0| | | | ....| b Din cauza asta, dupa ce copilul e facut si parintele este dat in background, copilul executa comanda indicata de primul parametru al lui execvp(), *d, 3 Un alt exemplu Prezentam un nou program shell, de data asta mai sofisticat. Acesta poate recunoaste mai multe comenzi pe aceeasi linie, pipe-uri (comanda1 | comanda2), redirectari in fisiere (comanda >fisier1 <fisier2), comanda interna cd. ------------------------------------------------------ #define D ,close( char *c,q a512 i,ma 256 3 )if(!ma*ci)Afor(*++c=0;!ma*--ci;); ------------------------------------------------------- 4 ConcluziiPentru nucleu, shell-ul este un proces ca toate celelalte, care se executa fara nici un fel de privilegii si care ocazional face cite un apel de sistem. Tema : |
||||||
|
||||||
|
||||||
Copyright© 2005 - 2024 | Trimite document | Harta site | Adauga in favorite |
|