Sistemi operativi - Gestione dei File
Transcript
Sistemi operativi - Gestione dei File
Program m azione di Sist em a – 2 Lucidi per il corso di Laboratorio di Sistemi Operativi tenuto da Paolo Baldan presso l'Università Ca' Foscari di Venezia, anno accademico 2004/ 2005. Parte di questo materiale è rielaborato dai lucidi del Corso di Laboratorio di Sistemi Operativi tenuto da Rosario Pugliese presso l'Università di Firenze, anno accademico 2001/ 02. UNIX: Program m azione di Sist em a Per ut ilizzare i servizi offert i da UNIX, quali creazione di file, duplicazione di processi e com unicazione t ra processi, i program m i applicat ivi devono int eragire con il sist em a operat ivo. Per far ciò devono usare un insiem e di rout ine det t e syst em call, che cost it uiscono l'int erfaccia funzionale del program m at ore col nucleo di UNIX. Le syst em call sono sim ili alle rout ine di libreria C m a eseguono una chiam at a di subrout ine diret t am ent e nel nucleo di UNIX. 2 UNIX: Syst em Call Le syst em call sono delle “ ent ry point ” per il kernel. Il program m at ore chiam a la funzione ut ilizzando la sint assi usuale delle funzioni C int open(const char *path, int mode) La funzione invoca, nel m odo opport uno, il servizio del sist em a operat ivo “ salva” gli argom ent i della syst em call ed un num ero ident ificat ivo della syst em call st essa (in regist ri) esegue una ist ruzione m acchina t rap, int , ... (sezione 2 di man: man 2 syscall). 3 UNIX: Funzioni di libreria Le funzioni di libreria forniscono servizi di ut ilit à generale al program m at ore Non sono ent ry point del kernel, anche se possono far uso di syst em call per realizzare il proprio servizio. Es. print f può ut ilizzare la syst em call writ e per st am pare st rcpy (st ring copy) e at oi (convert ASCII t o int eger) non coinvolgono il sist em a operat ivo. Possono essere sost it uit e con alt re funzioni che realizzano lo st esso com pit o (in generale non possibile per le syst em call). (sezione 3 di man: man 3 libfun). 4 UNIX: Program m azione di Sist em a Le chiam at e di sist em a possono essere raggruppat e in t re cat egorie principali gest ione dei file, gest ione degli errori, gest ione dei processi. La com unicazione t ra processi (IPC - int erprocess com m unicat ion) rient ra nella gest ione dei file poiché UNIX t rat t a i m eccanism i per IPC com e file speciali. Per ut ilizzare le syst em call sono fornit i opport uni file di int est azione. Ad es. sys/file.h errno.h 5 Gerarchia di Syst em Call: File File open close read lseek unlink dup2 chown chmod fcntl truncate ftruncate sync write dup stat link Sp ecia li Directory get_dents mknod ioctl pipe In tern et Sock et Sock et accept bind listen socket connect gethostbyname gethostname htonl htons inet_addr inet_ntoa 6 Gerarchia di Syst em Call: Processi Gestion e Processi nice exec getppid getruid chdir exit setuid wait set_gid getgid fork set_grp getuid Segn ali alarm kill signal pause Errori perror 7 Gest ione dei File Gest ione dei File Le syst em call per la gest ione dei file perm et t ono di m anipolare file regolari, direct ory, file speciali. Tra i file speciali link sim bolici, disposit ivi (t erm inali, st am pant i), m eccanism i di IPC (pipe e socket ). 9 Gest ione dei File: Operazioni di Base Le syst em call descrit t e nella prim a part e realizzano le operazioni di base per la gest ione dei file open() - apert ura read() - let t ura write() - scrit t ura lseek() - posizionam ent o close() - chiusura Unbuffered I/O (vs. buffered I/O library: t ipo FILE e funzioni fopen, fread, fwrite, ...) Non sono veram ent e unbuffered ... 10 File: Tipica Sequenza di Operazioni int fd; / * dichiara un descrittore di file */ ... fd = open(fileName, ...); / * apre un file ; fd è il descrittore */ if (fd = = - 1) { ... / * gestisce l'errore */ }; ... fcntl(fd, ...); / * modifica alcuni flag di I/ O */ ... read(fd, ...); / * legge dal file */ ... write(fd, ...); / * scrive nel file */ ... lseek(fd, ...); / * si sposta all'interno del file */ ... close(fd); / * chiude il file, liberando il descrittore */ ... unlink(fileName); / * rimuove il file */ ... 11 Gest ione dei File Per accedere a un file quest o deve essere apert o t ram it e la syst em call open() localizza il file nel filesyst em t ram it e il suo pat hnam e; copia nella t abella degli i-node at t ivi l'i-node corrispondent e al file; alloca una ent ry nella t abella dei file apert i globale; alloca una ent ry nella t abella dei descrit t ori di file apert i del processo; open() rit orna un int ero posit ivo fd, det t o descrit t ore di file, ut ilizzat o nelle successive operazioni di I/O sul file, se ha successo; -1 se fallisce. 12 Gest ione dei File: St rut t ure dat i p r oce ss t a b le op e n f ile t a b le file de s file st a t us fla g fd curre nt offse t a ct ive i-node pt r a ct ive i-n od e i- n ode in fo file siz e Il process cont rol block di ciascun processo cont iene una t abella di punt at ori a file descript or present i nella t abella dei file apert i. La t abella dei file apert i cont iene un file descript or per ogni file apert o nel sist em a, con un punt at ore alla t abella degli i-node at t ivi. La t abella degli i-node at t ivi cont iene l'i-node per ogni file che sia apert o (una o più volt e) nel sist em a. 13 Descrit t ore di File Molt e syst em call di I/O richiedono com e prim o argom ent o un (punt at ore a un) descrit t ore di file. Ogni descrit t ore riferisce un insiem e di propriet à (che sono indipendent i da quelle del file a cui punt a) Punt at ore di let t ura/scrit t ura offset , rispet t o all'inizio del file della posizione a cui st a leggendo o scrivendo; inizializzat o a 0 alla creazione del descrit t ore; aggiornat o ad ogni operazione di let t ura/scrit t ura nel file. Flag close on exec indica se il descrit t ore deve essere chiuso aut om at icam . all'invocazione di una syst em call della fam iglia exec(). Flag append indica se l'out put sul file deve essere inserit o in fondo. 14 Descrit t ore di File Se il file è speciale (es. pipe o socket ), ci sono alt re propriet à associat e al descrit t ore Flag blocking indica se un processo si deve bloccare quando t ent a di leggere dal file e quest o è vuot o. SIGIO pid/gid ident ificat ore di processo o di gruppo a cui va spedit o un segnale SIGIO quando l'input sul file divent a disponibile. Le propriet à associat e ad un descrit t ore possono esser m anipolat e t ram it e le syst em call open() e fcntl(). 15 Descrit t ore di File Un file può essere apert o più volt e con descrit t ori diversi (anche dallo st esso processo) p r oce ss t a b le file de s op e n f ile t a b le file st a t us fla g curre nt offse t a ct ive i-n od e i-node info file size a ct ive i-node pt r file st a t us fla g cur re nt offse t a ct ive i-node pt r fd1=open(“myfile”, ...) fd2=open(“myfile”, ...) 16 Descrit t ore di File Uno st esso descrit t ore può essere riferit o da più ent ry delle t abelle dei processi all'int erno dello st esso processo (t ram it e dup()) ... p r oce ss t a b le op e n f ile t a b le a ct ive i-n od e file de s file st a t us fla g i-node info curre nt offse t file size a ct ive i-node pt r 17 Descrit t ore di File Uno st esso descrit t ore può essere riferit o da più ent ry delle t abelle dei processi in processi diversi (t ram it e fork()) p r oce ss t a b le fa t he r file de s op e n f ile t a b le a ct ive i-n od e file st a t us fla g i-node info curre nt offse t file size a ct ive i-node pt r ch ild file de s fd = open(“myfile”, ...) fork() 18 Descrit t ore di File I descrit t ori sono num erat i a part ire da 0. I prim i t re hanno un significat o part icolare 0: corrisponde allo st andard input ; 1: corrisponde allo st andard out put ; 2: corrisponde allo st andard error. 19 Gest ione dei File: Chiusura Quando un processo non ha più bisogno di un file apert o, lo chiude invocando close(). Tut t i i file apert i da un processo sono chiusi aut om at ic. quando il processo t erm ina (m a è buona prat ica di program m azione chiudere esplicit am ent e i file apert i). Quando il riferim ent o ad un file viene chiuso la corrispondent e ent ry nella process t able viene liberat a e può essere riassegnat a da una successiva open(); se non ci sono alt ri punt at ori alla ent ry nella open file t able, anche quest a viene liberat a; se il file non è apert o in nessun processo anche l'i-node nella t abella degli act ive i-node viene deallocat o. 20 Esem pio: reverse.c reverse -c [fileName] Invert e le linee di input let t e da fileName e le m ost ra sullo st andard out put . Se non si specifica alcun file di input , reverse invert e lo st andard input . Con l'opzione -c, reverse invert e anche i carat t eri su ogni linea. [ reverseLine.c] 21 reverse.c #include <fcntl.h> /* For file mode definitions */ #include <stdio.h> #include <stdlib.h> /* Enumerator */ enum { FALSE, TRUE }; /* Standard false and true values */ enum { STDIN, STDOUT, STDERR }; /* Standard I/O channel */ /* #define Statements */ #define BUFFER_SIZE 4096 /* Copy buffer size */ #define NAME_SIZE 12 #define MAX_LINES 100000 /* Max lines in file */ /* Globals */ char *fileName = NULL; /* Points to file name */ char tmpName [NAME_SIZE]; int charOption = FALSE; /* Set to true if -c option is used */ int standardInput = FALSE; /* Set to true if reading stdin */ int lineCount = 0; /* Total number of lines in input */ int lineStart [MAX_LINES]; /* Store offsets of each line */ int fileOffset = 0; /* Current position in input */ int fd; /* File descriptor of input */ 22 reverse.c int main(int argc, char *argv[]) { parseCommandLine (argc,argv); /* Parse command line */ pass1 (); /* Perform first pass through input */ pass2 (); /* Perform second pass through input */ return (/* EXIT SUCCESS */ 0); /* Done */ } /***********************************************************/ int parseCommandLine (int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) { if(argv[i][0] == '-') processOptions (argv[i]); else if (fileName == NULL) fileName = argv[i]; else usageError (); /* An error occurred */ } standardInput = (fileName == NULL); } 23 reverse.c int processOptions (char *str) { int j; for (j = 1; str[j] != '\0'; j++) { switch(str[j]) { /* Switch on command line flag */ case'c': charOption = TRUE; break; default: usageError (); break; } } } /***********************************************************/ int usageError (void) { fprintf (stderr, "Usage: reverse -c [filename]\n"); exit (/* EXITFAILURE */ 1); } 24 reverse.c int pass1 (void) { /* Perform first scan through file */ int tmpfd, charsRead, charsWritten; char buffer [BUFFER_SIZE]; if (standardInput) { /* Read from standard input */ fd = STDIN; sprintf (tmpName, ".rev.%d", getpid ()); /* Random name */ /* Create temporary file to store copy of input */ tmpfd = open (tmpName, O_CREAT | O_RDWR, 0600); if (tmpfd == -1) fatalError (); } else { /* Open named file for reading */ fd = open (fileName, O_RDONLY); if (fd == -1) fatalError (); } 25 reverse.c lineStart[0] = 0; /* Offset of first line */ while (TRUE) { /* Read all input */ /* Fill buffer */ charsRead = read (fd, buffer, BUFFER_SIZE); if (charsRead == 0) break; /* EOF */ if (charsRead == -1) fatalError (); /* Error */ trackLines (buffer, charsRead); /* Process line */ /* Copy line to temporary file if reading from stdin */ if (standardInput) { charsWritten = write (tmpfd, buffer, charsRead); if(charsWritten != charsRead) fatalError (); } } /* Store offset of trailing line */ lineStart[lineCount] = fileOffset; /* If reading from standard input, prepare fd for pass2 */ if (standardInput) fd = tmpfd; } 26 reverse.c int trackLines (char *buffer, int charsRead) { /* Store offsets of each line start in buffer */ int i; for (i = 0; i < charsRead; i++) { ++fileOffset; /* Update current file position */ if (buffer[i] == '\n') lineStart[++lineCount] = fileOffset; } } /*************************************************************/ int pass2 (void) { /* Scan input file again, displaying lines in reverse order */ int i; for (i = lineCount - 1; i >= 0; i--) processLine (i); close (fd); /* Close input file */ if (standardInput) unlink (tmpName); /* Remove temp file */ } 27 reverse.c int processLine (int i) { /* Read a line and display it */ int charsRead; char buffer [BUFFER_SIZE]; /* Find the line and read it */ lseek (fd, lineStart[i], SEEK_SET); charsRead = read (fd, buffer, lineStart[i+1] - lineStart[i]); /* Reverse line if -c option was selected */ if (charOption) reverseLine (buffer, charsRead); /* Write it to standard output */ write (1, buffer, charsRead); } 28 reverse.c int reverseLine (char *buffer, int size) { /* Reverse all the characters in the buffer */ int start = 0, end = size - 1; char tmp; if (buffer[end] == '\n') --end; /* Leave trailing newline */ /* Swap characters in a pairwise fashion */ while (start < end) { tmp = buffer[start]; buffer[start] = buffer[end]; buffer[end] = tmp; ++start; /* Increment start index */ --end; /* Decrement end index */ } } /************************************************************/ int fatalError (void) { perror ("reverse: "); /* Describe error */ exit (1); } 29 open() int open(char *path, int mode [,mode_t perms]) apre (o crea) un file in let t ura e/o scrit t ura path: pat hnam e assolut o o relat ivo del file. mode: indica la m odalit à di apert ura si ot t iene com binando, t ram it e l'operat ore ` |', flag di let t ura/scrit t ura ed event ualm ent e alt ri flag. perms:perm essi di accesso al file (in form a ot t ale o con cost ant i) è specificat o solo quando il file è creat o; sui perm essi influisce anche il valore di um ask. open() rest it uisce un int ero non negat ivo fd, se ha successo; alt rim ent i, rest it uisce il valore -1. 30 open(): Flag di let t ura/scrit t ura I valori predefinit i dei flag sono nel file fcntl.h. Flag di let t ura/scrit t ura sono O_RDONLY: apert ura in sola let t ura (0); O_WRONLY: apert ura in sola scrit t ura (1); O_RDWR : apert ura in let t ura e scrit t ura (2). Solo una di quest e cost ant i può com parire in m ode. Alt re cost ant i (aggiunt e in or “ |” a una di quest e t re) definiscono alt ri com port am ent i. 31 open(): Alt ri flag O_APPEND: Il punt at ore al file è posizionat o alla fine del file prim a di ogni write(). O_CREAT: Se il file non esist e viene creat o l'UID “ effet t ivo” del processo è usat o com e ID del possessore; il param et ro perm (se present e) det erm ina, insiem e con um ask, i perm essi iniziali sul file. O_EXCL: Con O_CREAT, se il file esist e open() fallisce. O_NONBLOCK: Per pipe e socket se il flag è at t ivo open() in sola lett ura t erm ina im m ediatam ente, a prescindere dal fatt o che il lat o di scrittura sia aperto o no; open() in sola scrittura fallisce se il lato di lett ura non è apert o; se il flag non è at t ivo una open() su un file in sola lett ura o in sola scrittura si blocca fino a che l'altro lat o non è apert o. O_TRUNC: Se il file esist e, è t roncat o a lunghezza 0. 32 open(): esem pi sprintf(tmpName, ".rev.%d", getpid()); /* Random name */ /* Create temporary file to store a copy of input */ tmpfd = open (tmpName, O_CREAT | O_RDWR, 0600); if (tmpfd == -1) fatalError (); La syst em call getpid() rest it uisce il PID del processo chiam ant e. Quest o è unico in t ut t o il sist em a, per cui si usa spesso per generare nom i unici per file t em poranei. Per creare il file si usa il flag O_CREAT e si im post ano i perm essi iniziali t ram it e cifre ot t ali. fd = open (fileName, O_RDONLY); if (fd == -1) fatalError (); Per aprire il file fileName esist ent e si specifica solo il flag di let t ura/scrit t ura. 33 read() ssize_t read(int fd, void *buf, size_t count) Copia nel buffer buf una sequenza di count byt e let t i a part ire dalla posizione corrent e del file riferit o dal descrit t ore fd. Aggiorna il punt at ore di let t ura/scrit t ura. Legge quant i più byt e possibile, fino ad un m assim o di count , e rit orna il num ero dei byt e effet t ivam ent e let t i (senza cont are l'event uale carat t ere EOF). In part icolare, se invocat a dopo che si è già let t o l'ult im o byt e, rest it uisce il valore 0, che indica la fine del file. Se fallisce rest it uisce il valore -1. 34 read() Not a: read() esegue input di basso livello non ha le capacit à di form at t azione di scanf(), m a... salt a lo st rat o int erm edio delle funzioni di libreria C e quindi risult a m olt o più veloce. Es. while (TRUE) { charsRead = read (fd, buffer, BUFFER_SIZE); if (charsRead == 0) break; /* EOF */ if (charsRead == -1) fatalError (); /* Error */ } read è usat a per legger BUFFER_SIZE carat t eri per volt a. 35 writ e() ssize_t write(int fd, void *buf, size_t count) Scrive nel file riferit o dal descrit t ore fd una sequenza di count byt e let t i dal buffer buf. Se il flag O_APPEND è st at o at t ivat o, prim a di ogni scrit t ura il punt at ore è spost at o alla fine del file. Alt rim ent i scrive a part ire dalla posizione corrent e. Aggiorna il punt at ore di let t ura/scrit t ura. Scrive quant i più byt e possibile, fino ad un m assim o di count, e rit orna il num ero dei byt e effet t ivam ent e scrit t i. Se write() rit orna un valore inferiore a count probabilm . il disco è pieno. Se fallisce rest it uisce il valore -1. 36 writ e(): esem pi Not a: Valgono per write(), rispet t o a printf(), le considerazioni fat t e per read(), rispet t o a scanf(). Es. /* Copy line to temporary file if reading from stdin */ if (standardInput) { charsWritten = write (tmpfd, buffer, charsRead); if (charsWritten != charsRead) fatalError (); } 37 lseek() off_t lseek(int fd, off_t offset, int mode) Dat o il descrit t ore di file fd, spost a il punt at ore alla posizione corrent e di offset byt e. mode specifica com e int erpret are offset. I t re possibili valori sono definit i in stdio.h SEEK_SET: offset relat ivo all'inizio del file; SEEK_CUR: offset relat ivo alla posizione corrent e; SEEK_END: offset relat ivo alla fine del file; fallisce se si t ent a di m uovere il punt at ore ad un punt o che precede l'inizio del file; est ende il file se si spost a il punt at ore olt re la fine (senza allocare spazio, nel file si crea un “ buco” ). Rit orno la posizione corrent e, se ha successo; rit orna il valore -1, alt rim ent i. 38 lseek(): esem pi lseek (fd, lineStart[i], SEEK_SET); /* Find the line and read it */ charsRead = read (fd, buffer, lineStart[i+1]–lineStart[i]); lineStart[i] cont iene la posizione, relat iva all'inizio del file, del prim o carat t ere della riga i-m a. Quindi lseek() spost a il punt at ore all'inizio di t ale riga. La lunghezza della riga è calcolat a com e lineStart[i+1]–lineStart[i] e viene let t a l'int era riga. currentOffset = lseek (fd, 0, SEEK_CUR); m em orizza nella variabile currentOffset la posizione corrent e, senza spost are il punt at ore. 39 lseek(): Olt re la fine Se si esegue una lseek() spost ando il punt at ore olt re la fine del file ... Se si esegue una write(), il nucleo del SO est ende aut om at icam ent e la dim ensione del file. Not a: viene m odificat o il cam po file size nella t abella degli i-node at t ivi, e quindi la m odifica è visibile anche a chi operi sul file t ram it e un alt ro descrit t ore. L'area int erm edia del file è t rat t at a com e se fosse riem pit a da carat t eri NULL (codifica ASCII 0). Tut t avia, non viene allocat o spazio disco per l'area int erm edia e quindi il file occupa m eno spazio disco di uno analogo in cui i carat t eri NULL siano st at i inserit i esplicit am ent e dall'ut ent e. 40 close() int close(int fd) Libera il descrit t ore di file fd. Se fd è l'ult im o descrit t ore associat o al file, le risorse del nucleo per quel file vengono deallocat e. Quando un processo t erm ina, t ut t i i suoi descrit t ori di file sono chiusi aut om at icam ent e, m a è preferibile chiuderli esplicit am ent e quando non servono più. Se si chiude un descrit t ore che era già chiuso, si verifica un errore. Rest it uisce il valore 0, se ha successo; rest it uisce il valore -1, alt rim ent i. Not a: Quando un file viene chiuso, non è garant it o che i buffer associat i siano im m ediat am ent e sc aricat i su disco (cfr. sync()). 41 Esem pio: m ycopy.c /* mycopy src trg: crea una copia del file src e la chiama trg */ #include <stdio.h> #include <sys/file.h> #define BUFFSIZE 8192 int main(int argc, char *argv[]) { int fdSource; /* file descriptor per il file origine */ int fdTarget; /* file descriptor per il file copia*/ int n; char buf[BUFFSIZE]; /* buffer di transizione */ fdSource = open(argv[1], O_RDONLY); fdTarget = open(argv[2], O_WRONLY | O_CREAT, 0600); /* copia il file sorgente sul target a blocchi di BUFFSIZE byte */ while ( (n = read(fdSource, buf, BUFFSIZE)) > 0 ) if (write(fdTarget, buf, n) != n) { perror("write error"); exit(1); } } 42 Esem pio: invert .c #include <stdio.h> #include <sys/file.h> invert <file>: stam pa il file d i testo in in pu t in v ertito. int main(int argc, char *argv[]) { int fd; char buff; const int charSize = sizeof(char); if (argc != 2) { printf("invert: Usage invert <txtFile>\n"); exit(-1); } fd = open(argv[1], O_RDONLY); lseek(fd, 0, SEEK_END); /* Si posiziona alla fine del file */ /* legge il file al contrario: ad ogni passo sposta il puntatore di due passi indietro, perche' la lettura lo aggiorna */ while (lseek(fd, -2*charSize, SEEK_CUR) != -1) { read(fd, &buff, charSize); printf("%c", buff); } } 43 At om icit à delle operazioni Se un file (descript or) è condiviso t ra processi possono verificarsi int erazioni indesiderat e. Esem pio: Append realizzat a con lseek(fd, 0, SEEK_END); write(fd, buff,...); Problem a: Un alt ro processo pot rebbe [ est endere il file / spost are il punt at ore] t ra la lseek e la scrit t ura. Soluzione: Flag O_APPEND di open. Esem pio: Creazione di un file se non esist e if open(nome, O_RDONLY)< 0)open(nome,O_CREAT) Problem a: Un processo pot rebbe creare il file t ra le open! Soluzione: Flag O_EXECL di open con O_CREAT. 44 Gest ione degli errori: perror() Una syst em call rit orna -1 se fallisce. Per gest ire gli errori originat i dalle syst em call, i due principali ingredient i da ut ilizzare sono errno variabile globale che cont iene il codice num erico dell'ult im o errore generat o da una syst em call; perror() subrout ine che m ost ra una descrizione “ t est uale” dell'ult im o errore generat o dall'invocazione di una syst em call. 45 Gest ione degli errori: errno Ogni processo ha una variabile globale errno inizializzat a a 0 quando il processo è creat o; se si verifica un errore dovut o ad una syst em call, ad errno è assegnat o un codice num erico corrispondent e; errno.h cont iene codici di errore predefinit i. Es. #define EPERM 1 /* Not owner */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */ #define EINTR 4 /* Interrupted system call */ #define EIO 5 /* I/O error */ Una syst em call che fallisce sovrascrive il valore di errno. Una eseguit a con successo ... dipende (m eglio 46 salvare l'errore, se serve). Gest ione degli errori: perror() void perror (char *str) Most ra la st ringa str, seguit a da “ :” e da una st ringa che descrive il valore corrent e di errno (chiusa da newline). Se non ci sono errori da riport are, viene m ost rat a la st ringa Error 0 (o, in alcuni sist em i, Success). Non è una syst em call, m a una rout ine di libreria. Per accedere alla variabile errno ed invocare perror() occorre includere il file errno.h. I program m i dovrebbero cont rollare se il valore rit ornat o da una syst em call è -1 e, in quest o caso, invocare perror() per una descrizione dell'errore. 47 Esem pio: showErrno.c #include <stdio.h> #include <fcntl.h> #include <errno.h> int main(void) { int fd; /* Open a non-existent file to cause an error */ fd = open ("nonexist.txt", O_RDONLY); if (fd == -1) { /* fd == -1 => an error occurred */ printf ("errno = %d\n", errno); perror ("main"); }; fd = open ("/", O_WRONLY); /* Force a different error */ if (fd == -1) { printf ("errno = %d\n", errno); perror ("main"); }; /* continua ... */ 48 Gest ione degli errori: perror() /* Execute a successful system call */ fd = open ("nonexist.txt", O_RDONLY | O_CREAT, 0644); printf ("errno = %d\n", errno); /* Display after successful call */ perror ("main"); errno = 0; /* Manually reset error variable */ perror ("main"); return 0; } Ou tpu t del program m a $ showErrno errno = 2 main: No such file or directory errno = 21 main: Is a directory errno = 21 main: Is a directory (?) / Illegal seek! main: Error 0 / Success $ 49