Lezione 33 Il Block Layer - WEB Lab

Pagina creata da Michele Paolini
 
CONTINUA A LEGGERE
Lezione 33
Il Block Layer
Sistemi Operativi (9 CFU), CdL Informatica, A. A. 2020/2021
Dipartimento di Scienze Fisiche, Informatiche e Matematiche
Università di Modena e Reggio Emilia
http://weblab.ing.unimo.it/people/andreolini/didattica/sistemi-operativi
                                                                           1
Quote of the day
                     (Meditate, gente, meditate...)
“I think the major good idea of
UNIX was its clean and simple
interface: open, close, read and
write.”
Ken Thompson (1943-)
Ingegnere, Programmatore
Ideatore del sistema operativo UNIX
Creatore di Belle

                                                      2
GESTIONE STRATIFICATA I/O BLOCCHI

                                    3
Eterogeneità dei dispositivi
                    (Elevata, purtroppo)
La gestione di un dispositivo a caratteri prevede di
mantenere una sola posizione, quella attuale del cursore
di lettura/scrittura.
La gestione di un dispositivo a blocchi (che può
effettuare seek) è molto più complessa.
La complessità è incrementata dalla presenza di
dispositivi a blocchi con caratteristiche molto diverse.
  Rotazionali (a disco) e non rotazionali (SSD).
  Logici (LVM) e non.
  Provvisti di meccanismi per la lettura concorrente (ad
  esempio, Native Command Queueing).                   4
Componenti del Block Layer
                     (Generic Block Layer)
Generic block layer.
  Fornisce una interfaccia di accesso comune a tutti i
  dispositivi a blocchi nascondendo i dettagli tipici del
   singolo dispositivo.
  Nasconde i dettagli tipici del singolo dispositivo a
  blocchi al file system.
  Consente il disaccoppiamento tra organizzazione
  logica del file (file system) e posizione fisica del dato
  sottostante.
  Utilizza politiche efficienti di servizio delle richieste di
  I/O.                                                       5
Componenti del Block Layer
                   (Scheduler di I/O)

Scheduler del disco.
  Decide l'ordine di servizio delle richieste di I/O
  per uno specifico dispositivo a blocchi.
  L'utente può selezionare, tra quelli compilati
  nel kernel, lo scheduler utilizzato per ciascun
   dispositivo a blocchi.

                                                   6
Componenti del Block Layer
              (Diagramma semplificato)

                                               Descrittore
   File system             File system          del disco

Block layer
                  Generic block layer

   Scheduler del disco              Scheduler del disco

  Driver del dispositivo           Driver del dispositivo    7
Blocchi e settori
          (Unità di trasferimento del block layer e del dispositivo)

L'unità di indirizzamento minima di un dispositivo
a blocchi è il settore.
   Dimensione: è una caratteristica fisica del dispositivo.
   Dimensione tipica: 512 byte.
Il block layer utilizza, come unità di memorizzazione, il
blocco.
   Struttura dati “di collegamento” tra file system, mapping
   layer e block layer.
   Dimensione: multiplo di un settore.
   Dimensioni comuni: 512 byte, 1kB, 4 kB, ...
                                                                       8
Blocchi e settori
              (Uno schema semplificato)

Un blocco è un insieme di settori contigui su
disco.
                                              Blocchi
 Settore

                                                         ...

                       più settori contigui = 1 blocco         9
Blocchi e pagine
             (Una pagina → Uno o più blocchi)

Una pagina di memoria può contenere uno o più
blocchi.
La dimensione del blocco non può eccedere
quella della pagina.
Quando un blocco è mappato in memoria si dice
“contenuto in un buffer”.
Un buffer è la porzione di una pagina di memoria
corrispondente ad un blocco.
                                                10
La struttura buffer_head
              (Già incontrata nel contesto della page cache)
La struct buffer_head ha il compito di mappare
un buffer di una pagina di memoria nel blocco
corrispondente.
http://lxr.linux.no/linux+v3.6.5/include/linux/buffer_head.h#L59
La struttura dati contiene:
   informazioni sulla pagina.
   indirizzo della pagina di memoria.
   indirizzo del buffer all'interno della pagina.
   informazioni sul blocco.
   dispositivo fisico al quale il blocco si riferisce.
   numero di blocco.                                               11
