Newsgroup: it.comp.os.dibattiti
Titolo: Ricompilazione del kernel di Linux efficiente?

Una delle cose che mi colpiscono di più della
ricompilazione del kernel Linux è l'inefficienza.
Un kernel scritto per CPU moderne dovrebbe
supportare, in teoria, tutte le istruzioni estese del
processore, in modo da sfruttare tutte le peculiarità.
Sotto Linux, distribuzioni come Mandrake o RedHat
forniscono kernel compilati per i386 (Mandrake 9.2)
o Celeron (RedHat). Il perchè è chiaro: l'installer non
può eseguire una compilazione in fase di installazione
(lo fa solo Gentoo), perchè sarebbero necessarie
varie ore di calcolo: allora, provvede semplicemente
a copiare dalla ISO di installazione un kernel che
contenga quanto utile e che sia scarsamente
ottimizzato, proprio perchè così siamo certi che il
sistema alla prima partenza non si bloccherà.
La situazione è ancora peggiore con le applicazioni.
In teoria anche le librerie e le applicazioni dovrebbero
essere compilati con le istruzioni estese del processore.
In pratica, questo non viene fatto già nella distribuzione,
e l'unico modo per ottenere questo è prendere i sorgenti
e provvedere manualmente alla ricompilazione.
Ma anche volendo distribuire pacchetti che supportano
in modo intensivo le istruzioni estese, sorge un altro problema:
la memoria utilizzata dal binario.
Il fatto è che attualmente ci sono su piattaforma Intel i386
diversi set di istruzioni estese che sono del tutto incompatibili:
i386, i586, MMX, 3DNOW, 3DNOW2, ISSE, ISSE2, AMD64.
Volendo distribuire un binario che contiene al suo interno delle
ottimizzazioni per ognuno di questi processori, il risultato sarà
un binario enorme (perchè il codice deve essere ripetuto nel
binario per le diverse piattaforme, ma viene tutto portato in
memoria in fase di caricamento).
Sotto VegetaOS le cose vanno in maniera differente.
Ogni binario (applicazione o librerie), è contenuto in un file
che ha la seguente struttura:
1) Headers;
2) Main code;
3) Segment            i386
4) Segment            i586
5) Segment            iMMX
6) Segment            i3DNow
7) Segment            i3DNow2
8) Segment            iSSE
9) Segment            iSSE2
10) Segment          AMD64
I descrittori contengono una tabella con varie informazioni.
Sfruttando le informazioni in questa tabella, l'OS in fase di
caricamento provvede a portare in memoria solo il Main code
(che contiene procedure scritte in i386), ed il segment che
contiene il codice con le istruzioni ottimizzate per la particolare
architettura.
Tutto questo viene fatto in maniera totalmente
trasparente all'utente. In tal modo si ottengono i seguenti
vantaggi:
a) In memoria sono presenti solo la tabella delle procedure, il
main code ed il segment adeguato alla CPU su cui l'OS sta
girando: il codice relativo ad altre piattaforme non viene
caricato dall'OS e viene quindi semplicemente "scartato";
b) Ogni libreria lavora, su qualsiasi piattaforma, in maniera
ottimizzata ed alla massima velocità;
c) Possono essere distribuiti binari multipiattaforma, che si
adattano automaticamente al tipo di processore che gira sulla
CPU.
Lo svantaggio consiste nel fatto che la compilazione che
genera un binario siffatto dura fino a 7 volte la normale
compilazione (ma il problema non si pone per l'utente
finale, che scarica i pacchetti già compilati e pronti).
Inoltre, il binario risultante è particolarmente corposo (e questo
è il prezzo da accettare per lavorare con questo sistema,
anche se con gli hard disk attuali non è insopportabile).
Sotto VegetaOS tutto il microkernel, così come i sottosistemi
a ring 1, le librerie, e l'interfaccia, le applicazioni utente fornite
con l'OS saranno compilati con questa tecnologia.
Mi chiedo: perchè sotto Linux nessuno ha mai pensato di
creare qualcosa del genere?
Saluti
Vegeta
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.520 / Virus Database: 318 - Release Date: 19/09/03

 creare qualcosa del genere?
