Menu

BeOS: uno sguardo all'interno

BeOS è un sistema Unix like che affonda le radici nel sistema operativo (sconosciuto ai più): Xinu ("Xinu Is Not Unix", acronimo ricorsivo).

Xinu-logo

Xinu Logo

Xinu è un sistema operativo Unix-like, sviluppato da Douglas Corner per motivi didattici presso l’università di Pudue (Indiana, USA) negli anni 80. Il nome oltre ad essere ricorsivo è esattamente Unix letto al contrario. Il sistema fu portato su molte piattaforme, tra cui:  DEC LSI-11 e VAX,  Sun-2 and Sun-3 workstations, Intel x86, PowerPC G3 e MIPS, oltre ad essere usato per alcuni modelli di stampanti Lexmark.

La scelta di Xinu permette a BeInc di evitare, fin dalle fasi iniziali, tutti quei problemi legati alla necessità di mantenere completa compatibilità con librerie e applicazioni preesistenti, causa principale delle difficoltà che si possono riscontrare in tutti i sistemi operativi esistenti, che ha permesso, inoltre, di cercare liberamente nuove soluzioni e di implementare nuove funzionalità senza vincolo alcuno.

BeOs è strutturato su 3 livelli: il Kernel, i server e i kit, con le applicazioni che operano allo stesso livello dei kit.

Il kernel è effettivamente classificabile come un macrokernel (come la maggior parte dei kernel di derivazione Unix(tm) e non un microkernel (come ad esempio il kernel di QNX), altro errore abbastanza diffuso, dato che gestisce molteplici funzionalità al di là di quelli che sono i compiti di un microkernel tradizionale.

os_structure_mini

Tipologie di Kernel (click per ingrandire)

Il kernel è scritto quasi completamente in C ed offre un'API sempre basata sul C per gestirne le funzionalità, classificabili in 2 categorie: funzioni per manipolare gli oggetti fondamentali gestiti dal kernel, ovvero i team (processi), i thread, i semafori, le porte, le aree (la memoria), i file e funzioni per accedere nella maniera piu' astratta possibile all'hardware, funzioni comunque utilizzabili solo dai driver caricati dinamicamente dal kernel, proteggendo quindi il sistema da accessi più o meno accidentali a componenti critici del sistema.

Il kernel poi presenta una ulteriore peculiarità rispetto all'architettura tipica di unix, dato che è esso stesso multithreaded, caratteristica fondamentale per garantire al BeOS le ottime prestazioni realtime, come vedremo in seguito.

La compatibilità con lo standard Posix è garantita dalla presenza della libreria standard C, utilizzando l'implementazione GNU, che offre anche un buon supporto per le molteplici funzioni presenti nelle varie varianti di unix. La presenza di questa libreria è stata a sua volta fonte di confusione negli anni passati, in quanto molte persone associavano la sua esistenza alla presenza di un vero e proprio kernel Unix (idea rinforzata dal fatto che il terminale usato da BeOS si basa sul famoso Bash).

A livello del kernel, poi, vi sarà prossimamente un cambiamento importante in quanto il sistema di networking, attualmente in fase di riscrittura, verrà integrato direttamente nel kernel e non sarà più gestito da un server separato. Il motivo principale di questa decisione è legato alle prestazioni superiori che si possono ottenere con questo approccio che permette di trasferire i dati in tempi nettamente inferiori.

I server sono normali processi funzionanti a livello utente, che gestiscono tutte quelle funzionalità proprie del sistema operativo che non sono però controllate direttamente dal kernel. Il vantaggio di questa soluzione è una maggiore flessibilità e modularità del sistema (Be Inc. ha già saputo sfruttare questo vantaggio durante la fase di sviluppo di BeIA, la versione di BeOS per le Internet Appliances, potendo così creare agevolmente un sistema compatto semplicemente selezionando i componenti utili) e una maggiore solidità (se il server si blocca in generale è possibile riavviarlo senza danni al sistema, ad eccezione ovviamente delle funzioni che il server stesso stava svolgendo).

I kit rappresentano, infine, il punto di accesso al sistema da parte delle applicazioni, che non dialogano direttamente con i server, ma utilizzano le interfacce ad oggetti fornite dai kit per interagire con essi. I vantaggi di questo approccio sono ancora una maggiore modularità e flessibilità (non essendovi un legame diretto tra l'interfaccia e l'implementazione delle funzioni ad essa connesse, è possibile modificare in maniera anche profonda il funzionamento interno dei componenti del sistema senza intaccare la compatibilità con il software esistente; inoltre l'indipendenza dell'interfaccia dal resto del sistema ha permesso lo sviluppo di una API molto lineare, di facile comprensione ed utilizzo, dato che non è dovuta scendere a compromessi con problemi di compatibilità con il passato o complessità legate a dettagli di implementazione delle funzionalità di basso livello).

Le applicazioni infine si trovano allo stesso livello dei kit, in quanto durante il caricamento le applicazioni vengono linkate con le librerie di sistema che contengono il codice dei vari kit.

Il percorso di esecuzione delle funzioni del kernel e dei kit è differente: nel caso di funzioni gestite direttamente dal kernel, viene utilizzato il tradizionale metodo delle trap per passare da modo utente a modo supervisore e iniziare l'esecuzione della relativa funzione. Nel caso dei kit la maggior parte delle funzioni crea un messaggio che viene inviato ad un server per l'elaborazione, il quale, a seconda dei casi, restituisce una risposta che può essere sincrona o asincrona rispetto al messaggio inviato. L'operazione risulta quindi notevolmente più complessa, in quanto porta alla chiamata di più funzioni del kernel per scrivere e leggere il messaggio inviato ad una porta oltre ad un cambio di contesto (semplificando, il sistema deve interrompere l' esecuzione del thread che ha inviato il messaggio e attivare il thread che lo ha ricevuto); nonostante questo il sistema è in grado di gestire un elevato numero di messaggi al secondo garantendo ottimi tempi di risposta anche sotto notevoli carichi di lavoro, elemento chiave per ottenenere buone prestazioni a fianco della notevole flessibilità che questo approccio offre.

I due elementi chiave nell'architettura del sistema sono quindi l'uso esteso dei thread e dei messaggi: distribuendo i compiti su più thread è possibile migliorare notevomente i tempi di risposta del sistema e sfruttare più a fondo i sistemi multiprocessore, usando un efficiente sistema di scambio dei messaggi è possibile coordinare l'azione dei singoli thread scrivendo poco codice (a vantaggio delle prestazioni e della affidabilità dei programmi) e consumando di conseguenza una quantità di risorse molto limitata. Inoltre la possibilità di interrompere un thread quando sta eseguendo codice all'interno del kernel rende in pratica impossibili quegli irritanti blocchi temporanei (specie durante la riproduzione di brani audio o video) che si possono riscontrare su altri sistemi.