1 / 37

SC che operano su processi

SC che operano su processi. Getpid, fork, exec, wait, waitpid, exit, dup, dup2. Process identifier: getpid,getppid. pid indice del processo all’interno della tabella dei processi ppid indice del processo padre all’interno della tabella dei processi il kernel ha pid 0 e ini t ha pid 1

vesna
Download Presentation

SC che operano su processi

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. SC che operano su processi Getpid, fork, exec, wait, waitpid, exit, dup, dup2

  2. Process identifier: getpid,getppid • pid indice del processo all’interno della tabella dei processi • ppid indice del processo padre all’interno della tabella dei processi • il kernel ha pid 0 e init ha pid 1 • si possono ottenere con pid_t getpid(void) pid_t getppid(void)

  3. PID: getpid,getppid (2) /* frammento che stampa il pid del processo in esecuzione e quello del padre usando la macro WRITE di stampa (in sysmacro.h) … */ char buf[N]; /* stringa da stampare */ … sprintf(buf,”Processo %d, mio padre e’ %d\n.”, getpid(),getppid()); WRITELN(buf); …

  4. PID: getpid,getppid (2.1) /* da sysmacro.h … */ #define STIN 0 #define STDOUT 1 #define STDERR 2 #define WRITE(m) \ IFERROR(write(STDOUT,m,strlen(m)),m) #define WRITELN(m) WRITE(m); WRITE(m);

  5. Creazione : fork() pid_t fork(void); • crea un nuovo processo con indice pid • lo spazio di indirizzamento del nuovo processo è un duplicato di quello del padre • padre e figlio hanno due tabelle dei descrittori di file diverse (il figlio ha una copia di quella del padre) • MA …. condividono la tabella dei file aperti (e quindi anche il puntatore alla locazione corrente di ogni file)

  6. Creazione : fork() (2) pid_t fork(void); • restituisce 0 al figlio e pid al padre, • oppure -1 (solo al padre) in caso di fallimento • es. la tabella dei processi non ha più spazio ...

  7. Creazione di processi (2) copia • Spazio di indirizzamento di padre e figlio dopo una fork terminata con successo 232 - 1 232 - 1 Stack Stack Area vuota Area vuota heap heap Data Data Text Text 0 0 SI figlio SI padre

  8. Creazione di processi (3) • Come prosegue l’esecuzione nei processi padre e figlio 232 - 1 232 - 1 Stack Stack &x &x 45 0 Area vuota Area vuota PC = istruzione successiva a fork heap heap Data Data Text Text 0 0 SI padre (pid=34) SI figlio (pid = 45)

  9. Creazione di processi (4) /* frammento che crea un nuovo processo */ int pid; /* pid del processo creato */ … IFERROR( pid = fork(),”main: creazione”); if ( pid ) { /* siamo nel padre */ sprintf(buf,”Processo %d, ho creato %d\n.”, getpid(),pid); WRITELN(buf); } else { /* siamo nel figlio */ sprintf(buf,”Processo %d, mio padre e’ %d\n.”, getpid(),getppid()); WRITELN(buf); }

  10. Terminazione : exit() void exit(int status); • chiude tutti i descrittori di file, • libera lo spazio di indirizzamento, • invia un segnale SIGCHLD al padre • salva il primo byte (0-255) di status nella tabella dei processi in attesa che il padre lo accetti (con la wait(), waitpid()) • se il processo padre è terminato, il processo ‘orfano’ viene adottato da init (cioè ppid viene settato a 1) • se eseguita nel main è equivalente ad una return

  11. Attesa di terminazione del figlio pid_t wait(int *status) pid_t waitpid(pid_t pid,int *status,int options) • restituisce informazioni sul tipo di terminazione del figlio e il byte meno significativo ritornato con la exit() • per leggere queste informazioni c’è bisogno di opportune maschere WIFEXITED(status) WEXITSTATUS(status) • in caso di errore (es non ci sono figli …) viene ritornato il valore -1

  12. Attesa di terminazione ...(2) pid_t wait(int *status) pid_t waitpid(pid_t pid,int *status,int options) • la waitpid permette di fare attese non bloccanti • WNOHANGspecificato nelle opzioni indica di non attendere se nessun figlio è ancora terminato • permette di attendere un figlio con un pid specifico (pid)

  13. Esempio : wait() ed exit() int status ; /* conterra’ lo stato */ IFERROR( pid = fork(),”main: creazione”); if ( pid ) { /* siamo nel padre */ sleep(20); /* aspetta 10 secondi */ pid = wait(&status); if (WIFEXITED(status)) { /*!=0 se il figlio e’terminato normalmente, (exit o return) non ucciso da signal */ printf(“stato %d\n”, WEXITSTATUS(status)); } else { /* siamo nel figlio */ printf(“Processo %d, figlio.\n”,getpid()); exit(17); /*termina con stato 17 */ }

  14. Esempio : wait() ed exit() (2) cosa accade se eseguiamo un main contenente il codice dell’esempio : $ a.out & -- avvio l’esecuzione in bg Processo 1246, figlio. -- stampato dal figlio

  15. Esempio : wait() ed exit() (3) prima che i 20 secoondi siano finiti ... $ a.out & -- avvio l’esecuzione in bg Processo 1246, figlio. -- stampato dal figlio $ ps -l … S UID PID PPID ………… CMD … Z 501 1246 1245 …………… a.out -- il figlio e’ un processo zombie

  16. Esempio : wait() ed exit() (4) quando il padre si risveglia ed esegue la wait() ... $ a.out & -- avvio l’esecuzione in bg Processo 1246, figlio. -- stampato dal figlio $ ps -l … S UID PID PPID ………… CMD … Z 501 1246 1245 …………… a.out -- il figlio e’ un processo zombie (Z) $ Stato 17. -- stampato dal padre $

  17. Differenziazione : le exec() • execve • è l’unica chiamata di sistema vera • execl, execlp,execle,execv, execvp • sono funzioni di libreria con differenze sul tipo di parametri • alla fine invocano la execve • tutte le exec*() • differenziano un processo rimpiazzando il suo spazio di indirizzamento con quello di un file eseguibile passato come parametro

  18. Differenziazione : le exec() (2) • execl, execlp,execle,execv, execvp, execve • è possibile richiedere che la exec() cerchi il file nelle directory specificate dalla variabile di ambiente PATH è (p nel nome) • è possible passare un array di argomenti secondo il formato di argv[] (v nel nome) • è possible passare un array di stringhe che descrivono l’environment (e nel nome) • è possibile passare gli argomenti o l’environment come lista (terminato da NULL) (l nel nome)

  19. Differenziazione : le exec() (3) • execl, execlp,execle,execv, execvp, execve • le exec() non ritornano in caso di successo!!! • Restituiscono -1 in caso di fallimento • non trova il file, il file non è eseguibile etc... • ATTENZIONE 1: le exec non creano nuovi processi!! • ATTENZIONE 2: padre e figlio continuano a condividere la tabella dei file aperti ….

  20. Differenziazione : le exec() (4) Numero che contraddistingue il file come eseguibile • Formato di un file eseguibile • risultato di compilazione, linking etc ... Magic number Ampiezza area di memoria occupata dalle variabili globali NON inizializzate Altre info Ampiezza BSS Variabili globali inizializzate I-Data segment Text segment Codice del programma (assemblato)

  21. Differenziazione : le exec() (5) Variabili di ambiente (envp) 232 - 1 env • (1) il contenuto del file eseguibile viene usato per sovrascrivere lo spazio di indirizzamento del processo che la invoca Agomenti (argv) argv Stack FRAME per la funzione main Area vuota BSS-segment Data Ampiezza BSS I-Data segment I-Data segment Text segment Text 0 File eseguibile

  22. Differenziazione : le exec() (6) 232 - 1 env • (2) si carica in PC l’indirizzo iniziale X argv Indirizzo della prima istruzione compilata di main() Stack Area vuota BSS-segment X Ampiezza BSS I-Data segment I-Data segment Text segment Text X 0

  23. Esempio : una shell semplificata int pid, status; char * argv[]; while (TRUE) { /*ciclo infinito*/ type_prompt(); /* stampa prompt*/ argv = read_comm(); /*legge command line*/ IFERROR3(pid = fork(),”Nella fork”,continue); if (pid) {/* codice padre */ wait(&status); if (WIFEXITED(status)) …/*gest. stato*/ } else {/*codice figlio*/ IFERROR(execvp(argv[0],argv),”nella execvp”); }

  24. Duplicazione dei descrittori di file: dup() e dup2() int dup(int oldfd); int dup2(int oldfd,int newfd); • creano entrambi una copia del descrittore di file oldfd, • entrambi i descrittori puntano alla stassa locazione della tabella dei file aperti e possono essere utilizzati per lavorare sullo stesso file • dup cerca la prima posizione libera • dup2 chiude prima newfd (se aperto) e poi ci copia oldfd

  25. Es: la redirezione • La shell permette di ridirigere stdin/out/error • Es. $ ls indirizzi.pdf k.c s.doc

  26. Es: la redirezione • La shell permette di ridirigere stdin/out/error • Es. $ ls indirizzi.pdf k.c s.doc $ ls > pippo

  27. Es: la redirezione • La shell permette di ridirigere stdin/out/error • Es. $ ls indirizzi.pdf k.c s.doc $ ls > pippo $ more pippo indirizzi.pdf k.c s.doc

  28. Es: la redirezione (2) • La shell permette di ridirigere stdin/out/error. Es (2) $ more pippo i.pdf s.doc k.c $ sort < pippo k.c i.pdf s.doc

  29. Es: la redirezione (3) • Redirezione dello stdout ed error su file diversi $ more pippo.c pluto.c 1> out 2> log

  30. Es: la redirezione (3) • Redirezione dello stdout ed error su file diversi $ more pippo.c pluto.c > out &> log

  31. Es: la redirezione (3) • Redirezione dello stdout ed error su file diversi $ more pippo.c pluto.c 1> out 2> log $ more log pippo.c: No such file or directory

  32. Es: la redirezione (3) • Redirezione dello stdout ed error su file diversi $ more pippo.c pluto.c 1> out 2> log $ more log pippo.c: No such file or directory $ more out /* frammento che stampa il pid del processo in esecuzione e quello del padre usando la macro WRITE di stampa (in sysmacro.h) … */ char buf[N]; /* stringa da stampare */ … sprintf(buf,”Processo %d, mio padre e’ %d\n.”, getpid(),getppid());

  33. Es: la redirezione (3.1) • Attenzione: out e log vengono sovrascritti!!!!! • Per appendere usare ‘>>’ $ more pippo.c pluto.c 1>> out 2>> log

  34. Es: la redirezione (3.1) • Attenzione: out e log vengono sovrascritti!!!!! • Per appendere usare ‘>>’ $ more pippo.c pluto.c 1>> out 2>> log $ more log pippo.c: No such file or directory pippo.c: No such file or directory

  35. Es: redirezione con dup() e dup2() • Es. voglio ridirigere lo standard output (file descriptor 1) su un file pippo int fd; ... IFERROR(fd=open(“pippo”,O_WRONLY|O_TRUNC|O_CREAT,0644),”nella open”); dup2(fd,STDOUT); /* duplica fd sullo standard output*/ close(fd); /* fd non serve piu’ */ printf(“Questo viene scritto in pippo!”); ...

  36. Come la shell implementa la redirezione ... • Es. $ ls -l > pippo • Il processo shell si duplica con una fork()e si mette in attesa della terminazione del figlio con unawait • Il figlio apre in scrittura il file pippo (creandolo o troncandolo) • Il figlio duplica il descrittore di pippo con la dup2 sullo stdout e chiude il descrittore originario • Il figlio invoca una exec di ls -l, la quale conserva i descrittori dei file, e quindi va a scrivere in pippo ogni volta che usa il file descriptor 1

  37. Come la shell implementa la redirezione … (2) • Es. $ ls -l > pippo(cont.) • Quando il figlio termina, il padre riprende la computazione con i sui descrittori di file invariati. • (padre e figlio hanno ognuno la sua tabella dei descrittori e casomai puntano alla stessa locazione della tabella dei file aperti)

More Related