La struttura buffer_head
              (Uno schema semplificato)
                 buffer_head
                   b_bdev
                   b_page
                                               Dispositivo
                  b_blocknr
page
                    b_size
buffer              b_data
buffer                               Blocco
  ...                                2
                                     settori
buffer
                                                        12
Problemi delle buffer_head
                      (Prestazionali)
Nelle versioni del kernel Linux precedenti alla 2.6, la
struct buffer_head non descriveva solo la
mappatura tra blocchi a pagine.
Era utilizzata per tutte le operazioni di I/O.
Ciascuna operazione di I/O era effettuata sul singolo
blocco.
  Operazioni di I/O potenzialmente grandi risultavano
  frammentate.
  Aggravio computazionale enorme.
  Alto consumo di memoria (tante strutture piccole in
  caso di letture consistenti).                     13
La struct bio
             (Risolve i problemi delle buffer_head)

La struct bio (introdotta nel kernel v2.6 come
rimpiazzo dei buffer) rappresenta le operazioni di
I/O in corso come una lista di segmenti.
Un segmento è una porzione di buffer contigua in
memoria.
Può essere più grande di un blocco!
I singoli buffer non devono essere contigui in
memoria.
                                                      14
Definizione della struct bio
                        (Una lista di segmenti)
La struct bio rappresenta le operazioni di I/O
in corso come una lista di segmenti.
http://lxr.linux.no/#linux+v3.6.6/include/linux/blk_types.h#L35
La struttura contiene:
   una lista di struct bio_vec, ciascuna delle quali
   rappresenta un segmento, ovvero una porzione di
   memoria ad un certo offset all'interno di una certa
   pagina.
   dimensioni dell'I/O da effettuare.
   caratteristiche      del     dispositivo  coinvolto
   dall'operazione di I/O.                           15
I/O vettorizzato
                     (Scatter-gather I/O)

La struct bio consente al kernel di effettuare
I/O a blocchi da locazioni multiple di memoria.
I/O vettorizzato (scatter-gather I/O): sfrutta il
parallelismo del dispositivo per scrivere in
memoria più buffer contemporaneamente.
  Dischi veloci, schede di rete.

                                               16
La struct iovec
           (Contiene i dati letti in maniera vettorizzata)

struct iovec: contiene un campo “base” ed uno
“lunghezza” → identifica un “segmento” da leggere in
memoria.
La chiamata di sistema readv() legge una lista di
                                                   17
segmenti (anche non contigui).
La struct bio_vec
                   (Il vettore di segmenti)
struct bio_vec {
                                               pagina
      /* puntatore alla pagina */
      struct page *bv_page;                   segmento

      /* lunghezza del segmento */
      unsigned int bv_len;

      /* posizione del segmento */
      unsigned int bv_offset;
};
                                                     18
