In un sistema Linux i file rivestono un ruolo fondamentale, infatti oltre ad essere i soliti contenitori di dati, informazioni, eseguibili e quant’altro debba essere memorizzato ed archiviato in modo permanente, rappresentano anche il modo per usare dispositivi come hard disk o porte seriali. Ogni periferica infatti è vista dal sistema operativo come un file su cui scrivere o da cui leggere, saper usare quindi le funzioni a basso livello dell’I/O è di fondamentale importanza nella programmazione del sistema operativo Linux. In questo articolo vedremo le differenze tra le funzioni della libreria standard del C ( ANSI C ) e le API ( Application Programming Interface ), le primitive offerte dallo strato più alto del nucleo Linux, per fare I/O e gestire i file.
Tutti i compilatori conformi allo standard ANSI devono offrire una serie di funzioni destinate a svolgere compiti più o meno complessi, tutte queste funzioni sono contenute all’interno della libreria standard. In particolare queste funzioni si chiameranno allo stesso modo in tutti i sistemi operativi e quindi permettono di scrivere sorgenti portabili da un’architettura all’altra. Ad esempio lo standard ANSI ha definito una struttura chiamata FILE che contiene le informazioni su un file ed alcune funzioni per la sua gestione, queste operano su stream ( flusso ) di dati ovvero un puntatore ad una struttura FILE. Ecco un esempio di programmazione di file in standard C su Linux:
/* File testfile.c Compilare con : gcc -Wall -o testfile testfile.c */ #include <stdio.h> int main(int argc, char** argv) { FILE* f; char buffer[100]; f = fopen("testfile.txt", "w"); fprintf(f, "Questo è solo un test di scrittura e lettura su file\n"); fclose(f); f = fopen("testfile.txt", "r"); while (fscanf(f, "%s", buffer) != EOF) { printf("%s", buffer); printf("%c", ' '); } fclose(f); printf("%c", '\n'); return 0; }
Su Linux un programma utente accede ad un file attraverso un identificatore chiamato descrittore di file, che è un numero intero associato dal sistema operativo ad un file nel momento in cui viene aperto e chiuso da un programma. Il descrittore di file è semanticamente equivalente ad una struttura FILE della libreria standard, serve infatti ad identificare un file al posto del suo nome. Il sistema operativo tiene conto dei file aperti attraverso una tabella dei descrittori di fileche raccoglie appunto tutti i descrittori di file aperti. I primi tre descrittori di file ( 0, 1, 2 ) di questa tabella sono aperti automaticamente dalla shell all’avvio di un programma:
Come sicuramente saprete da linea di comando è possibile redirezionarli dove si vuole, anche su un file. cat /etc/profile > myprofile.txtUtilizzando le funzioni delle API del sistema operativo Linux, l’esempio di prima, scritto per lo standard C, può essere riscritto come:
/* File testfile.c Compilare con : gcc -Wall -o testfile testfile.c */ #include <sys/types.h> #include <unistd.h> #include <fcntl.h> int main(int argc, char** argv) { int f; char buffer[100]; f = open("testfile.txt", O_CREAT|O_WRONLY, 0750); write(f, "Questo è solo un test di scrittura e lettura su file\n", 60); close(f); f = open("testfile.txt", O_RDONLY); read(f, buffer, 99); close(f); write(1, buffer, 60); return 0; }
Come potete notare ora possiamo lavorare con i descrittori di file e non più con la struttura FILE dello standard C ANSI. Altra cosa da notare è che al momento della creazione del file abbiamo inserito 0750 ( per i permessi dei file in Linux vi consiglio la lettura di questo articolo ) per fare in modo di poterlo leggere successivamente, caratteristica tipica di Linux.
Se leggete la definizione di file noterete che si tratta di una struttura dati omogenea ad accesso sequenziale, ossia che solo dopo aver acceduto a quelli che le precedono si possono leggere o scrivere i dati successivi. Nel caso ci servisse di leggere l’ultima parte ben definita di un file, possiamo saltare le parti precedenti con la funzione lseek così definita:
long lseek(int fd, long offset, int control)
Questa funzione consente di specificare la nuova posizione corrente composta da due parti, base + offset, il primo è il puntatore di partenza al quale sommare l’offset, cioè i
l numero di caratteri da saltare. Base è controllato da un terzo argomento che può avere questi valori:
la funzione restituisce la nuova posizione del puntatore, ecco un semplice esempio d’uso:
... f = open("testfile.txt", O_RDONLY); lseek(f, -20, 2); read(f, buffer, 20); close(f); write(1, buffer, 20); ...
La libreria standard fornisce una funzione simile che si chiama fseek. Per uno studio approfondito delle dichiarazioni delle funzioni sia standard che API potete vedere la documentazione in linea.
Sono arrivato alla convinzione che un abbonamento per tutti i miei software gestionali sia il…
MerciGest è un software per la gestione del magazzino completamente gratuito. Continua a leggere→
In ufficio può capitare di doversi allontanare dal proprio posto di lavoro, ecco che allora…
In questo articolo vedremo quando è più o meno utile togliere la corrente ad un…
Dopo la pausa invernale dovuta al lavoro che devo fare per sostentarmi, eccomi di nuovo…
Vediamo come eliminare i files direttamente da Windows senza utilizzare il cestino. Continua a leggere→