Salta al contenuto
Note per Studenti Esercizio - Scheduling del disco con FCFS, SSTF, SCAN e C-SCAN (slide di memoria di massa, eserciziario, esercizio 95)

Esercizio - Scheduling del disco con FCFS, SSTF, SCAN e C-SCAN (slide di memoria di massa, eserciziario, esercizio 95)

In questa pagina 4

Testo.

  • Slide di memoria di massa. Disco con cilindri da 0 a 199; coda di richieste 98, 183, 37, 122, 14, 124, 65, 67; testina inizialmente al cilindro 53. Calcolare lo spostamento totale della testina (in cilindri) con FCFS, SSTF, SCAN e C-SCAN.

  • Esercizio 95 (eserciziario del corso di Sistemi Operativi, Ing. Informatica UniPD). Scheduling del disco con SCAN. Tempo di seek lineare nel numero di tracce attraversate (una traccia al millisecondo); ritardo rotazionale e tempo di trasferimento trascurabili. Disco da 200 tracce (0-199); a t=0t=0 la testina è sulla traccia 50. Una volta avviata una richiesta di I/O non è possibile interromperla: le scelte dello scheduler avvengono solo dopo il completamento di una richiesta. Se non ci sono richieste pendenti la testina resta ferma sull'ultima traccia visitata; la direzione di scansione si inverte quando non ci sono altre richieste pendenti nella direzione attuale. Con la tabella seguente (numero richiesta, traccia, tempo di arrivo in ms), dare la sequenza con cui le richieste sono soddisfatte e i relativi tempi.

    richiesta 1 2 3 4 5 6 7 8
    traccia 70 65 80 75 120 60 90 80
    arrivo (ms) 2 8 20 21 29 31 38 100

Teoria: 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 →.


Parte 1: l'esempio delle slide

Distanza fra due cilindri aa e bb: ∣a−b∣|a-b|. Testina in 53, richieste da servire: 98,183,37,122,14,124,65,6798,183,37,122,14,124,65,67.

