Ritorna indietro

Lezione 3.A - Fondamentali di MentOS

Pubblicato il 11/29/21 da SeekBytes – 1078 parole

Che cosa è?

MentOS è un sistema operativo open-source utilizzato per scopi didattici. MentOS può essere scaricato dalla repository Github gratuita: github.com/MentOS. L’obiettivo di MentOS è di fornire un ambiente progettuale che sia abbastanza realistico da mostrare come funziona un vero sistema operativo, ma, allo stesso tempo, abbastanza semplice che gli studenti possano capirlo e modificarlo in modo significativo.

Ma se ci sono così tanti sistemi operativi, perché qualcuno ha scritto MentOS? È vero, ci sono molti sistemi operativi per l’istruzione, MA quanti di loro seguono le linee guida definita da Linux? MentOS mira ad avere le stesse strutture dati e algoritmi di Linux. Ha un codice sorgente ben documentato, e puoi compilarlo sul tuo portatile in pochi secondi! Se sei un principiante nello sviluppo di sistemi operativi, forse MentOS è il sistema operativo giusto per iniziare.

Concetti fondamentali

Registri CPU

Esistono tre tipi di registri nella CPU:

Registri General Purpose

Gli otto registri di uso generale a 32 bit sono usati per contenere operandi per operazioni logiche e aritmetiche, operandi per il calcolo degli indirizzi e puntatori di memoria. Quanto segue mostra per cosa sono usati:

Registri di stato e di controllo

I due registri di controllo di stato a 32 bit sono usati per:

Tabella con le flag:

BitDescrizioneCategoria
0Carry FlagStatus
2Parity FlagStatus
4Adjust FlagStatus
6Zero FlagStatus
7Sign FlagStatus
8Trap FlagControllo
9Interrupt enable flagControllo
10Direction flagControllo
11Overflow flagStatus
12-13Privilege level
….

Privilegi

Ci sono quattro livelli di privilegio, numerati da 0 (il più privilegiato) a 3 (il meno privilegiato).

In qualsiasi momento, una CPU x86 è in esecuzione in un livello di privilegio specifico, che determina quale codice può e non può essere eseguito. Quale delle seguenti operazioni può fare quando la CPU è in modalità utente?

  1. aprire un file
  2. stampare sullo schermo;
  3. allocare la memoria.

Ogni volta che la CPU cambia livello di privilegio, si verifica un cambio di contesto! Esempio di eventi che fanno cambiare modalità di esecuzione alla CPU: Un clic del mouse, la digitazione di un carattere sulla tastiera, una chiamata di sistema…

Programmable Interrupt Controller (PIC)

Un controllore di interrupt programmabile è un componente che combina diversi interrupt su una o più linee della CPU.

Esempio di richiesta di interrupt:

Il timer è un componente hardware a parte della CPU. Ad una frequenza fissa, il timer alza un segnale collegato all’IRQ 0 del PIC. Linux fissa la frequenza del timer a 100 Hz. La CPU esegue un processo utente per un massimo di 10 millisecondi, poi il Kernel riprende il controllo della CPU.

Organizzazione della memoria

Il kernel applica la memoria virtuale per mappare gli indirizzi virtuali agli indirizzi fisici. La RAM è virtualmente divisa in spazio Kernel (1GB) e spazio utente (3GB). La CPU in Ring 0 ha visibilità su tutta la RAM. La CPU nel Ring 3 ha visibilità solamente dello spazio utente.

Kernel Doubly-Linked list

I kernel dei sistemi operativi, come molti altri programmi, hanno spesso bisogno di mantenere elenchi di strutture di dati. Per ridurre la quantità di codice duplicato codice, gli sviluppatori del kernel hanno creato un’implementazione standard di liste circolari a doppio link.

Pro:

Contro:

Per utilizzare il meccanismo della lista, gli sviluppatori del kernel hanno definito la struttura dei dati della testa della lista come segue:

typedef struct list_head {
	struct list_head *next, *prev;
} list_head_t;

Una list_head rappresenta un nodo di una lista!

Per utilizzare la funzione di lista di Linux, abbiamo solo bisogno di incorporare una testa di lista all’interno delle strutture che compongono la lista.

struct mystruct {
	//...
	list_head_t list;
	//...
};

Le istanze di mystruct possono ora essere collegate per creare una lista double-linked!

La testa di una lista deve essere una struttura di tipo list_head_t

struct mystruct {
	//...
	list_head_t list;
	//...
};

La head è sempre presente nella lista circolare. Se una lista è vuota, allora esise solo la head.

Funzioni di supporto

Funzioni di supporto da usare con una lista circolare a doppio link.

List_entry

(type *) list_entry(list_head_t *ptr, struct_type, field_name)

Restituisce la struct che incorpora una testa di lista. In dettaglio:

Esempio di come utilizzare la list_entry.
// Example showing how to get the first mystruct from a list
list_head_t *listptr = head.next;
struct mystruct *item = list_entry(listptr, struct mystruct, list);

List_for_each

Itera su ogni elemento di una lista doppiamente collegata. In dettaglio:

Partendo dal primo elemento della lista, ad ogni chiamata ptr viene impostato con l l’indirizzo del prossimo elemento della lista fino a quando non viene raggiunta la sua testa.

Esempio di come utilizzare la list_for_each
list_head_t *ptr;
struct mystruct *entry;
// Inter over each mystruct item in list
list_for_each(ptr, &head) {
	entry = list_entry(ptr, struct mystruct, list);
}