Tu farnetichi... Un binario eseguibile non si puo` caricare solo in
parte. Viene caricato tutto in memoria e poi eseguito. Tra l'altro per
fare quello che vuoi tu devi anche scriverti un compilatore di C/C++
tutto tuo, personalizzato. In pratica, per evitare giri di parole,
dici boiate. Credi forse che windows sia compilato col supporto a
tutte le istruzioni esistenti? Sbagli, e` compilato con il minimo
delle istruzioni esistenti. RH9 da la possibilita` di scegliere anche
tra binari i686 cosi` come mandrake. Tutte quelle compilate con gcc >=
3.2 poi non sono compatibili con i386 se non erro.
E` assurdo avere tutte le versioni ottimizzate nello stesso binario,
ma veramente assurdo... Il binario enorme uccide le prestazioni
perche` va caricato in ram prima di essere elaborato e con le
dimensioni che avrebbe impiegherebbe 10 volte tanto all'avvio e
occuperebbe MOLTA piu` memoria.
Se la tua idea invece e` quella di lavorare direttamente sul disco e
caricare selettivamente allora impiegherai 1000 volte piu` tempo ad
avviare un programma...
Mi ripeto: prima di volare alto, impara le basi (che hai parecchio
carenti) e poi si vedra`.
Vuoi un sistema ultra personalizzato per la tua macchina? Scarichi i
sorgenti e compili. Se io ho un Athlon-xp cosa cacchio me ne frega di
avere anche la versione per PIII? 
Vuoi le versioni ottimizzate? Compilalo una volta per ogni
architettura e una volta per ogni opzione e poi distribuiscilo. Voglio
vederti quando un software puo` supportare 4 o 5 librerie diverse in
combinazioni varie a fare tutte le compilazioni di tutti i
binari... Per me sei matto, ma matto forte.
-- 
Valentino Volonghi, Regia SpA, Milan
Linux User #310274, Gentoo Proud User

 occuperebbe MOLTA piu` memoria.
Ovviamente so benissimo che si possono usare gli ifdef in determinati
punti per usare o meno determinate istruzioni asm e via dicendo.  Solo
che lo si fa per set di istruzioni normalmente comuni al maggior
numero di processori oppure per la cpu piu` diffusa/migliore per quel
lavoro.
ES: le sse2 sotto alcuni programmi per windows, vengono usate solo con
un P4 e non con un Athlon e via dicendo, pur mantenendo lo stesso
eseguibile, ma qua si tratta di rifare una piccola parte del codice
per supportare una architettura nuova, non di avere N versioni diverse
di tutto il codice.
La cosa in se` puo` anche essere realizzabile, ma non nel modo pensato
da Vegeta. Cosi` la penso io.


 3.2 poi non sono compatibili con i386 se non erro.
No, Valentino. Perchè l'OS prima legge l'header, e
poi provvede semplicemente a leggere la parte successiva
(il main code), seguita da un seek sul file binario che
porta al segment che interessa, e da una successiva lettura
del segment che interessa. Alla fine tutto viene portato
in ram.
Rispetto all'approccio tradizionale hai solo un seek in
più. Vorrei ricordare che il codice è costituito da dati.
E come i dati, puoi portarlo in memoria parzialmente.
Naturalmente resta il problema degli indirizzamenti.
Però, supponendo di lavorare con indirizzamento lineare,
se x è l'indirizzo di base della libreria in memoria (lo assegna
l'OS), y è l'indirizzo di base del main code (lo calcola in
fase di loading l'OS in base alla formula x+ampiezza area dati),
z è l'indirizzo di base del segment che ci interessa (lo calcola
in fase di loading l'OS in base alla formula x+ampiezza area dati+
dimensioni del main code), per chiamare una procedura del
main code con offset relativo P1 è necessaria solo una CALL
all'indirizzo Y+P1, mentre per chiamare una procedura
ottimizzata del segment con offset relativo P2 è necessaria
solo una CALL all'indirizzo Z+P2.
Come si vede tutto può essere svolto con minimo dispendio
di calcoli.
Saluti
Vegeta
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.520 / Virus Database: 318 - Release Date: 18/09/03

 che ha la seguente struttura:
Non vedo vantaggi nella tua idea. Piuttosto c'è lo svantaggio di dover
ospitare su memoria secondaria anche il codice non supportato sulla
piattaforma di esecuzione. Inoltre rischi di dover duplicare anche codice
identico (quello non vettoriale) tra le varie versioni i386/MMX/ISSE...
Saluti.
-- 
\/               
wirix...@libero.it
          ICQ UIN: 3233084
/\ e l l o s s   (per rispondermi in privato, elimina il DEMONE)


Non lo fai, perchè il codice identico tra le varie versioni è
in quella parte del binario che prende il nome di main-code.
Solo le procedure ottimizzate stanno nei vari segment e
vengono linkate dinamicamente in fase di caricamento.
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.520 / Virus Database: 318 - Release Date: 18/09/03

 un P4 e non con un Athlon e via dicendo
non in alcuni programmi, in tutti. Gli athlon xp ed mp non hanno le sse2
ma solo le sse.

 del genere?
perché, a differenza, tua sanno quello che fanno. E soprattutto lo fanno,
non ne parlano e basta.

 vengono linkate dinamicamente in fase di caricamento.
ha ha ha ha :-)
che perla! :-)

