File system - interfaccia, directory e implementazione
In questa pagina 9
Il file system è la parte del sistema operativo che dà un'interfaccia uniforme alla memoria di massa (Memoria di massa e scheduling del discoLa memoria di massa è fatta di dischi rigidi (HDD: piatti, tracce, cilindri, settori) e memorie non volatili NAND (SSD); tempo di accesso HDD = seek + latenza rotazionale (mezzo giro, 30/RPM secondi), tempo di I/O = accesso + trasferimento + overhead del controller; i blocchi sono indirizzati con un LBA lineare; per l'HDD si minimizza il seek con FCFS, SSTF (rischio di starvation), SCAN (ascensore) e C-SCAN (più uniforme), con le varianti LOOK e C-LOOK e il deadline di Linux; per le NVM contano FTL, garbage collection, overprovisioning e wear leveling; il sistema operativo formatta (fisico e logico), partiziona, gestisce il boot e lo spazio di swap; parità ed ECC rilevano e correggono errori; il RAID usa striping, mirroring e parità (livelli 0, 1, 4, 5, 6, 10) per più velocità e affidabilità, con MTTDL = 1/PDL.Memoria di massa e scheduling del disco →). Questa nota ha tre parti: l'interfaccia (che cosa vede il programmatore e l'utente), la struttura e l'implementazione (come si mappano i file sui blocchi) e il montaggio con i file system virtuali e remoti. Le system call sui file sono in System call POSIX, file descriptor e API delle socketLe system call sono le funzioni con cui un programma in user space chiede servizi al kernel (open, read, write, close, fork, pipe, dup2, socket, bind, listen, accept, connect); restituiscono -1 e impostano errno in caso di errore; un file descriptor e' un intero che indicizza la tabella dei file aperti del processo (0 stdin, 1 stdout, 2 stderr) e vale per file, pipe e socket; read e write possono trasferire MENO byte del richiesto (e sui socket TCP non c'e' nessun confine fra i messaggi), quindi servono cicli write_all e read_exact; l'API delle socket crea un punto finale di comunicazione (socket), lo lega a indirizzo e porta (bind), lo rende passivo (listen), accetta connessioni (accept) o si connette (connect); getaddrinfo traduce nomi e porte in indirizzi (IPv4 e IPv6); UDP usa sendto e recvfrom e conserva i confini dei datagrammi, TCP e' uno stream affidabile.System call POSIX, file descriptor e API delle socket →; i permessi e la sicurezza sono anche in Sicurezza e protezione nei sistemi operativiLe minacce all'accesso sono gli intrusi (masquerader, misfeasor, clandestine user) e il software malevolo (parassita: virus, logic bomb, backdoor; indipendente: worm, bot); contromisure: sistemi di rilevamento delle intrusioni (IDS, host o network, con sensori, analizzatori e interfaccia), autenticazione (identificazione + verifica con qualcosa che si sa, si ha, si è, si fa) e controllo degli accessi (permessi, sudo, SELinux, ACL, auditing, firewall); il buffer overflow scrive oltre un buffer nello stack e può sovrascrivere variabili o l'indirizzo di ritorno (code injection, shellcode); difese a compilazione (linguaggi sicuri, codice sicuro, librerie, stack protection con canarino) e a esecuzione (NX bit, ASLR, guard pages); sulla rete ci sono sniffing, spoofing e man-in-the-middle, e la crittografia (simmetrica e asimmetrica, RSA) limita mittenti e destinatari; la tolleranza ai guasti usa ridondanza (spaziale, temporale, informativa) e si misura con R(t), MTTF, MTTR e disponibilità.Sicurezza e protezione nei sistemi operativi →.
Il concetto di file
Definizione (file). Un file è uno spazio di indirizzi logici contigui, il cui contenuto è deciso da chi lo crea: dati (numerici, caratteri, binari) o programmi. Il tipo si riconosce spesso dall'estensione, che di solito non è obbligatoria: UNIX usa invece un numero magico (magic number) all'inizio del file.
Attributi
- Nome: l'unica informazione in forma leggibile da una persona.
- Identificatore: etichetta unica (un numero) che identifica il file nel file system.
- Tipo, posizione (puntatore alla posizione sul dispositivo), dimensione.
- Protezione: chi può leggere, scrivere, eseguire.
- Data, ora e identità dell'utente: per sicurezza e controllo dell'uso.
Queste informazioni stanno nella struttura delle directory, che si trova su disco. Esistono anche attributi estesi (checksum, codifica dei caratteri).
Operazioni
Creare; scrivere (alla posizione del puntatore di scrittura); leggere (posizione del puntatore di lettura); riposizionarsi (seek); cancellare; troncare; aprire (open: cerca il file sul disco e ne porta le informazioni in memoria); chiudere (close: toglie il file dalla memoria e aggiorna le informazioni su disco).
File aperti
Per gestire i file aperti il sistema usa:
- una tabella dei file aperti, una di sistema (condivisa) e una per processo;
- il puntatore al file: l'ultima posizione di lettura o scrittura;
- il contatore di aperture (file-open count): il numero di volte che il file è aperto; quando l'ultimo processo lo chiude si toglie la riga dalla tabella;
- la posizione su disco del file, tenuta in memoria per accedere ai dati;
- i diritti di accesso: la modalità di accesso di ogni processo.
Condivisione e lock
Alcuni sistemi offrono lock sui file. Un lock condiviso è come un lock da lettore: molti processi lo possono prendere insieme; un lock esclusivo è come quello da scrittore. Un lock obbligatorio (mandatory) nega l'accesso in base ai lock presi e richiesti; uno consultivo (advisory), usato in UNIX, lascia ai processi il compito di leggere lo stato del lock e decidere. Vedi Semafori, monitor e problemi classici di sincronizzazioneUn semaforo è un intero accessibile solo con due operazioni atomiche, wait (P: aspetta finché S > 0 e decrementa) e signal (V, in POSIX sem_post: incrementa); il semaforo contatore ha valori illimitati, quello binario vale 0 o 1; con valore iniziale 1 realizza la mutua esclusione, con valore iniziale 0 impone un ordine di esecuzione (S1 prima di S2); senza attesa attiva ogni semaforo ha una coda di processi sospesi (sleep e wakeup); i semafori si usano male con facilità (ordine sbagliato, omissioni); il monitor è un tipo di dato astratto in cui un solo processo alla volta è attivo e le variabili condizione x.wait()/x.signal() sospendono e risvegliano (in POSIX mutex più pthread_cond_t); le anomalie di liveness sono deadlock, starvation e inversione di priorità; i problemi classici sono produttore-consumatore a buffer limitato (mutex, vuote = n, piene = 0; l'ordine delle wait è importante), lettori-scrittori (rw_mutex, mutex, read_count; i lettori possono far morire di fame gli scrittori) e filosofi a cena (la soluzione ingenua con un semaforo per bacchetta va in deadlock; si evita limitando a n-1 filosofi, rompendo la simmetria o ordinando le risorse), con soluzioni in C (POSIX) e in Go (canali e sync).Semafori, monitor e problemi classici di sincronizzazione → per i lettori-scrittori.
Struttura e record
Un file può essere: una sequenza di byte o di parole (nessuna struttura); a record semplici (righe, record di lunghezza fissa o variabile); a struttura complessa (documento formattato, file eseguibile rilocabile). Il record logico (la minima unità di dati) raramente coincide con il record fisico (il settore): UNIX indirizza i singoli byte, ma il disco ha settori da 512 o 4096 byte, quindi c'è frammentazione interna nell'ultimo blocco.
Metodi di accesso
- Sequenziale:
read next,write next,reset; come un nastro. - Diretto:
read n,write n,position to n, con numero di blocco relativo all'inizio del file (il sistema decide dove metterlo); può simulare l'accesso sequenziale. - Altri (per esempio a indice): si costruisce un indice del file, tenuto in memoria; se è troppo grande, si fa un indice dell'indice.
Directory
Definizione (directory). Una directory è un file speciale che contiene una raccolta di voci con le informazioni sui file. Le directory e i file risiedono su disco.
Operazioni: cercare, creare, cancellare un file; elencare una directory; rinominare; percorrere il file system (la directory corrente e le sue sottodirectory). Una buona organizzazione dà efficienza (trovare presto un file), nomi comodi (due utenti possono avere lo stesso nome per file diversi; lo stesso file può avere più nomi) e raggruppamento (per esempio per proprietà).
| organizzazione | caratteristica | pregi | difetti |
|---|---|---|---|
| livello singolo | una directory per tutti | semplice | problemi di nomi e di raggruppamento |
| due livelli | una directory per utente; percorso = utente + file | stesso nome per utenti diversi; ricerca efficiente | nessun raggruppamento |
| ad albero | sottodirectory; un bit per voce dice se è file (0) o directory (1); ogni processo ha una directory corrente | raggruppamento, percorsi assoluti e relativi | niente condivisione tra rami |
| a grafo aciclico | file e sottodirectory condivisi tramite link | un elemento con più nomi (aliasing) | cancellazioni e puntatori pendenti |
| a grafo generale | sono possibili cicli | massima libertà | cicli e ricerche infinite |
In UNIX e Linux il percorso assoluto inizia dalla radice /, quello relativo parte dalla directory corrente (.; .. è il genitore).
Grafo aciclico: link fisici e simbolici
Nel grafo aciclico un file ha più nomi. Se si cancella /dict/w/list, il nome /spell/words diventa un puntatore pendente (dangling). Soluzioni: puntatori inversi per eliminare tutti i riferimenti; eliminare gli altri riferimenti solo quando si usano; conservare il file finché non sono cancellati tutti i riferimenti (è la scelta di UNIX con il contatore dei link).
Definizione (hard link e link simbolico). Un hard link è un altro nome (una voce di directory) per lo stesso inode: ha la stessa identità del file, non si distingue dall'originale. Un link simbolico (symbolic link) è un file speciale che contiene il percorso di un altro file: un puntatore a un puntatore. In Linux:
ln nome_file nome_linkcrea un hard link,ln -s nome_file nome_simbolicoun link simbolico.
| hard link | link simbolico | |
|---|---|---|
| inode | lo stesso del file | uno proprio |
| contatore dei link del file | aumenta di 1 | non cambia |
| se si cancella l'originale | il file esiste ancora (finché c'è un link) | resta pendente |
| tra file system diversi | no | sì |
| directory | di norma no | sì |
Nel grafo generale i cicli si gestiscono in quattro modi: vietando i link a directory; usando un algoritmo di rilevamento di cicli a ogni nuovo link; permettendoli ma evitando le ricerche infinite; con la garbage collection (controllo periodico dei blocchi irraggiungibili). I cicli dei grafi orientati sono trattati in Grafi diretti e ordinamento topologicoGrafi diretti (archi orientati, grado entrante e uscente, cammini e cicli diretti), visite su grafi diretti e tipi di archi; DAG; ordinamento topologico con l'algoritmo basato sui gradi entranti e con la DFS (reverse postorder), correttezza e costo Theta(n+m); esempio svolto.Grafi diretti e ordinamento topologico →. Un esercizio sui link, con la dimensione e i blocchi di un link, è Esercizio - Hard link e link simbolici, fast symlink (laboratorio 10).
Protezione e permessi
Il proprietario di un file deve poter controllare cosa si può fare e da chi. Tipi di accesso: lettura, scrittura, esecuzione, aggiunta in fondo, cancellazione, elenco.
In UNIX e Linux le modalità sono read, write, execute (rwx) e le classi di utenti sono tre: proprietario (owner), gruppo (group), altri (public). Ognuna è un numero ottale di 3 bit (r=4, w=2, x=1).
Esempio.
chmod 754 abc: proprietario , gruppo , altri , quindirwxr-xr--. Conchmod 444 abcde.txtil file è di sola lettura per tutti, anche per il proprietario. Un gruppo si crea consudo groupadd team, si assegna consudo chgrp team abc.
Windows usa liste di controllo degli accessi (ACL) per utente e gruppo; in Linux man acl. Il programma C del laboratorio 9, con stat() e chmod(), è in Esercizio - Permessi dei file con stat e chmod (laboratorio 9).
Struttura del file system
Un disco permette riscrittura e accesso casuale; i trasferimenti sono per blocchi di settori (di solito 512 o 4096 byte). Il file system fa corrispondere la visione logica del file ai blocchi fisici.
Strati
- File system logico (logical file system): gestisce i metadati; traduce il nome del file in un numero, un handle e una posizione mantenendo i blocchi di controllo del file (FCB; in UNIX inode); gestisce la struttura delle directory e la protezione.
- Modulo di organizzazione dei file: traduce il numero di blocco logico in fisico; gestisce lo spazio libero e l'allocazione.
- File system di base: comandi generici ("leggi il blocco 12"); gestisce buffer e cache in memoria.
- Controllo dell'I/O: driver e gestori delle interruzioni per i dispositivi: traduce comandi come "leggi dal disco 1, cilindro 72, traccia 2, settore 10" in operazioni sul controller (vedi Sistemi di I-O e memory-mapped I-OIl sistema operativo nasconde la varietà dei dispositivi con driver e un'interfaccia uniforme (dispositivi a blocchi, a caratteri, di rete, timer, ioctl); l'hardware è fatto di porte, bus e controller con registri di dato, stato e controllo, indirizzati con istruzioni di I/O dedicate o con il memory-mapped I/O; la CPU comunica con il dispositivo con il polling (busy wait, adatto a dispositivi veloci), con le interruzioni (linea IRQ, vettore, priorità, mascherabili) o con il DMA (trasferimenti di blocchi senza CPU, un'interruzione alla fine); le chiamate possono essere bloccanti, non bloccanti o asincrone; le istruzioni di I/O sono privilegiate e si passa dalle system call; il kernel gestisce errori, buffer e protezione; mmap() mappa un file nello spazio di indirizzi di un processo: accesso con load e store, caricamento pigro con il demand paging, meno chiamate di sistema e meno copie, condivisione con MAP_SHARED.Sistemi di I-O e memory-mapped I-O →).
Esistono molti file system, anche nello stesso sistema operativo: ISO 9660 (CD-ROM), UFS e FFS (UNIX), FAT, FAT32 e NTFS (Windows), ext3 e ext4 (Linux, che ne ha più di 100 tipi), e ZFS, GoogleFS, FUSE e altri.
Strutture su disco
- Blocco di controllo di avvio (boot control block): le informazioni per avviare il sistema da quel volume (di solito il primo blocco); in UFS si chiama boot block, in NTFS partition boot sector.
- Blocco di controllo del volume (volume control block): numero di blocchi, blocchi liberi, dimensione del blocco, puntatori ai blocchi liberi; in UFS è il superblock, in NTFS la master file table.
- Struttura delle directory e FCB dei file. L'FCB contiene permessi, proprietario, date, dimensione e puntatori ai blocchi (non il nome del file, che sta nella directory).
Strutture in memoria
Tabella dei montaggi (mount table); cache delle directory recenti; tabella dei file aperti di sistema (copia dell'FCB di ogni file aperto); tabella dei file aperti del processo (puntatori alla tabella di sistema); buffer per le letture e scritture. Con open si cerca il file nelle directory, si carica l'FCB nella tabella di sistema e si restituisce un descrittore (indice della tabella del processo); con read i dati arrivano al buffer e sono copiati nell'indirizzo del processo.
Implementazione delle directory
- Lista lineare di nomi con puntatori ai blocchi: semplice da programmare, ma lenta (ricerca lineare; si può ordinare o usare un albero bilanciato).
- Tabella hash (vedi Tabelle hashTabella hash per implementare una mappa: funzione hash = hash code + compression function, bucket array, separate chaining; hash code per numeri e stringhe (polynomial, cyclic shift), division e MAD; load factor, complessità al caso pessimo Theta(n) e medio O(1+lambda), rehashing; esempio svolto con inserimenti e collisioni.Tabelle hash →): riduce il tempo di ricerca; le collisioni si risolvono con tabella più grande o con catene di overflow.
Metodi di allocazione
L'allocazione stabilisce come si assegnano i blocchi del disco ai file. Tre metodi.
Allocazione contigua
Ogni file occupa un insieme di blocchi contigui. Serve solo l'indirizzo iniziale e la lunghezza. Migliori prestazioni (sequenziale e diretto). Problemi: trovare spazio, conoscere la dimensione in anticipo (spesso impossibile), frammentazione esterna (serve una compattazione, in linea o no). Una versione migliore, a extent (blocchi contigui di spazio): un file è formato da uno o più extent, e se uno non basta se ne aggiunge un altro collegato; può ancora soffrire di frammentazione interna ed esterna. L'usa ext4.
Allocazione concatenata
Ogni file è una lista concatenata di blocchi, sparsi sul disco; ogni blocco contiene il puntatore al successivo. La directory punta al primo blocco (e all'ultimo o al numero di blocchi). Se il blocco è 512 byte e l'indirizzo 4 byte, restano 508 byte utili. Il file finisce con un puntatore nullo.
Pro: nessuna frammentazione esterna. Contro: per trovare un blocco servono molti I/O e seek, quindi è inadatta all'accesso diretto; i puntatori consumano spazio (si può ridurre raggruppando blocchi contigui in cluster, a costo di più frammentazione interna); affidabilità: se si rovina un blocco o c'è un errore software, il file è corrotto.
FAT (file allocation table): variante della concatenata usata da MS-DOS e altri. Una tabella all'inizio del volume ha una riga per ogni blocco; la riga contiene l'indice del blocco successivo del file; la directory punta al primo blocco. L'accesso casuale si fa cercando nella tabella (più veloce che girare per il disco), e va meglio se la tabella è in cache in memoria. FAT- indica il numero di bit per l'indice di blocco: con bit si hanno blocchi.
Allocazione indicizzata
Un solo blocco indice contiene tutti i puntatori del file; la directory punta al blocco indice e l'-esimo elemento punta all'-esimo blocco dati. Se il file è piccolo il blocco indice è sprecato. Soluzioni: schema concatenato (un puntatore a un altro blocco indice), indice a più livelli (il primo livello punta ai secondi) oppure schema combinato.
Definizione (schema combinato, inode UNIX). L'inode contiene 15 puntatori: i primi 12 diretti ai blocchi dati, il 13° punta a un blocco indiretto singolo (puntatori a blocchi dati), il 14° a un blocco indiretto doppio (puntatori a blocchi di puntatori), il 15° a un blocco indiretto triplo.
Con blocchi da 512 byte e indirizzi da 4 byte, un blocco contiene puntatori; un indiretto doppio indirizza . In generale, con blocco da byte e puntatori da byte: puntatori per blocco e la dimensione massima di un file è (se i puntatori diretti sono 12). Con blocchi da 4 KB e puntatori da 4 byte, e il massimo è circa 4 TB. Calcoli completi in Esercizio - Inode e dimensione massima dei file (eserciziario, esercizi 63, 97, 105 e 111).
ext4 e gli extent. ext4 sostituisce lo schema combinato (troppo complesso per file grandi) con un sistema a extent: un intervallo di blocchi fisici contigui che può mappare fino a 128 MiB. L'inode ne referenzia direttamente 4 (fino a 512 MiB direttamente accessibili); se un file ha più di 4 extent, gli altri sono indicizzati in un albero. ext4 supporta in teoria volumi fino a 64 ZiB e file fino a 16 TiB con blocchi da 4 KiB.
Prestazioni dei metodi
La scelta dipende dal tipo di accesso: la contigua è ottima per accesso sequenziale e diretto; la concatenata è buona per il sequenziale, non per il diretto; la indicizzata è più complessa (un accesso a un blocco può richiedere 2 letture dell'indice, poi la lettura del dato). Si può dichiarare il tipo di accesso alla creazione, scegliendo contigua o concatenata. Per le NVM, senza testine, servono ottimizzazioni diverse: i vecchi algoritmi sprecano CPU per evitare un movimento della testina che non c'è. Un esercizio di confronto è Esercizio - Allocazione dei file con metodo contiguo, concatenato, indicizzato e FAT (eserciziario, esercizi 42, 53, 65, 71, 104, 108, 113 e 119).
Gestione dello spazio libero
Il file system tiene una lista dello spazio libero (non necessariamente una lista vera).
- Vettore di bit (bitmap): bit per blocchi, con 1 per libero e 0 per occupato (o il contrario). Esempio: blocchi liberi 0, 5, 6, 9
10000110010…. La ricerca è rapida perché le CPU hanno istruzioni che restituiscono la posizione del primo bit a 1 di una parola. Efficiente se sta in memoria, un problema per dischi grandi: blocco da 4 KB byte, disco da 1 TB byte, bit, cioè 32 MB (con cluster da 4 blocchi, 8 MB). - Lista concatenata dei blocchi liberi: ogni blocco libero contiene il puntatore al successivo; basta ricordare la testa; nessuno spazio sprecato; non è facile avere spazio contiguo.
- Raggruppamento (grouping): il primo blocco libero contiene gli indirizzi di altri blocchi liberi e un puntatore al blocco successivo di questo tipo.
- Conteggio (counting): si conserva l'indirizzo del primo blocco libero e il numero di blocchi liberi che seguono; più efficiente se il conteggio medio è maggiore di 1 (tipico con extent e allocazione contigua).
Esercizi: Esercizio - Spazio libero con bitmap e lista concatenata (eserciziario, esercizi 41, 98 e 120).
Montaggio e file system virtuali
Un calcolatore può avere più dispositivi di memoria; si dividono in partizioni, i volumi possono occupare più partizioni, e ogni volume di solito contiene un solo file system. La partizione radice contiene il sistema operativo e si monta all'avvio. Le altre si montano su un punto di montaggio (mount point), una directory dell'albero esistente: per esempio una partizione montata in /users. Al montaggio si controlla la coerenza del file system: se i metadati sono corretti, si aggiunge alla tabella dei montaggi e si permette l'accesso.
Con file system condivisi i permessi devono valere anche tra sistemi diversi: che succede se la partizione montata ha file di utenti che non esistono nel sistema ospite? Il comportamento dipende dal sistema operativo e dal file system (per esempio si assegnano a un amministratore).
VFS (virtual file system)
Il VFS di UNIX e Linux è un modo orientato agli oggetti di realizzare i file system: la stessa interfaccia di system call serve per file system di tipo diverso (o di rete). Separa le operazioni generiche dall'implementazione; il VFS invia l'operazione alla routine del file system giusto.
Linux ha quattro tipi di oggetto: file (file aperto), dentry (voce di directory), inode (singolo file) e superblock (intero file system). Ogni oggetto ha un puntatore a una tabella di funzioni con gli indirizzi delle routine che il singolo file system deve implementare: per il file, open, close, read, write, mmap. Questo è l'equivalente in C dell'ereditarietà con funzioni virtuali. Il comando findmnt -lo TARGET,FSTYPE elenca i file system montati (nell'esempio del corso: sysfs, proc, tmpfs, devpts, nfs per la home e ext4 per la radice).
File system distribuiti e NFS
Condivisione di file in rete: a mano (per esempio FTP), con il Web (browser, accesso anche anonimo) o con un file system distribuito (DFS), in cui le directory remote sono visibili dalla macchina locale. In un modello client-server il server offre l'accesso tramite un protocollo; di solito gli utenti di client e server devono coincidere, si monta il file system remoto, le operazioni sono inviate al server per conto dell'utente, il server controlla i permessi e restituisce un handle usato fino alla chiusura.
La semantica di consistenza dice quando le modifiche saranno viste dagli altri utenti e come sincronizzare le operazioni in rete. In UFS i dati scritti in un file aperto sono subito visibili agli altri, e gli utenti possono condividere il puntatore alla posizione corrente. In AFS (Andrew file system) i dati scritti non si vedono durante la sessione: ci sono più copie, modificate separatamente, e alla fine ne resta una sola.
NFS (Sun Network File System) è un'implementazione e una specifica per accedere a file remoti in LAN o WAN (anche su protocolli non affidabili come UDP). Una directory remota si monta su una directory locale e appare come un sottoalbero locale (anche in cascata: per esempio montare S1:/usr/shared su U:/usr/local); l'indipendenza dalla macchina viene da RPC (Remote Procedure Call) sopra XDR (External Data Representation). L'architettura ha tre strati: interfaccia UNIX (open, read, write, close), strato VFS (distingue file locali e remoti, e i locali per tipo di file system), strato del servizio NFS (realizza il protocollo).
Blocchi, frammentazione e stat (laboratori 9 e 10)
Il comando stat nomefile e la funzione C stat() (o lstat(), che riconosce anche i link simbolici) restituiscono una struct stat con st_ino (numero di inode), st_mode (tipo e permessi), st_nlink (numero di hard link), st_uid, st_gid, st_size (byte) e st_blocks (numero di blocchi da 512 byte allocati); statvfs() dà informazioni sul file system montato, come f_bsize (dimensione del blocco, di solito 4096), f_blocks, f_bfree, f_files.
Per ragioni storiche i blocchi contati da stat sono da 512 byte, mentre il blocco fisico di I/O è da 4096. Un file di 1948 byte occupa 1 blocco fisico da 4096, cioè : Blocks: 8. Un file di 17 112 byte ne occupa 5 (): Blocks: 40, e la frammentazione interna è byte. Un file di 1 byte occupa comunque 4096 byte. Nel laboratorio 10, il file di 1 981 975 byte richiede blocchi e la frammentazione interna è byte. Il programma completo è in Esercizio - Frammentazione interna di un file con stat e statvfs (laboratorio 10).
Link simbolici veloci
In ext4, se il nome del file puntato è lungo meno di 60 caratteri, il link simbolico è contenuto nell'inode stesso (che è già in memoria): è un fast symlink, e non occupa nessun blocco dati. Oltre i 60 caratteri serve un blocco.
Domande d'esame
- Confrontare allocazione contigua, concatenata e indicizzata. Contigua: base e lunghezza, ottimo accesso sequenziale e diretto, frammentazione esterna e dimensione da conoscere. Concatenata: nessuna frammentazione esterna, accesso diretto lento, puntatori in ogni blocco, poco affidabile (FAT la migliora con la tabella in cache). Indicizzata: accesso diretto con un blocco indice, ma il blocco indice è sprecato per file piccoli (schema combinato dell'inode).
- Dimensione massima di un file con inode da 12 puntatori diretti, uno indiretto e uno doppio, blocchi da 1 KB e puntatori da 4 byte. : KB.
- Differenza tra hard link e link simbolico; cosa succede cancellando il file originale. L'hard link è un altro nome dello stesso inode (contatore dei link); il file esiste finché c'è un nome. Il link simbolico contiene un percorso: dopo la cancellazione resta pendente. Non si possono fare hard link tra file system diversi.
Versione ripasso
File. Spazio di indirizzi logici contigui; tipo dall'estensione (UNIX: numero magico). Attributi: nome (l'unico leggibile), identificatore, tipo, posizione, dimensione, protezione, date e utente. Operazioni: create, write, read, seek, delete, truncate, open (cerca il file e ne porta le informazioni in memoria), close (le aggiorna su disco). File aperti: tabella di sistema e per processo, puntatore al file, contatore di aperture, posizione su disco, diritti. Lock: condiviso (come un lettore) o esclusivo (scrittore); obbligatorio o consultivo (UNIX) (Semafori, monitor e problemi classici di sincronizzazioneUn semaforo è un intero accessibile solo con due operazioni atomiche, wait (P: aspetta finché S > 0 e decrementa) e signal (V, in POSIX sem_post: incrementa); il semaforo contatore ha valori illimitati, quello binario vale 0 o 1; con valore iniziale 1 realizza la mutua esclusione, con valore iniziale 0 impone un ordine di esecuzione (S1 prima di S2); senza attesa attiva ogni semaforo ha una coda di processi sospesi (sleep e wakeup); i semafori si usano male con facilità (ordine sbagliato, omissioni); il monitor è un tipo di dato astratto in cui un solo processo alla volta è attivo e le variabili condizione x.wait()/x.signal() sospendono e risvegliano (in POSIX mutex più pthread_cond_t); le anomalie di liveness sono deadlock, starvation e inversione di priorità; i problemi classici sono produttore-consumatore a buffer limitato (mutex, vuote = n, piene = 0; l'ordine delle wait è importante), lettori-scrittori (rw_mutex, mutex, read_count; i lettori possono far morire di fame gli scrittori) e filosofi a cena (la soluzione ingenua con un semaforo per bacchetta va in deadlock; si evita limitando a n-1 filosofi, rompendo la simmetria o ordinando le risorse), con soluzioni in C (POSIX) e in Go (canali e sync).Semafori, monitor e problemi classici di sincronizzazione →). Struttura: byte, record, strutture complesse. Record logico settore frammentazione interna. Accesso: sequenziale (read next, reset), diretto (read n, blocco relativo), a indice (anche indice dell'indice).
Directory. File speciale con le voci dei file. Operazioni: cerca, crea, cancella, elenca, rinomina, percorri. Organizzazioni: livello singolo (problemi di nomi e raggruppamento), due livelli (percorso utente file), ad albero (bit file/directory, directory corrente, percorsi assoluti / e relativi .), grafo aciclico (link, aliasing, puntatori pendenti), grafo generale (cicli: vietarli, rilevarli, garbage collection). Cancellazione con link: conservare il file finché c'è un riferimento. Hard link altro nome per lo stesso inode (contatore dei link, ln); link simbolico file speciale con un percorso (ln -s, può restare pendente, vale tra file system diversi, anche per directory). Nel grafo generale i cicli (Grafi diretti e ordinamento topologicoGrafi diretti (archi orientati, grado entrante e uscente, cammini e cicli diretti), visite su grafi diretti e tipi di archi; DAG; ordinamento topologico con l'algoritmo basato sui gradi entranti e con la DFS (reverse postorder), correttezza e costo Theta(n+m); esempio svolto.Grafi diretti e ordinamento topologico →).
Permessi. r, w, x per proprietario, gruppo, altri; r=4, w=2, x=1; chmod 754 rwxr-xr--; chmod 444 sola lettura per tutti; chgrp, groupadd; ACL (man acl) in Windows e Linux (Sicurezza e protezione nei sistemi operativiLe minacce all'accesso sono gli intrusi (masquerader, misfeasor, clandestine user) e il software malevolo (parassita: virus, logic bomb, backdoor; indipendente: worm, bot); contromisure: sistemi di rilevamento delle intrusioni (IDS, host o network, con sensori, analizzatori e interfaccia), autenticazione (identificazione + verifica con qualcosa che si sa, si ha, si è, si fa) e controllo degli accessi (permessi, sudo, SELinux, ACL, auditing, firewall); il buffer overflow scrive oltre un buffer nello stack e può sovrascrivere variabili o l'indirizzo di ritorno (code injection, shellcode); difese a compilazione (linguaggi sicuri, codice sicuro, librerie, stack protection con canarino) e a esecuzione (NX bit, ASLR, guard pages); sulla rete ci sono sniffing, spoofing e man-in-the-middle, e la crittografia (simmetrica e asimmetrica, RSA) limita mittenti e destinatari; la tolleranza ai guasti usa ridondanza (spaziale, temporale, informativa) e si misura con R(t), MTTF, MTTR e disponibilità.Sicurezza e protezione nei sistemi operativi →).
Strati. (1) file system logico: metadati, nome numero/handle, FCB (inode UNIX), directory, protezione; (2) organizzazione dei file: blocco logico fisico, spazio libero, allocazione; (3) file system di base: comandi generici, buffer e cache; (4) controllo dell'I/O: driver e interruzioni (Sistemi di I-O e memory-mapped I-OIl sistema operativo nasconde la varietà dei dispositivi con driver e un'interfaccia uniforme (dispositivi a blocchi, a caratteri, di rete, timer, ioctl); l'hardware è fatto di porte, bus e controller con registri di dato, stato e controllo, indirizzati con istruzioni di I/O dedicate o con il memory-mapped I/O; la CPU comunica con il dispositivo con il polling (busy wait, adatto a dispositivi veloci), con le interruzioni (linea IRQ, vettore, priorità, mascherabili) o con il DMA (trasferimenti di blocchi senza CPU, un'interruzione alla fine); le chiamate possono essere bloccanti, non bloccanti o asincrone; le istruzioni di I/O sono privilegiate e si passa dalle system call; il kernel gestisce errori, buffer e protezione; mmap() mappa un file nello spazio di indirizzi di un processo: accesso con load e store, caricamento pigro con il demand paging, meno chiamate di sistema e meno copie, condivisione con MAP_SHARED.Sistemi di I-O e memory-mapped I-O →). Tipi: ISO 9660, UFS, FFS, FAT, NTFS, ext3/ext4 (Linux ne ha più di 100), ZFS, FUSE. Su disco: boot block (UFS) o partition boot sector (NTFS); volume control block (superblock, master file table); directory; FCB (permessi, proprietario, date, dimensione, puntatori; non il nome). In memoria: mount table, cache delle directory, tabella dei file aperti di sistema (copia dell'FCB) e per processo, buffer. Directory: lista lineare (ricerca lenta) o tabella hash (Tabelle hashTabella hash per implementare una mappa: funzione hash = hash code + compression function, bucket array, separate chaining; hash code per numeri e stringhe (polynomial, cyclic shift), division e MAD; load factor, complessità al caso pessimo Theta(n) e medio O(1+lambda), rehashing; esempio svolto con inserimenti e collisioni.Tabelle hash →).
Allocazione.
- Contigua: base lunghezza, ottima per sequenziale e diretto; frammentazione esterna, dimensione da conoscere; versione a extent (ext4).
- Concatenata: lista di blocchi con puntatore (512 B con indirizzo da 4 B 508 utili); nessuna frammentazione esterna; accesso diretto lento; poco affidabile. FAT: tabella con una riga per blocco, indice del successivo; in cache in memoria; FAT- blocchi.
- Indicizzata: blocco indice; se piccolo il file lo spreca; schema concatenato, a più livelli o combinato: inode con 15 puntatori (12 diretti, singolo, doppio, triplo). ; massimo ; , : MB per il doppio; KB: circa 4 TB. ext4: extent fino a 128 MiB, 4 nell'inode (512 MiB), poi albero; volumi fino a 64 ZiB, file fino a 16 TiB.
Prestazioni: contigua per sequenziale e diretto, concatenata per sequenziale, indicizzata più complessa (2 letture dell'indice dato); NVM: ottimizzazioni diverse.
Spazio libero. Bitmap ( bit MB per 1 TB e blocchi da 4 KB, 8 MB con cluster da 4; istruzioni per il primo bit a 1), lista concatenata (nessuno spreco, non facile avere spazio contiguo), raggruppamento (il primo libero contiene indirizzi), conteggio (primo blocco quanti seguono).
Mount e VFS. Partizioni, volumi; radice montata all'avvio; altre su un mount point, controllo di coerenza; permessi tra sistemi diversi. VFS (Linux: oggetti file, dentry, inode, superblock con tabelle di funzioni open, close, read, write, mmap); findmnt -lo TARGET,FSTYPE. DFS: FTP, Web, file system distribuito; semantica UFS (scritture subito visibili) contro AFS (non visibili durante la sessione, resta l'ultima copia); NFS con RPC e XDR, tre strati (interfaccia UNIX, VFS, servizio NFS), montaggio anche in cascata.
stat e laboratori. st_blocks conta blocchi da 512 byte, il blocco fisico è 4096 ( blocchi contati): 1948 byte Blocks: 8; 17 112 byte 5 blocchi fisici , frammentazione ; 1 981 975 byte blocchi, . Fast symlink (ext4): percorso caratteri nell'inode, nessun blocco (Esercizio - Hard link e link simbolici, fast symlink (laboratorio 10)).
Domande tipiche. Contigua contro concatenata contro indicizzata; massimo file con 12 diretti + singolo + doppio ( KB, B KB); hard contro simbolico; bitmap per un disco dato.
Errori tipici. Nome nell'FCB; blocchi di stat da 4096; blocchi indice non contati; frammentazione per file multipli del blocco; hard link e simbolici scambiati.
Collegamenti: Memoria di massa e scheduling del discoLa memoria di massa è fatta di dischi rigidi (HDD: piatti, tracce, cilindri, settori) e memorie non volatili NAND (SSD); tempo di accesso HDD = seek + latenza rotazionale (mezzo giro, 30/RPM secondi), tempo di I/O = accesso + trasferimento + overhead del controller; i blocchi sono indirizzati con un LBA lineare; per l'HDD si minimizza il seek con FCFS, SSTF (rischio di starvation), SCAN (ascensore) e C-SCAN (più uniforme), con le varianti LOOK e C-LOOK e il deadline di Linux; per le NVM contano FTL, garbage collection, overprovisioning e wear leveling; il sistema operativo formatta (fisico e logico), partiziona, gestisce il boot e lo spazio di swap; parità ed ECC rilevano e correggono errori; il RAID usa striping, mirroring e parità (livelli 0, 1, 4, 5, 6, 10) per più velocità e affidabilità, con MTTDL = 1/PDL.Memoria di massa e scheduling del disco →, Sistemi di I-O e memory-mapped I-OIl sistema operativo nasconde la varietà dei dispositivi con driver e un'interfaccia uniforme (dispositivi a blocchi, a caratteri, di rete, timer, ioctl); l'hardware è fatto di porte, bus e controller con registri di dato, stato e controllo, indirizzati con istruzioni di I/O dedicate o con il memory-mapped I/O; la CPU comunica con il dispositivo con il polling (busy wait, adatto a dispositivi veloci), con le interruzioni (linea IRQ, vettore, priorità, mascherabili) o con il DMA (trasferimenti di blocchi senza CPU, un'interruzione alla fine); le chiamate possono essere bloccanti, non bloccanti o asincrone; le istruzioni di I/O sono privilegiate e si passa dalle system call; il kernel gestisce errori, buffer e protezione; mmap() mappa un file nello spazio di indirizzi di un processo: accesso con load e store, caricamento pigro con il demand paging, meno chiamate di sistema e meno copie, condivisione con MAP_SHARED.Sistemi di I-O e memory-mapped I-O →, Sicurezza e protezione nei sistemi operativiLe minacce all'accesso sono gli intrusi (masquerader, misfeasor, clandestine user) e il software malevolo (parassita: virus, logic bomb, backdoor; indipendente: worm, bot); contromisure: sistemi di rilevamento delle intrusioni (IDS, host o network, con sensori, analizzatori e interfaccia), autenticazione (identificazione + verifica con qualcosa che si sa, si ha, si è, si fa) e controllo degli accessi (permessi, sudo, SELinux, ACL, auditing, firewall); il buffer overflow scrive oltre un buffer nello stack e può sovrascrivere variabili o l'indirizzo di ritorno (code injection, shellcode); difese a compilazione (linguaggi sicuri, codice sicuro, librerie, stack protection con canarino) e a esecuzione (NX bit, ASLR, guard pages); sulla rete ci sono sniffing, spoofing e man-in-the-middle, e la crittografia (simmetrica e asimmetrica, RSA) limita mittenti e destinatari; la tolleranza ai guasti usa ridondanza (spaziale, temporale, informativa) e si misura con R(t), MTTF, MTTR e disponibilità.Sicurezza e protezione nei sistemi operativi →, System call POSIX, file descriptor e API delle socketLe system call sono le funzioni con cui un programma in user space chiede servizi al kernel (open, read, write, close, fork, pipe, dup2, socket, bind, listen, accept, connect); restituiscono -1 e impostano errno in caso di errore; un file descriptor e' un intero che indicizza la tabella dei file aperti del processo (0 stdin, 1 stdout, 2 stderr) e vale per file, pipe e socket; read e write possono trasferire MENO byte del richiesto (e sui socket TCP non c'e' nessun confine fra i messaggi), quindi servono cicli write_all e read_exact; l'API delle socket crea un punto finale di comunicazione (socket), lo lega a indirizzo e porta (bind), lo rende passivo (listen), accetta connessioni (accept) o si connette (connect); getaddrinfo traduce nomi e porte in indirizzi (IPv4 e IPv6); UDP usa sendto e recvfrom e conserva i confini dei datagrammi, TCP e' uno stream affidabile.System call POSIX, file descriptor e API delle socket →.
Esercizi su questo argomento
- Esercizio - Allocazione dei file con metodo contiguo, concatenato, indicizzato e FAT (eserciziario, esercizi 42, 53, 65, 71, 104, 108, 113 e 119)
- Esercizio - Frammentazione interna di un file con stat e statvfs (laboratorio 10)
- Esercizio - Hard link e link simbolici, fast symlink (laboratorio 10)
- Esercizio - Inode e dimensione massima dei file (eserciziario, esercizi 63, 97, 105 e 111)
- Esercizio - Permessi dei file con stat e chmod (laboratorio 9)
- Esercizio - Spazio libero con bitmap e lista concatenata (eserciziario, esercizi 41, 98 e 120)