Perché ci serve lo Slab?

Il kernel Linux usa il Buddy Algorithm per gestire la memoria fisica. Il Buddy divide la memoria in grandi blocchi (potenze di 2). Se il kernel ha bisogno di un piccolo spazio di 65 pagine, il Buddy gliene dà 128. Questo spreco di 63 pagine si chiama frammentazione interna.
Dato che il kernel crea e distrugge continuamente piccoli oggetti (come i descrittori di processo task_struct), usare solo il Buddy esaurirebbe la memoria in un attimo. La soluzione? Lo Slab Allocator.

Livello 1: Le Object Cache

Guarda la parte alta dell’immagine. Il kernel non butta i suoi oggetti a caso nella memoria. Li organizza in Object Caches.

  • Esiste una cache specifica per ogni tipo di oggetto. Se il kernel deve creare un nuovo processo, andrà dritto nella cache chiamata task_struct_cache.
  • Il vantaggio (Caching): Quando un processo muore, il suo task_struct non viene restituito al sistema centrale. Viene “ripulito” e tenuto in questa cache, pronto per essere riciclato istantaneamente appena servirà creare un altro processo. Questo azzera i tempi di inizializzazione.

Livello 2: Le Liste degli Slab

Ogni Object Cache è formata da blocchi di memoria chiamati Slab. Per trovare subito lo spazio libero, la cache divide i suoi slab in tre liste:

  1. Slab Pieni (Full): Tutti i posti sono occupati. Il kernel li ignora.
  2. Slab Parziali (Partial): Hanno alcuni posti occupati e altri liberi. È qui che il kernel cerca per prima cosa.
  3. Slab Vuoti (Empty): Sono completamente vuoti. Vengono usati solo se gli slab parziali finiscono.

Livello 3: Dentro lo Slab (L’Anatomia e l’Allocazione)

Guarda il centro dell’immagine (“Micro-Architettura di Slab C”). Questo è il cuore del sistema. Uno slab parziale è diviso in due parti principali:

  • Gli Slot: Sono gli spazi fisici (i “parcheggi”) dove vengono messi i dati. Nell’immagine ce ne sono 6 (da 0 a 5). Quelli verdi sono occupati, quelli bianchi sono liberi.
  • Lo Slab Descriptor: È il “cervello” di quel blocco. Contiene le istruzioni per assegnare i posti alla velocità della luce. Usa due strumenti:
    • Il free pointer: Indica qual è il primo slot libero da usare in questo momento.
    • L’array bufctl: È una mappa del tesoro che dice: “Se usi questo posto, il prossimo posto libero lo trovi all’indice X”.

L’Esempio Pratico (La sequenza in basso nell’immagine)

Seguiamo i 4 passaggi in fondo all’immagine per vedere cosa succede esattamente quando il kernel ha bisogno di memoria:

  1. La Richiesta: Il kernel bussa allo Slab C e dice: “Mi serve spazio per un task_struct!“.
  2. L’Assegnazione Immediata: Lo Slab Descriptor non perde tempo a scansionare gli slot. Guarda il suo free pointer, che in quel momento vale 1. Assegna immediatamente lo SLOT 1 al kernel.
  3. L’Occupazione: Lo SLOT 1, che prima era bianco (libero), ora diventa verde (occupato).
  4. L’Aggiornamento Intelligente: Ora lo Slab deve sapere qual è il prossimo posto libero. Come fa? Va a leggere dentro l’array bufctl alla posizione 1. Lì dentro c’è scritto 5. Il free pointer viene aggiornato al valore 5. La prossima volta che qualcuno chiederà spazio, andrà dritto allo SLOT 5.