architettura.
Forse casco dal fico, ma... Perché, invece di questi onanismi mentali
sulla struttura degli eseguibili e sul caricamento degli stessi, non
sposti l'attenzione sull' ISTALLER?
Voglio dire, liberissimo di distribuire i pacchetti ottimizzati per le
varie sottoversioni (cosa che è inutile per il kernel e che le
applicazioni risolvono tramite DLL, come ti è stato detto. Ma se ne
sei convinto, insisti pure). Solo, al momento dell'istallazione del
software l'istaller legge il tipo di processore su cui gira al momento
e istalla solo quello che tu chiami Main+Segment.
Unico difetto: hai dei problemi se sostituisci la CPU (ad esempio,
P4->AMD), ma con un'oculata gestione dei pacchetti (e un demone che
all'avvio ti informi del fatto che devi reistallare questo e quel
software) puoi risolverlo tranquillamente 

 dinamicamente in fase di caricamento.
Preciso che quello che hai in mente tu non è linking dinamico, ma
piuttosto un'inedito linking statico con loading selettivo e binding a
loading time...
Di nuovo: cosa ci guadagno, rispetto a un sistema in cui
le librerie risiedono su file indipendenti e sono collegate dinamicamente?
Un'ulteriore dettaglio che prima mi era sfuggito: il collegamento dinamico
(che NON è quello che hai in mente tu) consente la condivisione del
codice in memoria tra diversi processi, vale a dire che se due processi
utilizzano la stessa libreria, essa è mappata contemporaneamente su due
spazi di indirizzamento diversi, probabilmente con indirizzi virtuali
diversi, ma sugli stessi indirizzi fisici. Questo con il tuo modello non
è possibile farlo.
Sicuramente sei pieno di idee, ma fossi in te ci andrei con più calma.
Dai tuoi post risulta evidente che hai ancora un po' di confusione con
certi concetti di base dei sistemi operativi e che soprattutto hai una
conoscenza approssimativa delle architetture che vorresti supportare. E'
perfettamente normale, credo che prima di avere una visione abbastanza
matura dello sviluppo di un kernel occorra progettarne almeno 3, e
scommetto che su questo gruppo nessuno ha fatto qualcosa del genere (se
c'è qualcuno che ha tanta esperienza, esercitazioni accademiche incluse,
sarò felice di essere smentito).
Comunque io proverei a ripartire da zero con un progettino sperimentale da
provare su un'architettura più lineare degli x86, così scoprirai i
piccoli e banali drammi dell'implementazione dei kernel.
(Prima che faccia la figura del saccentuzzo, sarà meglio precisare che la
mia esperienza si riduce a un minisistema operativo per sistemi mips,
svolto come progetto universitario - un lavoro non semplicissimo che mi ha
impegnato per sei mesi circa, ma pur sempre un progettino)



Perchè non è possibile farlo, scusa?

 piccoli e banali drammi dell'implementazione dei kernel.
che architettura proporresti per un newbie? mips? perché?
 

 ha scritto nel messaggio
news:g9souvkhuntesa861...@4ax.com...

All'inizio, infatti, avevo deciso di fare così.
Ma poi ha riflettuto. Per esempio, che cosa succede se io ho 200
applicazioni installate, magari con gli installer che stanno su diversi
cd-rom?
Che ogni volta che cambio motherboard, o processore, devo
reinstallare praticamente tutto il software applicativo.

 Perchè non è possibile farlo, scusa?
"Impossibile" magari no, improponibile sì. Come faccio a dire al sistema
operativo che il flusso i dell'eseguibile x è lo stesso che il flusso j
dell'eseguibile y, e che quindi la memoria può essere risparmiata? Magari
si può trovare un workaround, ma quando un'idea comincia a richiedere
trucchetti del genere per essere implementata nel mondo reale bisognerebbe
cominciare a pensare che forse non era tanto geniale come credevamo.


 che architettura proporresti per un newbie? mips? perché?