Relazione tra bio, bio_vec e pagine
            (Come è implementata la lista di segmenti)

    struct bio

     bi_io_vec             bi_idx (posizione attuale dell'I/O)

  bio_vec     bio_vec     bio_vec    bio_vec
                                                  Pagine coinvolte
                 pagina                           nell'operazione di I/O

                                                pagina
                                pagina
       pagina
                                                                     19
PROGRAMMAZIONE ASINCRONA I/O

                               20
Accesso a dispositivi a blocchi
                  (Sincrono o asincrono)
Non è detto che una richiesta di I/O debba
risultare bloccante per il flusso di esecuzione di
un processo.
Se è una lettura, c'è la possibilità che lo sia.
  Il processo generalmente ha bisogno dei dati che
  legge per proseguire con l'elaborazione.
  Questo non è sempre vero.
Se è una scrittura, è stata delegata dal processo al
flusher.
  Così come il processo, il flusher non ha bisogno di
  bloccarsi in attesa del suo completamento.       21
Accesso a dispositivi a blocchi
                   (Sincrono o asincrono)

Tuttavia, l'accesso al dispositivo fisico avviene in
modo concorrente.
  C'è sempre qualcuno che deve aspettare il proprio
  turno...
Il block layer deve interagire con il device driver
del singolo dispositivo a blocchi.
  Bisogna rispettare i tempi del dispositivo fisico, che
  può essere impegnato in altre operazioni.
                                                      22
La struct request_queue
    (Contiene le operazioni di I/O in attesa di essere elaborate dal driver)

La struct request_queue è utilizzata per
memorizzare le operazioni di I/O in attesa di
servizio da parte del device driver.
http://lxr.linux.no/#linux+v3.6.6/include/linux/blkdev.h#L286

                                                                               23
La struct request_queue
   (Contiene le operazioni di I/O in attesa di essere elaborate dal driver)

Ciascun dispositivo a blocchi ha la propria
request_queue.
  Rappresentata dal  sottoalbero di                                       sysfs
  /sys/block//queue.
  Contiene una lista doppiamente concatenata di struct
  request (viste in seguito) rappresentanti richieste di I/O.
  La coda è mantenuta ordinata per settori crescenti (in
  modo tale da ridurre i seek).
                                                                              24
Accesso a dispositivi via request queue
           (È il driver a pescare richieste dalla request_queue)
Nel momento in cui il block layer vuole mettere a
disposizione del device driver di un dispositivo una
richiesta, la accoda nella request_queue del
dispositivo.
Quando il driver è pronto a servire una richiesta, controlla
se la request_queue del dispositivo è vuota.
   Se non lo è, estrae una richiesta dalla request_queue e
   la serve.
   Se lo è, attende che il block layer lo solleciti ad estrarre
   una richiesta. Tipicamente, ciò avviene ogni volta che un
   processo viene messo in attesa.                            25
Uso di callback
                (Asincronia delle operazioni)

Il completamento di una operazione di I/O viene
segnalato dal device driver al block layer con l'uso
di un callback (elv_completed_request()).
L'invocazione del callback:
  avviene nella bottom half del dispositivo a blocchi.
  provoca la cancellazione delle strutture dati non più
  utili ai fini dell'operazione.
  provoca la schedulazione di altre richieste di I/O.
                                                     26
RIORGANIZZAZIONE RICHIESTE I/O

                                 27
Modalità di I/O
                       (I/O sequenziale)

Un processo può effettuare richieste di I/O
secondo due modalità.
I/O sequenziale: una richiesta riguarda settori
contigui rispetto a quelli della richiesta
precedente.
  Esempi: lettura di un file grande, file system check, ...

                                                              28
Modalità di I/O
                     (I/O casuale)

Un processo può effettuare richieste di I/O
secondo due modalità.
I/O casuale: una richiesta non riguarda settori
contigui rispetto a quelli della richiesta
precedente.
  Esempio: il caricamento in memoria di librerie
  preliminare all'avviamento di un'applicazione segue
  un pattern casuale.
                                                   29
Modalità di I/O
                    (Un problema)
Ciascuna richiesta di I/O è rappresentata dalla
struct bio, che mantiene la mappatura tra i
blocchi e le pagine interessati dall'operazione.
Si consideri il caso di un processo che effettua
accesso sequenziale ad un disco.
Il fatto di avere multiple richieste di I/O per
blocchi i cui settori sottostanti sono adiacenti
introduce:
  aggravio computazionale inutile.
  consumo non necessario di memoria.          30
La struct request
         (Identifica la singola richiesta da fare al dispositivo fisico)
La      struct           request         rappresenta
un'operazione di I/O in corso su un insieme di
blocchi i cui settori sottostanti sono adiacenti.
   Può coinvolgere diverse bio.
Consente al block layer di comunicare con il
device driver (struct request è la struttura
accodata nella request_queue del dispositivo).
http://lxr.linux.no/#linux+v3.6.5/include/linux/blkdev.h#L95
La struct request contiene il puntatore ad
una lista di struct bio.                 31
Fusione di richieste
                (Merging: una forma di batching)
Nel momento in cui una struct bio viene
costruita nel block layer:
  si controlla se esistono, all'interno del block layer, una
  o più struct request che riguardano settori
  adiacenti.
  In caso affermativo, le strutture dati bio sono
  accorpate in una unica struct request.
  → Operazione di merging: fusione di una bio in una o
  più richieste già esistenti.
In questo modo, si riduce l'aggravio legato alla
gestione di multiple struct bio.               32
Fusione di richieste
                      (Front merge, back merge)
Front merge: inserimento della nuova richiesta prima di
una richiesta già presente.
Back merge: inserimento della nuova richiesta dopo una
richiesta già presente.
Coalesce: raggruppamento di tre richieste in seguito al
fatto che la nuova sia successiva alla prima e precedente
alla seconda.                                      Back merge
             richiesta    nuova       richiesta     nuova
           già presente    bio      già presente     bio
                                                   Front merge
Coalesce                                                         33
Plugging
                 (Un'altra forma di batching)
Se le richieste fossero date immediatamente al
driver, la testina subirebbe molti seek.
  Ciò va evitato come la peste.
Plugging: il block layer attende per un po' di
tempo, nella speranza che arrivino tanti richieste
fondibili.
Obiettivo: creare poche richieste grandi e vicine.
Al verificarsi di un evento, viene attivato il device
driver.
  Scadenza di un timer.
                                                   34
  Accumulo eccessivo di richieste.
Plugging per processo
          (Abbassa le latenze dovute al plugging “globale”)

Il plugging è un ottimo meccanismo che, tuttavia,
soffre di un problema.
  Se diversi processi fanno richieste, tutti provano a
  prendere lo stesso lock sulla request_queue.
  Le attese possono diventare lunghe.
Nelle ultime versioni del kernel, il lock è stato reso
a grana più fine.
  Una struttura dati di plug per processo.
  Un lock per struttura dati di plug.
Esempi successivi: plugging classico.                         35
Tempi di esecuzione della richiesta
                     (Seek, latency, transfer)

In generale, il tempo impiegato da un disco
magnetico per trasferire una certa quantità di dati
può essere rappresentato come somma di:
tempo di seek → tempo di posizionamento della testina
sulla traccia corretta.
latenza rotazionale → tempo impiegato per posizionare
il settore giusto al di sotto della testina (tipicamente, la
metà del tempo di rotazione indicato dal costruttore)
tempo di trasferimento dei dati
                                                          36
Accesso ad un dispositivo rotazionale
                         (Un diagramma semplificato)
                     Disco magnetico               Tempo di seek

                           traccia
                                                   Ultima posizione
                                                   della testina

                                                   Latenza rotazionale

Tempo di trasferimento                                                   37
                                               Settori da trasferire
Sorting
       (Si riordina la sequenza di richieste casuale per ridurre i seek)

Il tempo di trasferimento è costante.
Si conosce il valor medio della latenza (è fornito dal
costruttore).
Il tempo di seek dipende dalla posizione della richiesta
servita rispetto alla posizione precedente della testina.
   Anche in questo caso si conosce il valor medio.
   Conoscendo i settori interessati dalle richieste di I/O, però,
   è possibile ridurre il numero di seek effettuati.
Sorting: riordinamento delle strutture dati request per
settori crescenti.
                                                                           38
Sorting
                   (Un esempio)

Si consideri un semplice scenario di accesso
casuale a un dispositivo a blocchi.
Disco rotazionale avente tempo medio di seek di
15 millisecondi.
10 richieste effettuate per settori collocati su
tracce diverse nel seguente ordine:
10, 2, 5, 8, 4, 7, 1, 9, 3, 6.
                                              39
Accesso senza riordinamento
                       (La testina si sposta di continuo)
          10
                                       9                    10 seek
Settore                                                

                       8                                   10 * (15 ms)
                               7                            = 150 ms
                                                           0,15 secondi sono persi
                                                6           nelle operazioni di seek
                   5                                       Il tasso di servizio ne
                           4                                risente

                                            3
               2
                                   1
                                                                                      40
                                                Tempo
Accesso con riordinamento
                          (La testina non si sposta mai)
                                                10
                                             9            1 seek (per raggiungere
Settore
                                        8                  il primo settore, se
                                                           necessario)
                                    7                     Attesa di 15 ms

                               6                          In seguito, il

                           5                               trasferimento avviene in
                                                           modo continuato con
                      4                                    alto tasso di servizio
                  3
              2
          1
                                                                                41
                                                 Tempo
Scheduler del disco
                  (Riordina le richieste di I/O)
Scheduler del disco: componente il cui compito
è decidere in che ordine le strutture request
debbano essere messe a disposizione del device
driver.
Tipicamente, persegue due obiettivi:
  il tasso di servizio deve essere alto.
  le richieste devono essere servite il prima possibile.
Implementa politiche di gestione delle richieste.
  Deve rispettare prototipi generici definiti in un
  descrittore.
                                                  42
  Può implementare operazioni specifiche.
Scheduler del disco
                 (Riordina le richieste di I/O)

La politica implementata da uno scheduler
solitamente prevede che partecipi alle operazioni
di merge e sort operate dal generic block layer.
Dà il consenso ad operazioni di merge su request
già presenti nelle proprie strutture dati private.
Tipicamente, gestisce le richieste secondo
l'algoritmo dell'ascensore (elevator): non salta
follemente di piano in piano, ma serve le richieste
in ordine di settore.                              43
UNA VISIONE D'INSIEME

                        44
Un esempio concreto di I/O
       (Interazione fra i componenti del block layer)
                   Pagina                                       User
Processo          memoria                                       mode

                                                                Kernel
                                              Block layer       mode
   Richiesta
lettura blocco                     Il processo richiede un dato via
                                   read(). Il VFS individua il giusto
                                   dispositivo    ed     invoca     la
                                   do_sync_read(), che attiva il block
                                   layer.

                                                            Hardware   45
Un esempio concreto di I/O
       (Interazione fra i componenti del block layer)
                   Pagina       ...    Pagina                   User
Processo          memoria             memoria                   mode

                                                                Kernel
                                              Block layer       mode
Read ahead                         Il block layer decide se è il caso di
                                   effettuare una anticipazione (read
                                   ahead) di 128KB, per migliorare le
                                   prestazioni delle read() successive
                                   (nel caso di accesso sequenziale).

                                                            Hardware   46
Un esempio concreto di I/O
              (Interazione fra i componenti del block layer)
                          Pagina       ...    Pagina                   User
       Processo          memoria             memoria                   mode

                                                                       Kernel
                                                     Block layer       mode
  Preparazione
  struct bio                              Il block layer prepara la struct
                                          bio descrivente il segmento di
 bio
                                          memoria coinvolto nella lettura.

bio_vec      ...   bio_vec

                                                                   Hardware   47
Un esempio concreto di I/O
             (Interazione fra i componenti del block layer)
                         Pagina       ...    Pagina                   User
      Processo          memoria             memoria                   mode

                                                                      Kernel
                                                    Block layer       mode
  Inserimento
 della bio nello
   scheduler                             Il block layer trasforma la bio in una
                                         request e la inserisce nella coda di
bio               request                richieste dello scheduler di I/O.

                                                                  Hardware   48
Un esempio concreto di I/O
             (Interazione fra i componenti del block layer)
                         Pagina       ...    Pagina                   User
      Processo          memoria             memoria                   mode

                                                                      Kernel
                                                    Block layer       mode
  Inserimento
 della bio nello                         Il block layer trasforma la bio in una
   scheduler                             request e la inserisce nella coda di
                                         richieste dello scheduler di I/O. La
bio               request                coda è ordinata per settori crescenti.

                                                                  Hardware   49
Un esempio concreto di I/O
             (Interazione fra i componenti del block layer)
                         Pagina       ...    Pagina                   User
      Processo          memoria             memoria                   mode

                                                                      Kernel
                                                    Block layer       mode
  Inserimento
 della bio nello
   scheduler                             Lo scheduler opera una fusione delle
                                         richieste, se contigue.
bio               request

                                                                  Hardware   50
Un esempio concreto di I/O
             (Interazione fra i componenti del block layer)
                         Pagina       ...    Pagina                   User
      Processo          memoria             memoria                   mode

                                                                      Kernel
                                                    Block layer       mode
  Inserimento
 della bio nello                         Il block layer NON invia subito la
   scheduler                             richiesta al device driver, bensì
                                         attende per uno specifico intervallo
bio               request                (unplug timeout). L'idea è quella di
                                         operare    più   fusioni    possibili,
                                         ottenendo poche, grandi richieste.

                                                                  Hardware   51
Un esempio concreto di I/O
               (Interazione fra i componenti del block layer)
                           Pagina       ...    Pagina                   User
        Processo          memoria             memoria                   mode

                                                                        Kernel
                                                      Block layer       mode
       Device driver                        Allo scadere del timer di unplug, il
                                            device driver è attivato. Esso chiede
                                            una richiesta allo scheduler di I/O e la
                    request     Coda        inserisce nella coda delle richieste del
                                scheduler   dispositivo in modo tale da
                                            mantenere ordinati i settori.

Coda
dispositivo                                                         Hardware   52
Un esempio concreto di I/O
               (Interazione fra i componenti del block layer)
                           Pagina       ...    Pagina                   User
        Processo          memoria             memoria                   mode

                                                                        Kernel
                                                      Block layer       mode
       Device driver
                                            Successivamente, il device driver
        DMA
                                            pesca la prima richiesta dalla coda
                    request     Coda        del dispositivo e la programma in
                                scheduler   DMA.

Coda
dispositivo                                                         Hardware   53
Un esempio concreto di I/O
        (Interazione fra i componenti del block layer)
                    Pagina       ...    Pagina                   User
 Processo          memoria             memoria                   mode

                                                                 Kernel
                                               Block layer       mode
Device driver
                                    La richiesta è programmata. Non
schedule()                          rimane che attendere l'interruzione
                                    del dispositivo. Il device driver
                                    rischedula il processo: schedule().

                                                             Hardware   54
Un esempio concreto di I/O
       (Interazione fra i componenti del block layer)
                   Pagina       ...    Pagina                   User
Processo          memoria             memoria                   mode

                                                                Kernel
                                              Block layer       mode
                                   Quando arriva l'interruzione del
            Bottom half            dispositivo, viene eseguita la sua top
                                   half, che controlla lo stato del
                                   dispositivo, riabilita le interruzioni e
                                   schedula la bottom half. Attenzione: i
Top half                           dati richiesti sono già in memoria
                                   centrale (il trasferimento è avvenuto
                                   in DMA).
                                                            Hardware   55
Un esempio concreto di I/O
               (Interazione fra i componenti del block layer)
                           Pagina       ...    Pagina                    User
        Processo          memoria             memoria                    mode

                                                                         Kernel
                                                       Block layer       mode
       Device driver
                       Bottom half           Quando viene eseguita la bottom
                                             half, si dichiara completata la
                                 Coda        richiesta. Il device driver distrugge,
                                 scheduler   per conto della bottom half, tutte le
                                             strutture dati coinvolte per la
                                             gestione della stessa.
Coda
dispositivo                                                          Hardware   56
Un esempio concreto di I/O
               (Interazione fra i componenti del block layer)
                           Pagina       ...    Pagina                    User
        Processo          memoria             memoria                    mode

                                                                         Kernel
                                                       Block layer       mode
       Device driver
                       Bottom half           Il device driver chiede allo scheduler
                                             la       prossima     richiesta    da
                    request      Coda        programmare in DMA. La procedura
                                 scheduler   di prelievo si ripete fino a quando
                                             non sono portati in memoria centrale
                                             tutti i dati.
Coda
dispositivo                                                          Hardware   57
Un esempio concreto di I/O
        (Interazione fra i componenti del block layer)
                    Pagina       ...    Pagina                    User
 Processo          memoria             memoria                    mode

                                                                  Kernel
                                               Block layer        mode
Device driver

                                    Il device driver risveglia il processo.

                                                             Hardware   58
Puoi anche leggere