Introduzione ai sistemi operativi con UNIX
Prec 3. Alcune system call di UNIX per l'I/O Succ

3.1 read

La system call read è dichiarata nel seguente modo:
ssize_t
     read(int d, void *buf, size_t nbytes);
e il significato dei parametri è il seguente:
d
descrittore che riferisce il dispositivo da leggere
buf
puntatore al buffer in cui inserire i byte letti
nbytes
numero di byte da leggere
le definizioni dei tipi di dati non primitivi coinvolti sono:
size_t
unsigned int
ssize_t
int
Se la chiamata ha successo il valore di ritorno rappresenta il numero di byte che sono stati effettivamente letti e memorizzati in buf, che può essere inferiore a quello richiesto (il valore di nbytes), ad esempio semplicemente perchè dalla posizione corrente fino alla fine del file, il file da cui si sta leggendo ha meno di nbytes byte. Se viene incontrata la fine del file viene restituito uno zero. La ragione percui il tipo di ssize_t è con segno è che viene ritornato il valore -1 in caso di errore. In tal caso viene anche settata una (pseudo) variabile globale errno che contiene il codice numerico dell'errore, mentre se tutto va bene, la errno non viene cambiata. In questo modo errno riflette sempre il codice dell'ultimo errore verificatosi. Per maggiore leggibilità esistono definizioni di costanti simboliche in /usr/include/sys/errno.h che possono essere usate al posto dei codici numerici. Riporto di seguito solo quelle che può impostare la read(2) in errno:
#define EBADF           9               /* Bad file descriptor */
#define EFAULT          14              /* Bad address */
#define EIO             5               /* Input/output error */
#define EINTR           4               /* Interrupted system call */
#define EINVAL          22              /* Invalid argument */
#define EAGAIN          35              /* Resource temporarily unavailable */
L'interpretazione precisa di codici errori di questo tipo, che sono utilizzati da più system call dipende ovviamente dal tipo di system call e dalle circostanze della chiamata. Ad esempio la manpage read(2) descrive meglio le ragioni di ciascuno degli errori precedenti. Per stampare messaggi di errori descrittivi, utilizzate la funzione della libreria standard del C perror(3). L'header <string.h> contiene inoltre le due funzioni strerror(3) e strerror_r(3) utili rispettivamente per ottenere un puntatore alla stringa costante del messaggio di errore corrispondente ad un numero di errore o per copiare tale stringa in un proprio vettore di caratteri, in modo da poterla anche modificare.

È molto importante che buf punti ad una area di memoria correttamente allocata ad esempio tramite malloc(3) con dimensioni minimo pari a nbytes bytes e non di meno, per evitare accessi illegali alla memoria o peggio subdole modificazioni di altri dati del processo che non producono alcun errore immediato. In C il programmatore è responsabile di allocare e deallocare correttamente la memoria. Il kernel da parte sua può controllare solamente che l'indirizzo di memoria a cui punta buf sia parte dello spazio indirizzi del processo che la invoca.

La read(2) per default quando legge da terminale si ferma dopo aver letto un newline. Anche questo è un altro caso in cui la read(2) può restituire un numero di byte inferiore a quello richiesto senza che si verifichi alcun errore. Questo comportamento è comodo perchè di solito il punto di vista sull'input dei programmi interattivi è a linee, talora persino a singoli caratteri.


Prec Indice Succ
Alcune system call di UNIX per l'I/O Livello superiore write