Io non propongo mips, io ho *usato* mips. Il fatto che mips sia
indubbiamente più pulito di x86 unito a un supporto per caratteristiche
avanzate (indirizzamento virtuale) molto semplice, lo rendono un'ottima
scelta per esercitarsi sui sistemi operativi; ma non posso dire se è la
scelta migliore perché io, in realtà, conosco solamente mips e x86.
Per mips esistono emulatori didattici di buon livello (come il nostro MPS
http://www.cs.unibo.it/~morsiani/
) che consentono di concentrarsi sullo
sviluppo del sistema operativo senza preoccuparsi troppo dei dettagli
dell'hardware, e che tuttavia rendono possibile scrivere gestori della
memoria fisica e virtuale analoghi a quelli del mondo reale. Insomma uno
può proprio sbizzarrirsi, io stesso mi sono divertito a scrivere un
rudimentale gestore della memoria e imitare un'architettura microkernel
(imitarla soltanto, in realtà dei microkernel c'era solamente la
filosofia progettuale). E ci si rende conto che anche a voler fare le cose
facili, supportati da un'architettura semplice e lineare, ci sono miriadi
di problemi da risolvere e di ore di lavoro da buttare :-).
Prima che esca dal seminato, torniamo a mips. Non è sicuramente la mia
architettura preferita, è solamente la meno peggio tra quelle che
conosco. Ho trovato certe sue caratteristiche irritanti: ad esempio lavora
soltanto con indirizzamento virtuale, il che richiede performance del tipo
di saltellare sulle mani toccandosi il naso per gestire gli spazi di
indirizzamento. Inoltre supporta in hardware solo 64 spazi di
indirizzamento (ma anche senza occuparsi di questo dettaglio, si hanno
abbastanza problemi su cui sbattere la testa).
In conclusione credo che su mips si possa fare tutta l'esperienza di cui
si ha bisogno prima di lavorare, in futuro, con un'architettura quale x86.



In realtà, il problema non si pone. Io potrei anche usare
un'opzione del compilatore che mi crea una libreria con
il solo "main code", e senza segmenti. Questo equivale
all'approccio tradizionale: tutto il codice in memoria e lo
stesso per qualsiasi architettura.


reinstallare praticamente tutto il software applicativo.
Lascio perdere il quoting un po' sbrigativo.
Credi davvero di arrivare mai ad avere 200 applicazioni ottimizzate
sul tuo PC? Ad esempio, credi che un text editor (non un word
processor, un editor) possa trarre giovamento da una qualsiasi
ottimizzazione? Al massimo potrai compilarlo per i586 anziché i386, ma
di sicuro non userai nč MMX nč SSE nč simili. E cosě molti altri
software generici (Newsreader, P2P, Visualizzatori d'immagini...).
Quindi, a meno che il tuo Upgrade non sia 486->P4, dei famosi 200
programmi (mai conosciuto nessuno, tra l'altro, che avesse 200
programmi contemporaneamente sul PC) dovrai correggere l'istallazione
di al massimo una 30ina: sempre meglio che ricompilare tutto per la
nuova piattaforma o di formattare e reistallare da zero.

 è possibile farlo.
[cut]
   Sei sicuro di 'sta cosa ??? Non e` una domanda polemica, e` pura 
curiosita`: tempo addietro postai proprio una questione a tal proposito, 
non essendomi stato chiare quello che avevo trovato in rete...
   Avresti qualche riferimento, per piacere ???
Vh
-- 
                          | rombando dal loro luogo
\|/ ____ \|/   \ ||_|     | d'origine, i buchi neri 
"@'/ ,. \`@"    \|| |     | tracannavano energia e da
/_| \__/ |_\ Vax Headroom | bolle frattali nascevano
   \__U_/                 | 

    Avresti qualche riferimento, per piacere ???
Per il momento no...


 Per il momento no...
   E adesso ??? ;-))))))
Vh
-- 
                          |    I veri programmatori non
\|/ ____ \|/   \ ||_|     | commentano il loro codice. E`
"@'/ ,. \`@"    \|| |     | stato duro scriverlo, deve
/_| \__/ |_\ Vax Headroom | essere duro capirlo.
   \__U_/                 |

    E adesso ??? ;-))))))
Prova a googlare con "DLL memory sharing" ;).


 Prova a googlare con "DLL memory sharing" ;).
   Peccato che non siano le DLL il mio dubbio... Provero` comunque, magari 
mi portano da qualche parte "interessante"...
Saluti...
Vh
-- 
                          |  Del resto mimporta 'nasega sai
\|/ ____ \|/   \ ||_|     |  Ma fatta bene
"@'/ ,. \`@"    \|| |     |  Del resto mimporta 'nasega sai
/_| \__/ |_\ Vax Headroom |  Ma fatta bene che non si sa mai
   \__U_/                 |  Che non si sa mai, che non si sa mai

 per ogni eseguibile, ma non ne sono per nulla sicuro...
In memoria c'e`  una sola copia del segmento codice  mappata nei diversi
processi (a dire il vero potrebbe  anche non essere in memoria, potrebbe
essere  sul disco).   Ovviamente ogni  processo ha  il proprio  segmento
dati.
Luca
-- 
Home: 
http://kronoz.cjb.net
Carpe diem, quam minimum credula postero. (Q. Horatius Flaccus)

 per ogni eseguibile, ma non ne sono per nulla sicuro...
piů di una volta. almeno lsof lista le stesse librerie una volta per ogni
programma che le usa.
 

 programma che le usa.