FCFS (nell'ordine di arrivo): 53→98→183→37→122→14→124→65→6753\to98\to183\to37\to122\to14\to124\to65\to67.

passo →98\to98 →183\to183 →37\to37 →122\to122 →14\to14 →124\to124 →65\to65 →67\to67
spostamento 45 85 146 85 108 110 59 2

Totale =45+85+146+85+108+110+59+2=640=45+85+146+85+108+110+59+2=\mathbf{640} cilindri.

SSTF (sempre la più vicina): da 53 la più vicina è 65 (distanza 12), poi 67 (2), poi 37 (30), poi 14 (23), poi 98 (84), 122 (24), 124 (2), 183 (59):

12+2+30+23+84+24+2+59=236.12+2+30+23+84+24+2+59=\mathbf{236}.

SCAN (ascensore). La testina parte verso il cilindro 0 (direzione scelta dalla slide) servendo 37 e 14, arriva a 0, inverte e sale servendo 65, 67, 98, 122, 124, 183:

(53−0)+(183−0)=53+183=236.(53-0)+(183-0)=53+183=\mathbf{236}.

Se la direzione iniziale fosse verso l'alto: 53→19953\to199 (146), poi 199→14199\to14 servendo 37 e 14 (185): totale 331\mathbf{331}. Lo SCAN dipende dalla direzione iniziale.

C-SCAN. Si sale servendo 65, 67, 98, 122, 124, 183, si arriva a 199, si torna subito a 0 senza servire nulla, poi si sale a servire 14 e 37:

(199−53)+(199−0)+(37−0)=146+199+37=382(199-53)+(199-0)+(37-0)=146+199+37=\mathbf{382}

(contando il ritorno di 199 cilindri; senza contarlo, 146+37=183146+37=183).

algoritmo spostamento
FCFS 640
SSTF 236
SCAN 236
C-SCAN 382

Varianti: LOOK (SCAN che si ferma all'ultima richiesta, verso il basso poi verso l'alto: 39+169=20839+169=208) e C-LOOK (si va solo fino alla richiesta più alta, 130130, poi si torna alla più bassa, 169169, poi 2323: 322322).

Parte 2: esercizio 95

La testina è su 50. Si usa la regola "dopo ogni completamento si sceglie, fra le richieste già arrivate, la più vicina nella direzione corrente; se non ce ne sono si inverte". All'inizio la prima richiesta arriva in salita (traccia 70 contro 50), quindi la direzione è verso l'alto.

istante testina richieste pendenti (traccia) direzione scelta spostamento completa a
0-2 50 nessuna – attesa fino a t=2t=2 – –
2 50 1 (70) su richiesta 1 (70) 20 2+20=222+20=\mathbf{22}
22 70 2 (65), 3 (80), 4 (75) su richiesta 4 (75) 5 27
27 75 2 (65), 3 (80) su richiesta 3 (80) 5 32
32 80 2 (65), 5 (120), 6 (60) su richiesta 5 (120) 40 72
72 120 2 (65), 6 (60), 7 (90) su: nessuna sopra 120, si inverte (giù) richiesta 7 (90) 30 102
102 90 2 (65), 6 (60), 8 (80) giù richiesta 8 (80) 10 112
112 80 2 (65), 6 (60) giù richiesta 2 (65) 15 127
127 65 6 (60) giù richiesta 6 (60) 5 132

Sequenza di servizio: 1,4,3,5,7,8,2,61,4,3,5,7,8,2,6, con istanti di completamento (ms) 22,27,32,72,102,112,127,13222, 27, 32, 72, 102, 112, 127, 132. È la stessa tabella della soluzione del corso.

Osservazioni:

  • a t=22t=22 la 2 (65) è già pendente ma è dietro la testina (70): sale prima su 75 e 80;
  • a t=72t=72 la 7 (90) è arrivata a t=38t=38 e viene servita solo dopo l'inversione: parte a t=72t=72, dopo 34 ms di attesa;
  • la richiesta 8 (80) arriva a t=100t=100, durante il servizio della 7, e viene presa durante la discesa, prima della 2 e della 6.

Un simulatore in C

Il programma calcola lo spostamento totale con i quattro algoritmi della parte 1 (non gestisce gli istanti di arrivo della parte 2). Si compila con gcc -Wall -Wextra -o disco disco.c (compilato qui con zig cc per Linux, senza avvisi; non eseguito).

c
/* disco.c - spostamento totale della testina con FCFS, SSTF, SCAN e C-SCAN.
 * Compilare:  gcc -Wall -Wextra -o disco disco.c
 * Usare:      ./disco 53 98 183 37 122 14 124 65 67
 *             (la prima e' la posizione della testina, le altre le richieste;
 *              il disco ha i cilindri da 0 a 199)
 */
#include <stdio.h>
#include <stdlib.h>

#define MAXC 199 /* ultimo cilindro */

static int dist(int a, int b) { return abs(a - b); }

static int cmp(const void *a, const void *b) { return *(const int *)a - *(const int *)b; }

static int fcfs(int testina, const int *r, int n) {
    int tot = 0;
    for (int i = 0; i < n; i++) { tot += dist(testina, r[i]); testina = r[i]; }
    return tot;
}

static int sstf(int testina, const int *r, int n) {
    int fatto[64] = {0}, tot = 0;
    for (int passo = 0; passo < n; passo++) {
        int migliore = -1;
        for (int i = 0; i < n; i++)
            if (!fatto[i] && (migliore < 0 || dist(testina, r[i]) < dist(testina, r[migliore])))
                migliore = i;
        fatto[migliore] = 1;
        tot += dist(testina, r[migliore]);
        testina = r[migliore];
    }
    return tot;
}

/* SCAN: prima verso 0 fino in fondo, poi verso l'alto fino all'ultima richiesta */
static int scan(int testina, int *ord, int n) {
    int tot = 0, sotto = 0, max = testina;
    for (int i = 0; i < n; i++) {
        if (ord[i] < testina) sotto++;
        if (ord[i] > max) max = ord[i];
    }
    if (sotto > 0) tot += testina - 0; /* scende fino al cilindro 0 */
    else return max - testina;         /* niente sotto: si va solo in su */
    if (max > testina) tot += max - 0; /* poi risale fino alla richiesta piu' alta */
    return tot;
}

/* C-SCAN: verso l'alto fino a MAXC, ritorno a 0 (conta), poi fino all'ultima richiesta bassa */
static int cscan(int testina, int *ord, int n) {
    int tot = 0, alto = 0, maxbasso = -1;
    for (int i = 0; i < n; i++) {
        if (ord[i] >= testina) alto++;
        else if (ord[i] > maxbasso) maxbasso = ord[i];
    }
    if (alto > 0) tot += MAXC - testina;
    if (maxbasso >= 0) tot += MAXC + maxbasso; /* ritorno 199 -> 0, poi 0 -> maxbasso */
    return tot;
}

int main(int argc, char **argv) {
    if (argc < 3 || argc > 60) { fprintf(stderr, "uso: %s testina r1 r2 ...\n", argv[0]); return 1; }
    int testina = atoi(argv[1]), n = argc - 2, r[64], ord[64];
    for (int i = 0; i < n; i++) ord[i] = r[i] = atoi(argv[i + 2]);
    qsort(ord, (size_t)n, sizeof ord[0], cmp);

    printf("FCFS   %d\n", fcfs(testina, r, n));
    printf("SSTF   %d\n", sstf(testina, r, n));
    printf("SCAN   %d\n", scan(testina, ord, n));
    printf("C-SCAN %d\n", cscan(testina, ord, n));
    return 0;
}

Con l'esempio della slide l'output atteso è FCFS 640, SSTF 236, SCAN 236, C-SCAN 382 (valori calcolati con lo stesso metodo in Python). Lo SCAN del programma scende prima verso 0.


Errori tipici

  • Fare servire a SCAN una richiesta dietro la testina prima di aver finito la direzione corrente.
  • Considerare nelle scelte anche le richieste non ancora arrivate (nell'esercizio 95, la 7 a t=32t=32).
  • Dimenticare di contare l'andata fino all'estremo (0 o 199) in SCAN e C-SCAN puri, o il ritorno in C-SCAN.
  • Non specificare la direzione iniziale dello SCAN: cambia il risultato (236 contro 331).
  • Dimenticare che la testina aspetta ferma quando non ci sono richieste (da t=0t=0 a t=2t=2).

Versione ripasso

Slide (testina 53, cilindri 0-199, coda 98 183 37 122 14 124 65 67): FCFS 45+85+146+85+108+110+59+2=64045+85+146+85+108+110+59+2=640; SSTF (65, 67, 37, 14, 98, 122, 124, 183) =236=236; SCAN verso 0: 53+183=23653+183=236 (verso l'alto: 146+185=331146+185=331); C-SCAN: 146+199+37=382146+199+37=382 (con il ritorno). LOOK 208, C-LOOK 322.

Ex. 95 (SCAN, 1 ms per traccia, testina in 50, direzione iniziale in su, scelta solo dopo il completamento, tra le richieste già arrivate, inversione se nessuna in direzione). Sequenza 1,4,3,5,7,8,2,61,4,3,5,7,8,2,6; completamenti: 22 (70), 27 (75), 32 (80), 72 (120), 102 (90, dopo l'inversione), 112 (80), 127 (65), 132 (60).

Simulatore. disco testina r...: FCFS, SSTF, SCAN (prima verso 0), C-SCAN con ritorno.

Tabella dell'es. 95 (testina 50, direzione iniziale in su): t=2t=2 richiesta 1 (70) →22\to22; richiesta 4 (75) →27\to27; richiesta 3 (80) →32\to32; richiesta 5 (120) →72\to72; a 120 nessuna sopra: inversione; richiesta 7 (90) →102\to102; richiesta 8 (80, arrivata a 100) →112\to112; richiesta 2 (65) →127\to127; richiesta 6 (60) →132\to132. Si sceglie solo dopo ogni completamento e fra le richieste già arrivate; la testina aspetta ferma se non ce ne sono. Simulatore disco.c: fcfs somma ∣ri−ri−1∣|r_i-r_{i-1}|; sstf sceglie ogni volta la più vicina non servita; scan (prima verso 0): testina+max\text{testina}+\text{max}; cscan: (199−testina)+199+maxbasso(199-\text{testina})+199+\text{maxbasso}. Uscita attesa sull'esempio: 640, 236, 236, 382.

Slide, passi. FCFS: ∣98−53∣=45|98-53|=45, ∣183−98∣=85|183-98|=85, ∣37−183∣=146|37-183|=146, ∣122−37∣=85|122-37|=85, ∣14−122∣=108|14-122|=108, ∣124−14∣=110|124-14|=110, ∣65−124∣=59|65-124|=59, ∣67−65∣=2|67-65|=2. SSTF: 12, 2, 30, 23, 84, 24, 2, 59. SCAN verso 0: (53−0)+(183−0)(53-0)+(183-0). C-SCAN: (199−53)+(199−0)+(37−0)(199-53)+(199-0)+(37-0); senza contare il ritorno 183. LOOK 39+169=20839+169=208; C-LOOK 130+169+23=322130+169+23=322.

Errori tipici: servire richieste dietro la testina; usare richieste non ancora arrivate; dimenticare l'andata all'estremo o il ritorno di C-SCAN; direzione iniziale non dichiarata (236/331).

Teoria: 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 →.

Teoria collegata