Prima di dire quello che hai detto hai provato a sommare la colonna SIZE?
Perche` io l'ho fatto e mi viene questo:
1501793601
Io di ram ho 256Mb su questo portatile e circa la stessa swap. La vedo
dura di avere 1,5Gb di ram occupata.


 codice? sì ne sono abbastanza sicuro.
E invece ti sbagli.
Immaginiamo di avere due applicazioni, che per comodità
chiameremo Gimp e VirtualDub, che sono state compilate
in modo da usare la medesima libreria, che chiameremo
ImageDec.Libr.
ImageDec.Libr è una libreria che si occupa di visualizzare
delle immagini grafiche (in vari formati) sullo schermo.
Siccome sia Gimp che VirtualDub hanno bisogno di
ImageDec, è inutile che la stessa librerie sia caricata
due volte in memoria. La libreria dovrà essere caricata
in memoria una volta sola e condivisa.
Vediamo di capire come funziona (questa tecnica io l'ho
già spiegata in dettaglio qualche tempo fa, ma ora voglio
essere molto più preciso).
Innanzitutto, ogni applicazione sotto VegetaOS può essere
caricata solo a condizione che sia stata preventivamente
effettuata una procedura detta "inoculazione".
In genere l'inoculazione viene svolta dall'installer. Siccome
durante il processo di inoculazione viene sempre eseguita
una scansione dell'applicativo (allo scopo di verificare
l'eventuale presenza di virus o altri malware), la sicurezza
del sistema contro l'esecuzione di codice virale è
sicuramente maggiore rispetto a Windows (anche se non
è perfetta).
Immaginiamo allora di volere usare Gimp. Abbiamo detto
che non possiamo lanciarlo "al volo" ma che dobbiamo
prima installarlo.
I FILE VIF
Ogni applicazione distribuita sotto VegetaOS è contenuta
in un file VIF. I file VIF sono una estensione del concetto
di RPM. Se un utente vuole installare un programma, è
sufficiente che clicchi sul file VIF per far partire il central
installation manager che si occuperà del resto del
processo.
Il file VIF ha la seguente struttura:
a) codice dell'installer (in linguaggio interpretato);
b) eventuali sorgenti dell'applicativo o delle librerie;
c) eventuali binari dell'applicativo o delle librerie;
I componenti b) e c) sono compressi in un formato ad alto rapporto
di compressione.
A noi interessa il codice dell'installer.  Infatti, sotto VegetaOS
gli installer non sono dei binari (come sotto Windows), ma
sono dei programmi interpretati, che vengono eseguiti da
un interprete detto Central Installation Manager (CIM).
Questo significa che il programma che si occupa dell'installazione
NON è un binario eseguibile. Si tratta invece di un insieme di
comandi per la Central Installation Manager che vengono
eseguiti sotto il controllo dell'interpreter.
Il programma di installazione che viene eseguito da CIM, può
fare diverse cose. Per esempio, può caricare i sorgenti eventuali
distribuiti nei file VIF e provvedere a compilarli. Oppure,
può caricare direttamente i binari contenuti nel file VIF,
magari dopo averli decrittati (allora, è possibile inviare ad
un cliente un file VIF, che si può installare solo dopo che
questo ha inserito un apposito codice di accesso).
Qualsiasi sia la strada seguita, alla fine il Central Installation
Manager si troverà con un insieme di binari (eseguibile +
librerie), ed un insieme di file di dati.
Ora deve avvenire l'inoculazione vera e propria. Il codice
interpreter chiede al sistema operativo di assegnargli:
a) un'area del disco (che appare all'utente come un file,
e che prende il nome di Block-ice), in cui dovranno essere
copiati tutti i file necessari al programma tranne le librerie;
b) un codice di 32 cifre che è generato casualmente dal
sistema operativo.
Questo codice si chiama INITIALIZATION CODE, ed
è diverso da applicazione ad applicazione. Non solo, ma
cambia a seconda della postazione in cui si lavora, perchè
viene generato casualmente dall'OS ogni volta che viene
installato un nuovo applicativo.
Il block-ice, è diviso in due parti. Una prima parte detta
Prestart Application Area (PAA), di appena 65536 byte.
Una seconda parte, detta Extended Application Area (EAA),
che al contrario non ha limitazioni nelle dimensioni.
Immaginiamo allora che, in fase di installazione, il codice
interpreter nel file VIF esegua il comando (riconosciuto
subito dal CIM):
InoculateApplication
Vediamo che cosa fa a questo punto il Central Installation
Manager.
a) Innanzitutto il CIM lancia una scansione antivirus dei
binari che dovranno essere installati (sia che si tratti di
codice che era già distribuito compilato nel file VIF,
sia che si tratta di codice che è risultato dalla
compilazione). Se il codice che si vuole installare è
infetto, il CIM arresterà subito il processo di installazione
segnalando che il pacchetto è potenzialmente dannoso
per il sistema.
b) Se il controllo a) viene superato, il CIM deve
provvedere all'inoculazione delle librerie. Il Manager
controlla quali librerie vuole installare il programma
(è anche possibile che il file VIF non contenga certe
librerie, ma che il software le richieda ugualmente:
tutte queste possibilità possono essere previste da
chi scrive il codice dell'installer e gestite attraverso
opportune istruzioni).
Se Gimp vuole installare la libreria ImageDec.Libr,
potrà farlo. Il sistema provvederà a copiare una copia
di ImageDec.Libr in un volume file integrato (e riservato
al sistema operativo), che si chiama Libraries.RVF
(RVF sta per Reserved Volume Files). A differenza
di ciò che accade in Windows, se esistono due versioni
di due diverse librerie, esse vengono **entrambe** mantenute
sul disco. Inoltre, la gestione di Libraries.RVF può essere
fatto solo attraverso opportune utility (e non con il file
system), con la conseguenza che è impossibile cancellare
accidentalmente una libreria.
c) Dopo avere inoculato le librerie, il sistema provvede
a creare il block-ice (nel percorso indicato dall'utente).
Nel block-ice vengono copiati tutti i file di supporto
dell'applicazione.
Mentre la Extended Application Area viene mantenuta in
chiaro, la Prestart Application Area viene crittografata
con una chiave a 128 bit. La chiave di decrittazione viene
mantenuta all'interno del sistema operativo, in un database
non visibile alle applicazioni.
d) Al termine del processo, il Central Installation Manager
riporta l'Initialization code al programma di installazione
(che abbiamo detto è scritto in linguaggio interpretato):
in genere l'unica operazione che fa il programma è
accedere alla Prestart Area e memorizzarvi il codice
di inizializzazione (in un file KEY.DAT) ed un altro
programmino che si chiama Prestart Application Code
(PAC) e che è scritto anch'esso in un linguaggio
interpretato.
e) Il Central Installation Manager aggiorna un database
interno registrando:
    1) Codice del programma;
    2) Initialization Code;
    3) Percorso del block-ice;
    4) Chiave di decrittazione della Prestart Application Area;
    5) Nome del programma di Prestart Application Code;
    6) Nome del programma principale nella Extended Application Area
    6) Librerie utilizzate dal programma e versioni.
A questo punto l'installazione è completata e per l'utente è
sufficiente fare un doppio clic sul block-ice (o su un collegamento)
per vedere partire il programma.
IL CARICAMENTO DEL PROGRAMMA
Ora, immaginiamo di avere fatto la medesima operazione di
installazione sia per Gimp, che per IrfanView. Siccome i due
programmi sono stati installati, sicuramente adesso sarà possibile
utilizzarli.
Immaginiamo anche, per semplicità, che sia Gimp che IrfanView
fossero distribuiti con la stessa versione della libreria
ImageDec.Libr (per esempio, la 6.9.8). Allora, in Libraries.RVF
vi sarà una sola copia della libreria (ce ne sarebbero state due
solo se le librerie distribuite con i pacchetti fossero state di
due versioni diverse).
Ogni programma sotto VegetaOS può partire in modalità SAFE,
oppure OPTIMUM. Nella modalità SAFE, il programma userà
le librerie che sono state progettate per lui (anche se in Libraries.RVF
vi sono delle librerie più nuove e teoricamente migliori), mentre in
modalità OPTIMUM il gestore di linking cercherà sempre di
reindirizzare verso la libreria più nuova (purchè dichiarata
retrocompatibile con la versione che serve al programma).
E' chiaro allora che se si fa lavorare il sistema con le applicazioni
in modalità SAFE, si elimina alla radice il problema del conflitto
tra le librerie (perchè ogni applicazione gira con le librerie per
le quali è stata progettata).
Dopo avere chiarito questo, immaginiamo di volere fare partire
GIMP.
Niente di più facile: doppio clic sul block-ice di Gimp ed inizia
l'operazione di caricamento.
Ma cerchiamo di capire cosa succede durante la fase di
caricamento.
Un modulo del kernel, l' Application Loader (AL) accede
alla Preload Application Area (PAA) del Block-Ice, e
carica in memoria il programma di prestart (PAC). Abbiamo
detto che la PAA è crittografata, tuttavia il kernel può
accedervi (le altre applicazioni invece no).
Il programma di prestart è anch'esso scritto in un linguaggio
interpretato. Anche questo programma non può fare niente
di dannoso. Infatti esso usa un set di comandi
che gli consentono solo di fare questo:
a) accedere ad una finestra sullo schermo per visualizzare
del testo;
b) accedere ai file della PAA;
c) lanciare il comando InsertInitializationCode all'AL;
d) chiudere il programma.
In questa fase si dice che il software opera in security-
condition: una condizione in cui il software non può
fare quasi nulla.
Il codice interpretato del programma di prestart non
può accedere al resto del file-system,
nè alla Extended Application Area, nè interagire con il
kernel oltre certi limiti, nè tantomeno lanciare codice
eseguibile, nè tantomeno accedere al gestore di
linking.
A cosa serve, allora, il programma di prestart? In genere
quello che fa è leggere il file KEY.DAT nella PAA ed eseguire
un bel
InsertInitializationCode (Key)
che viene immediatamente ricevuto dall'AL.
Ora si deve fare un ragionamento. Poichè l'initialization
code è specifico per l'applicazione, se l'applicazione non
fosse stata già installata essa "non saprebbe" che cosa inviare
al kernel.
L'initialization code è simile ad una parola d'ordine: avverte
il kernel che quell'applicazione è già stata installata e che
quindi è sicuro commutare in modalità full ed eseguire
il programma principale nella relativa Extended Application
Area dello stesso Block-Ice.
Tutto questo meccanismo serve perchè, se l'applicazione
è già stata installata, allora significa che il codice ha subito
un controllo antivirus.
Se l'antivirus integrato mantiene un'elevata efficienza, il
sistema è una fortezza quasi inespugnabile (salvo che
non si riesca ad avviare codice usando bug nel mail
reader o nel browser): ogni applicazione, prima di potersi
avviare, deve essere installata. Ma, se è già stata installata,
allora vuol dire che ha superato il controllo antivirus e
quindi è sicura.
L'invio dell'initialization code corretto al modulo Application
Loader provoca la commutazione del sistema in modalità full
functionality: AL provvede a caricare il programma principale
dall'extended application area (che è sempre nel block-ice).
Tale programma è (questo SI'), un binario, e segue lo schema
classico di caricamento (tranne che per il fatto che il
sistema può utilizzare i segment, come detto, per avere delle
immagini di routine ottimizzate in memoria).
Naturalmente l'utente non vede nulla di questa tecnologia,
che lavora in modo del tutto trasparente.
LA CONDIVISIONE DELLE DLL
Immaginiamo adesso di lanciare sia Gimp che VirtualDub.
Abbiamo detto che entrambi usano la libreria ImageDec.Libr.
I due software, alla partenza, chiederanno al gestore di
linking di fornire il Library ID Code (LIC) della libreria
ImageDec.Libr (versione x.x.xxxx).
Il gestore di linking risponde con un codice a 32 bit che
i due programmi devono memorizzare sfruttando la propria
memoria. E' importante osservare che se il gestore di
linking decide di utilizzare per entrambi i programmi la
medesima libreria (influisce sulla scelta soprattutto il fatto
che i programmi possano funzionare in modalità
OPTIMUM o SAFE), sia Gimp che IrfanView,
riceveranno la stessa LIC.
Da quel momento, sia per Gimp che per IrfanView,
ImageDec.Libr  =    LIC: 762D 82E7
Entrambi i programmi si riferiranno alla medesima libreria
utilizzando il medesimo LIC. La libreria viene caricata
in memoria (dal gestore di linking) una volta sola, ma ciò
avviene in maniera del tutto trasparente all'applicativo.
Si noti che, a questo punto, anche se si adotta una
allocazione di memoria del tipo:
000892722h        ImageDec.Libr        MainCode
982772882h                                       Segment MMX
L'applicazione non deve più preoccuparsi della condivisione
della memoria della libreria.
Infatti, se Gimp vuole chiamare la funzione DecodeBitmap
(params) della libreria ImageDec, egli sa che tale funzione
ha un codice identificativo (ID function) univoco per
la libreria (per esempio, può essere 7.876). Pertanto
si limiterà ad una richiesta al gestore di linking che sarà:
CallLibraryFunction (LIC, ID function, Addr Handle Params)
A questo punto è il gestore di linking che deve provvedere
ad eseguire la funzione.
Per farlo, prima deve verificare se la libreria richiesta è già
in memoria. Se non lo è, deve portarla in memoria e qualora
la RAM non fosse sufficiente deve riversare nel file di swap
la memoria relativa alle librerie che sono al momento meno
utilizzate.
Successivamente, il gestore di linking calcolerà l'indirizzo
corretto della procedura richiesta. Per fare questo, il gestore
di linking accede alla function address table, ricavando
l'indirizzo del codice relativo alla funzione nr. 7.876. Si noti
che, anche se la funzione fosse in un segment
(MMX o 3DNOW), l'unica cosa che cambierebbe
sarebbero gli indirizzi nella function address table.
Se invece fosse IrfanView a volere accedere alla funzione
DecodeBitmap della libreria ImageDec, esso farebbe la
medesima chiamata (medesimo codice LIC per la libreria,
e medesimo ID function), e accederebbe al medesimo codice
in memoria per la medesima libreria.
In questo modo la condivisione del codice in memoria è
automatica (e trasparente all'applicazione) ed è il gestore
di linking a calcolare gli indirizzi delle varie funzioni.
Ciò che viene invece duplicato, in ogni chiamata, è l'internal
computing space (ICS) della libreria. Infatti, Gimp ed IrfanView
potrebbero accedere quasi contemporaneamente allo stesso
frammento di codice.
Per questo, ogni volta che un'applicazione richiama una
funzione di una libreria, il memory linking crea una lista in
memoria contenente dei record che vengono sfruttati dalla
procedura richiamata per l'elaborazione. Inoltre, attraverso
i registri del processori viene passato l'indirizzo del record
riservato all'applicazione "chiamante".
In questo modo, è possibile condividere il codice senza
rischio di conflitti.
Esempio.
IrfanView chiama la funzione nr. 7637 di ImageDec.Libr.
Questa funzione, dopo una serie di calcoli che richiedono
della memoria, deve restituire un numero.
Il gestore di linking effettua una chiamata all'indirizzo
734C000h (perchè ha determinato che l'indirizzo fisico
della funzione nr. 7637 è proprio lì). Nell'eseguire la CALL,
il gestore di linking invia un parametro che è l'indirizzo
fisico dei parametri della funzione, ed un altro parametro
che è l'indirizzo dell'internal computing che viene assegnato
in quel momento (ad esempio, immaginiamo sia C873D88).
Successivamente, anche Gimp richiama la funzione nr. 7637
di ImageDec.Libr.
Il gestore di linking effettua una chiamata all'indirizzo
734C000h (perchè ha determinato che l'indirizzo fisico
della funzione nr. 7637 è proprio lì). Nell'eseguire la
CALL, però, il gestore di linking assegnerà un indirizzo
dell'internal computing che è totalmente diverso (per
esempio, D8728D99).
Risultato: anche se le due librerie utilizzano lo stesso codice,
uno esegue i calcoli in un buffer che si trova a C873D88,
mentre l'altro esegue i calcoli in un buffer che si trova
a D8728D99. Pertanto, anche se il codice fisico in
memoria è identico, gli spazi di indirizzamento delle
aree di elaborazione dati sono distinte ed il codice può
essere condiviso (per quanto il codice, per ogni processo,
venga mappato al medesimo indirizzo fisico).
Saluti
Vegeta

 E invece ti sbagli.
Dopo aver sopportato inoculazione, Central Installation Manager (CIM),
block-ice, PAA, EAA, al j-esimo "ma vediamo cosa fa" mi sono fermato.
Hai descritto una procedura incredibilmente complessa, troppo complessa,
temo anche complessa a sproposito, ma al momento non ho la forza di
risponderti punto per punto, tanto so che poi rimarresti della tua idea.
Per cui, se ti va, se ne sei in grado, fai pure quello che ti pare. Magari
fra qualche mese ti presenti con un pezzo di codice che fa anche il caffè.
Comunque mi è sembrato di capire che VegetaOS dovrebbe supportare anche
le librerie dinamiche. Se lo fa, allora non vedo la necessità di
includere diverse section negli eseguibili. 
Ma, ripeto, sei libero di fare come vuoi, questa è solo la mia opinione.



Se ti secchi o non hai tempo, puoi comunque leggere
la parte relativa alla condivisione delle DLL (che è
l'ultima parte del messaggio e che spiega in dettaglio
come fai a dire al programma x che c'è una libreria
condivisa e quindi la memoria può essere risparmiata).
Il punto, al di là del meccanismo che ho illustrato
(che in realtà è concettualmente semplicissimo: c'è
un meccanismo di protezione percui tutto quello che
avvii deve essere già preventivamente installato e
scansionato; cosa ben diversa da Windows o Linux,
dove puoi lanciare un bel BUDOKAN.EXE e poi
dentro c'è un bel virus)....
Il punto, dicevo, è che non è l'applicativo che deve
preoccuparsi di condividere il codice. L'applicativo
si deve limitare a richiedere al gestore di linking dei
servizi, che sono caratterizzati da due codici numerici
(uno di libreria, rilasciato dall'OS, e l'altro tipico della
funzione).
Dev'essere poi il gestore di linking a gestire il passaggio
dei parametri, la condivisione del codice, il calcolo degli
indirizzi delle procedure, lo swap su disco delle librerie
in quel momento meno utilizzate e così via....
Saluti
Vegeta
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (
http://www.grisoft.com
).
Version: 6.0.556 / Virus Database: 348 - Release Date: 26/12/03

anche se con gli hard disk attuali non è insopportabile).
Immagino i 350 Mb di OpenOffice 9.0 per VOS...