• Non ci sono risultati.

Test trasparenza e di codice rientrante per trap ed interruzioni

Come è stato dimostrato, trap ed interruzioni permettono di accedere al codice kernel eseguendo esattamente le stesse preliminari operazioni hardware e ritor-nando al programma utente entrambe mediante l'istruzione IRET. La rientranza e la trasparenza dell'una implica la rientranza e la trasparenza dell'altra.

Il test di trasparenza si compie andando ad vericare l'uguaglianza tra lo stato della CPU prima del passaggio al kernel e dopo il ritorno al programma utente. L'istruzione precedente a quella di generazione dell'interruzione può essere indivi-duata solamente se il conteggio è di tipo deterministico, tuttavia, l'estrapolazione dello stato precedente all'esecuzione del salto alla routine di interrupt, può essere facilmente determinato ricostruendolo a partire dallo stato della CPU, a patto che il programma utente interrotto sia eettivamente stato il programma utente, e non il codice kernel stesso (ad esempio mentre veniva eseguita una istruzione di trap). Dunque, posizionando un breakpoint proprio sull'istruzione di Branch alla routine di gestione delle interrupt si garantisce l'interruzione del programma nel momento in cui viene generata una interruzione da parte del timer.

Si prenda in considerazione ad esempio un programma che stampa a video ciclicamente i numeri da 1 a 9. Il codice assembly al quale corrisponde è il seguente:

numeri . axx −− programma in l i n g u a g g i o assembly START: LDWI R0 0030 ; c o d i c e ASCII d e l c a r a t t e r e 0 LOOP: INC R0

5.2. TEST TRASPARENZA E DI CODICE RIENTRANTE PER TRAP ED INTERRUZIONI93

; c o d i c e ASCII d e l c a r a t t e r e 9 SUB R0 R2

JMPZ START INT 1

; chiamata a l l a trap di stampa JMP LOOP

$ assembler . exe numeri −− comando di compi l azio ne d e l programma numeri . exx −− r i s u l t a t o d e l programma compilato

0000 00 | START: LDWI R0 0030 10 | 30 | 00 | 00 | LOOP: INC R0 48 | 20 | LDWI R2 003A 10 | 3A | 00 | 02 | SUB R0 R2 41 | F2 | JMPZ START C4 | 01 | INT 1 CC | F2 | JMP LOOP C3 |

$ l o a d e r . exe simos numeri mem2 −− mappatura d e l l a memoria

Dopo aver creato la mappatura della memoria utilizzando il programma loa-der.exe, si avvia SimCPU richiamando la nuova mappatura della memoria, si posiziona un breakpoint nell'area di memoria del segmento del sistema operativo nel quale inizia la routine di gestione delle interruzioni e si procede con un run forever.

$ simcpu . exe mem2 SIMCPU 8 . 1 0 s t a r t i n g . . .

I /O SIMULATION s t a r t i n g . . .

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > s b 88 e

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > r f

12345678912345678912345678912345678912345678912345678912345678912345678912345678 912345678912345678912345678912345678912345678912345678912345

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > d c

CPU s t a t u s : PC = 0088 IR = C000

CPU s t a t u s : z e r = 1 neg = 0 car = 0 ovf = 0 CPU s t a t u s : i n t = 0 pag = 1 ker = 1 TLB = 1

CPU s t a t u s : R00 = 0035 R01 = 0000 R02 = 0005 R03 = 0000 CPU s t a t u s : R04 = 0000 R05 = 0000 R06 = 0000 R07 = 0000 CPU s t a t u s : R08 = 0000 R09 = 0000 R10 = 0001 R11 = 0000 CPU s t a t u s : R12 = FF00 R13 = 0000 RA = 01D6 SP = AF0E

CPU s t a t u s : s p e c i a l r e g i s t e r s

CPU s t a t u s : UT = C400 KT = C000 FR = 0071 SFR = 0071 CPU s t a t u s : SRA = 0010 SSP = FF00 LTI = CC01

CPU s t a t u s : TLB( p o s i t i o n 01) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 02) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 03) = 0100000000FC CPU s t a t u s : TLB( p o s i t i o n 04) = 000000000000

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > s s d

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > n

ENTERING COMMAND MODE: c u r r e n t program counter = 0010 > d c

CPU s t a t u s : PC = 0010 IR = CD00

CPU s t a t u s : z e r = 0 neg = 0 car = 0 ovf = 0 CPU s t a t u s : i n t = 0 pag = 1 ker = 0 TLB = 1

CPU s t a t u s : R00 = 0035 R01 = 0000 R02 = 0005 R03 = 0000 CPU s t a t u s : R04 = 0000 R05 = 0000 R06 = 0000 R07 = 0000 CPU s t a t u s : R08 = 0000 R09 = 0000 R10 = 0000 R11 = 0000 CPU s t a t u s : R12 = 0000 R13 = 0000 RA = 0000 SP = FF00 CPU s t a t u s : s p e c i a l r e g i s t e r s CPU s t a t u s : UT = C400 KT = C000 FR = 0060 SFR = 0060 CPU s t a t u s : SRA = 0000 SSP = FF00 LTI = CC01

CPU s t a t u s : TLB( p o s i t i o n 01) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 02) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 03) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 04) = 000000000000

ENTERING COMMAND MODE: c u r r e n t program counter = 0010 > r f

6789123456789123456789123456789123456789123456789123456789123456789123456

Si nota immediatamente che le due mappature della CPU prima e dopo l'in-terruzione non sono coincidenti, tuttavia, il funzionamento è corretto. Infatti il programma numeri, per realizzare la stampa a video, chiama la trap INT 1. Ogni trap prevede l'esecuzione di un certo numero di istruzioni in codice kernel e se il programma utente nel quale la trap viene chiamata non conta un gran nume-ro di istruzioni prettamente di tipo utente, la pnume-robabilità che una interruzione del timer venga servita quando è eettivamente in esecuzione codice utente è molto bassa. Viceversa, nella maggior parte dei casi l'istruzione alla quale l'esecuzione si bloccherà per servire la routine di interruzione, sarà una di quelle caratteri-stiche di INT 1. In realtà questo esempio appena fornito è già esplicativo del corretto funzionamento della rientranza del codice kernel in quanto la routine di interruzione è stata chiamata durante l'esecuzione della routine di trap. A titolo di conferma basta osservare la prima mappatura della CPU. Il ag di zero è solle-vato in quanto l'esecuzione della routine di trap prevede, per il riconoscimento del tipo di interruzione chiamata, una serie di operazioni di sottrazione (SUB) che sollevano il ag di zero nel momento in cui forniscono un risultato nullo e veri-cano dunque il confronto. Inoltre, il registro SFR vale 71h ovvero 01110001b che indica che il ag di kernel del programma chiamante (posizione 5) era sollevato, ovvero si stava eseguendo codice kernel.

ri-5.2. TEST TRASPARENZA E DI CODICE RIENTRANTE PER TRAP ED INTERRUZIONI95

chiama una INT) la verica diretta della coincidenza tra una mappatura e l'altra di memoria, non può essere fatta in maniera deterministica. Tuttavia, si consideri ora la seconda mappatura della memoria. Quest'ultima è stata realizzata dopo aver imposto il bloccaggio del programma alla prima istruzione utente che sareb-be stata incontrata (comando s s d e comando n). Si noti i valori corretti del ag di kernel (nullo), dei registri R0 e R2, usati all'interno del programma. Lo screenshot della CPU, infatti è stato eettuato prima dell'esecuzione della succes-siva istruzione a quella di INT 1, ovvero la JMP LOOP. Inoltre, l'ultimo carattere ad essere stato stampato è il carattere 5, che corrisponde ad un codice ASCII di 35h. Di fatti, R0 contiene il codice ASCII del dato appena stampato, mentre R2, contiene il risultato della sottrazione tra il valore caricato precedentemente in R2 (3Ah) e il valore di R0 (35h) che come risultato fornisce esattamente 05h, il quale inoltre impone un ag di zero nullo. Si noti inne come il puntatore dello stack del programma utente non sia eettivamente stato utilizzato, di fatti il suo codice assembly non utilizza aatto lo stack.

Il programma, inne, a seguito di un comando di run forever, riprende l'esecuzione in maniera corretta a partire dalla stampa del successivo numero a quello stampato prima dell'interruzione.

Con le stesse modalità precedenti, ora verrà realizzato e caricato in memoria principale un programma utente simile al precedente e che non realizzi però nes-suna stampa a video. Il codice di cui è composto, è dunque solamente codice di tipo utente e qualsiasi interruzione del timer comporterà sia context switching che la possibilità di confrontare le mappature di memoria prima e dopo l'interruzione.

Il programma utilizzato è il seguente:

START: LDWI R0 0030 LOOP: INC R0 LDWI R2 003A SUB R0 R2 JMPZ START JMP LOOP

E i risultati ottenuti sono:

SIMCPU 8 . 1 0 s t a r t i n g . . . I /O SIMULATION s t a r t i n g . . .

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > s b 88 e

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > r f

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > d c

CPU s t a t u s : z e r = 0 neg = 0 car = 0 ovf = 0 CPU s t a t u s : i n t = 0 pag = 1 ker = 1 TLB = 1

CPU s t a t u s : R00 = 0034 R01 = 0000 R02 = 0006 R03 = 0000 CPU s t a t u s : R04 = 0000 R05 = 0000 R06 = 0000 R07 = 0000 CPU s t a t u s : R08 = 0000 R09 = 0000 R10 = 0000 R11 = 0000 CPU s t a t u s : R12 = 0000 R13 = 0000 RA = 0004 SP = AF00 CPU s t a t u s : s p e c i a l r e g i s t e r s CPU s t a t u s : UT = C400 KT = C000 FR = 0070 SFR = 0060 CPU s t a t u s : SRA = 0000 SSP = FF00 LTI = 0000

CPU s t a t u s : TLB( p o s i t i o n 01) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 02) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 03) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 04) = 0100000000FC

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > s s d

ENTERING COMMAND MODE: c u r r e n t program counter = 0088 > n

ENTERING COMMAND MODE: c u r r e n t program counter = 0004 > d c

CPU s t a t u s : PC = 0004 IR = CD00

CPU s t a t u s : z e r = 0 neg = 0 car = 0 ovf = 0 CPU s t a t u s : i n t = 0 pag = 1 ker = 0 TLB = 1

CPU s t a t u s : R00 = 0034 R01 = 0000 R02 = 0006 R03 = 0000 CPU s t a t u s : R04 = 0000 R05 = 0000 R06 = 0000 R07 = 0000 CPU s t a t u s : R08 = 0000 R09 = 0000 R10 = 0000 R11 = 0000 CPU s t a t u s : R12 = 0000 R13 = 0000 RA = 0000 SP = FF00 CPU s t a t u s : s p e c i a l r e g i s t e r s CPU s t a t u s : UT = C400 KT = C000 FR = 0060 SFR = 0060 CPU s t a t u s : SRA = 0000 SSP = FF00 LTI = 0000

CPU s t a t u s : TLB( p o s i t i o n 01) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 02) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 03) = 000000000000 CPU s t a t u s : TLB( p o s i t i o n 04) = 000000000000

ENTERING COMMAND MODE: c u r r e n t program counter = 0004 >

Si noti la perfetta coincidenza della mappatura della CPU con le uniche dif-ferenze dovute al fatto che, essendo il primo screenshot realizzato esattamente dopo l'esecuzione dell'interrupt test, il ag di kernel è ad uno, il registro origi-nale di ritorno RA si trova in SRA come anche FR e SP nei corrispettivi SFR e SSP, dunque il secondo display della CPU riporta i dati corretti. In questo caso, inoltre, internamente, è stato chiamato anche il context switching in quanto il codice interrotto è sempre codice utente, e questo attribuisce molto più prestigio alla correttezza della simulazione, che oltre a dimostrare trasparenza del codice, implica il corretto funzionamento del sistema di context switching. Lo stato del programma utente è infatti stato salvato nella sua PCB e lo scheduler ha richia-mato lo stesso programma (in quanto unico presente in memoria e non ancora terminato) e ha ricaricato nella CPU la PCB del programma appena interrotto.

5.3 Test dei codici d'errore

In questa sessione si valuterà il funzionamento dell'esecuzione corretta di princi-pali errori che si possono vericare, nonché la loro corretta gestione. La corretta

5.3. TEST DEI CODICI D'ERRORE 97

gestione di un errore comporta la terminazione del programma che la ha generata dopo la stampa a video di una particolare stringa che fornisce all'utente infor-mazioni sull'errore causato. Per dimostrare ciò verranno caricati in memoria due programmi, di cui il primo coincide con quello utilizzato nel test precedente per la stampa dei numeri e di cui il secondo simula un errore chiamando una trap normale (INT) con un particolare codice identicativo dell'errore. Se tutto fun-ziona correttamente la simulazione dovrebbe eseguire prima la stampa a video dei numeri da 1 a 9 no al context switching, poi eettuare la stampa dell'errore e poi riprendere immediatamente con l'esecuzione del primo programma che procederà indenitamente.

Tuttavia, per questo genere di test verrà utilizzato un programma di stampa a video leggermente modicato. La necessità di visualizzare in breve tempo un context switching, equivale ad imporre che la probabilità di esecuzione di codi-ce utente è maggiore della probabilità di eseguire codicodi-ce kernel. Ciò inducodi-ce a modicare il programma di stampa a video nella seguente maniera:

NIST : word 1000 START: LDWI R0 0030 LOOP: INC R0 LDWI R2 003A SUB R0 R2 JMPZ START INT 1 LDWA R1 NIST LOOP2: DEC R1 JMPNZ LOOP2 JMP LOOP

Dove in seguito alla stampa mediante la trap viene eseguito un ciclo di decre-mento della variabile NIST. Ciò garantisce una maggiore probabilità di eettuare il context switching. Allo stesso modo si poteva procedere abbassando la TIME SLICE e ricompilando SimCPU, ma in questo caso si è deciso di optare per questa soluzione.

Il programma di generazione errori è il seguente.

START: INT 0FE

E il risultato della simulazione è:

SIMCPU 8 . 1 0 s t a r t i n g . . . I /O SIMULATION s t a r t i n g . . .

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > r f

91234567891234567891234567891234567891234567891234567891234567891234567891234567 89123456789123456789123456789123456789123456789123456789123456789123456789123456 789123456789123456789123456789123456789123456789123456789123456789123456FATAL ER ROR: INSTRUCTION USAGE VIOLATION

78912345678912345678912345678912345678912345678912345678912345678912345678912345 67891234567891234567891234567891234567891234567891234567891234567891234567891234 56789123456789123456789123456789123456789123456789123456789123456789123456789123 45678912345678912345678912345678912345678912345678912345678912345678912345678912 34567891234567891234567891234567891234567891234567891234567891234567891234567891 ENTERING COMMAND MODE: c u r r e n t program counter = 0018

>

La corretta gestione dell'errore è evidente. L'unico difetto, la cui risoluzione si lascia a sviluppi futuri del sistema, è che non si è in grado ancora di capire quale eettivamente sia il programma che ha generato l'errore. L'implementazio-ne di questo geL'implementazio-nere di sviluppo, però, è estremamente semplice in quanto basta formattare gli output facendo stampare al sistema operativo, prima di richiamare l'esecuzione al programma utente vero e proprio, il numero del programma eet-tivamente in esecuzione nella CPU. In realtà, in un sistema multitasking a time sharing, questa implementazione non può venire eettuata in quanto la necessità dell'illusione del parallelismo nell'esecuzione dei programmi in memoria, compor-ta time slices estremamente piccole. Si è scelto di demandare questo problema a quando sarà sviluppata una shell minimale di interazione utente CPU.

Tralasciando il caso della gestione dell'errore di Writing Page Fault, per il quale si rimanda alla consultazione dell'altra tesi di riferimento, si valuterà il fun-zionamento dell'errore non codicato di TRAP NOT FOUND che verrà sollecitato semplicemente chiamando una trap con un codice dierente da tutti quelli eet-tivamente utilizzati, ad esempio INT 3. Il nuovo programma per la generazione dell'errore è dunque:

START: INT 3

e la simulazione della mappatura della memoria ora riporta:

SIMCPU 8 . 1 0 s t a r t i n g . . . I /O SIMULATION s t a r t i n g . . .

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > r f

12345678912345678912345678912345678912345678912345678912345678912345678912345678 91234567891234567891234567891234567891234567891234567891234567891234567891234567 89123456789123456789123456FATAL ERROR: TRAP NOT FOUND

78912345678912345678912345678912345678912345678912345678912345678912345678912345 67891234567891234567891234567891234567891234567891234567891234567891234567891234 56789123456789123456789123456789123456789123456789123456789123456789123456789123

5.4. TEST DI SCHEDULING 99

45678912345678912345678912345678912345678912345678912345678912345678912345678912 3456789123

ENTERING COMMAND MODE: c u r r e n t program counter = 01D6 >

Che di fatti rappresenta il corretto funzionamento del sistema.

5.4 Test di scheduling

Il test di scheduling corretto viene eettuato realizzando il cambio di contesto tra tre programmi, di struttura simile a quello per la generazione della stampa dei numeri da 1 a 9, ma ai quali è demandata anche la stampa di lettere maiuscole e lettere minuscole. Gli ulteriori due programmi realizzati sono i seguenti:

−− programma per l a stampa d e l l e l e t t e r e maiuscole NIST : word 1000 START: LDWI R0 0040 LOOP: INC R0 LDWI R2 005B SUB R0 R2 JMPZ START INT 1 LDWA R1 NIST LOOP2: DEC R1 JMPNZ LOOP2 JMP LOOP

−− programma per l a stampa d e l l e l e t t e r e minuscole NIST : word 1000 START: LDWI R0 0096 LOOP: INC R0 LDWI R2 007B SUB R0 R2 JMPZ START INT 1 LDWA R1 NIST LOOP2: DEC R1 JMPNZ LOOP2 JMP LOOP

Il risultato della simulazione, una volta mappata la memoria con i rispettivi programmi, è la seguente:

SIMCPU 8 . 1 0 s t a r t i n g . . . I /O SIMULATION s t a r t i n g . . .

> r f 12345678912345678912345678912345678912345678912345678912345678912345678912345678 9123456789123ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA BCDEFGHIJKLMNOPQRSTUVWXYZABCDEabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx yzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij456789123456789123 45678912345678912345678912345678912345678912345678912345678912345678912345678912 34567891234567891234567891234567891234567891234567891234567891234567891234567891 23456789123456789123456789123456789123456789123456789123456789123456789123456789 12345678912345678912345678912345678912345678912345678912345678912345678912345678 91234567891234567891234567891234567891234567891234567891234567891234567891234567 89123456789123456789123456789123456789123456789123456789123456789123456789123456 7891FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE FGHIJKLMNOPQRSTUVWXYZABCDklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm nopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmno pqrstuvwxyzabcdefgh

ENTERING COMMAND MODE: c u r r e n t program counter = 0016 >

In quest'ultima simulazione si notano due cose. La prima è il corretto fun-zionamento del sistema di schedulazione, la seconda, invece, è l'asimmetria nella chiamata al context switching. Ciò dipende molto dalla versione di Cygwin, sia da quella del sistema operativo su cui il programma viene compilato e poi eseguito. Questa specie di malfunzionamento nella asimmetria del context switching può essere attribuita al modo nel quale il sistema operativo di background (ambiente Windows o ambiente Linux), realizza lo scheduling tra i vari thread. In particola-re, è stato riscontrato che su ambiente Linux la schedulazione dei thread avviene correttamente e la generazione dei context switching è simmetrica. In ambiente Windows, invece, pare che venga privilegiata l'esecuzione del thread principale rispetto a quelli secondari (monitor tastiera e timer) e questo, tra le altre cose, favorisce un rallentamento delle fasi di scrittura a video. In sostanza, il tempo impiegato all'interno della istruzione di stampa a video, è elevato, e la probabi-lità che una interruzione del timer avvenga in questo frangente è maggiore. Ciò comporta che il context switching non viene eseguito e la stampa l'esecuzione del-lo stesso programma prosegue. Tuttavia, questo nulla toglie alla correttezza del codice e del funzionamento del sistema, anzi, in questo modo è stata vericata la robustezza del codice nei confronti di variazioni dei parametri ambientali di schedulazione dei thread.

5.5 Test della tastiera - programma echo

Il Programma di echo a schermo è l'esempio più allegorico del funzionamento corretto del thread della tastiera, del thread del monitor nonché del nuovo sistema di buering circolare implementato in SimCPU. Il programma di echo a schermo è estremamente semplice:

5.5. TEST DELLA TASTIERA - PROGRAMMA ECHO 101 START: INT 2 INT 1 JMP START SIMCPU 8 . 1 0 s t a r t i n g . . . I /O SIMULATION s t a r t i n g . . .

ENTERING COMMAND MODE: c u r r e n t program counter = 0000 > r f

ecco un esempio d i funzionamento d e l l ' echo a schermo . ENTERING COMMAND MODE: c u r r e n t program counter = 01E4 > d i

( input b u f f e r i s empty )

ENTERING COMMAND MODE: c u r r e n t program counter = 01E4 > l i $q

ENTERING COMMAND MODE: c u r r e n t program counter = 01E4 > d i

71 ( ASCII ' q ' ) 0A ( ASCII '\n ' )

ENTERING COMMAND MODE: c u r r e n t program counter = 01E4 > r f

q

ENTERING COMMAND MODE: c u r r e n t program counter = 01E6 >

Il funzionamento del programma è il seguente, una volta mandato il comando di run forever, il programma utente, mediante la trap 2, si mette in attesa del caricamento del buer della tastiera con almeno un carattere. Quando viene premuto un tasto (che non sia il tasto ESC), INT 2 restituisce in R0 il dato let-to che viene poi stampalet-to a video chiamando INT 1. Ovviamente, consideralet-to che il buer di ingresso è inizialmente vuoto e che ad ogni pressione di un tasto corrisponde la lettura di un carattere, il buer circolare rimane sempre vuoto. Tuttavia, se viene utilizzato il metodo di caricamento del buer mediante co-mando in COMMAND MODE, il funzionamento è coerente. Infatti il buer è stato riempito oine mediante i caratteri q e \n, che sono stati stampati correttamente al successivo run forever della macchina.

Conclusioni

In virtù dei risultati ottenuti sia dalle simulazioni presentate in questa sede, sia dai riscontri valutati durante il quotidiano utilizzo del codice sviluppato, è possibile aermare che l'obiettivo di realizzare un sistema operativo semplice su piatta-forma SimCPU è stato raggiunto. Il progetto portato a termine viene tuttavia considerato come solo il punto di partenza nei confronti di sviluppi futuri dello stesso, prestandosi nel contempo a numerose ottimizzazioni e svariati ampliamen-ti atampliamen-ti a svilupparne le funzionalità, le caratterisampliamen-tiche e la robustezza. Seppur il sistema sia stato sollecitato con stimoli ad ampio spettro alne di valutarne il corretto funzionamento, non si assicura la totale assenza di condizioni di simula-zione che ne causino un malfunzionamento, soprattutto qualora quest'ultimo si trovi ad operare in ambienti diversi da quelli di usuale utilizzo. La compilazione e la gestione di elementi avanzati di programmazione, quali ad esempio i thread, variano in maniera sostanziale in funzione dell'ambiente che ospita il programma simulato e spesso il passaggio da un sistema ad un altro può comportare dior-mità nell'esecuzione stessa dello stesso programma. Tuttavia, nonostante alcuni problemi di compatibilità e di portabilità non siano ancora stati risolti, si ritie-ne di aver comunque gettato le basi per la realizzazioritie-ne futura di un sistema di elevatissimo respiro didattico ed emulativo.

Appendice A

Ambiente Cygwin

Il programma Cygwin è risultato fondamentale ai ni del progetto. La compila-zione del simulatore e la sua esecucompila-zione è sempre dipesa da questo programma e in quanto strumento d'utilizzo obbligato, è opportuno realizzare una mini guida quantomeno sugli strumenti utilizzati in questa trattazione.

Cambio directory digitare 'cd ' e trascinare la cartella contenente i le da compilare sulla nestra di Cygwin e vericare che il percorso che compare sia racchiuso da virgolette .

Lista le nella directory corrente Per visualizzare i les presenti nella directory sulla quale si è posizionati digitare 'ls'.

Auto-completamento nomi e comandi Per velocizzare la scrittura dei nomi e dei comandi viene fornita la funzione di auto-completamento degli stessi che viene realizzata premendo il tasto TAB. Di conseguenza, per evitare di scrivere ad esempio user_interface.c basta scrivere user e premere TAB, il nome verrà completato da solo a patto che la radice inserita non sia troppo generica.

History dei comandi Invece di digitare ogni volta i comandi già digitati, è possibile richiamarli premendo i tasti freccia no a scorrere tutta la history dei comandi.

Avvio dei le eseguibili Nella maggior parte delle versioni di Cygwin è ne-cessario anteporre al nome del programma da eseguire la radice ./ che sta ad indicare che il programma suddetto si trova nella cartella corrente.

Compilazione mediante gcc di assembler.exe gcc -g -DDEBUG -o assembler.exe assembler.c Compilazione mediante gcc di simcpu.exe

gcc -g -DDEBUG -o simcpu.exe executor.c user_interface.c input_output.c

Compilazione di un programma *.axx ./assembler.exe nome_programma

Generazione della mappatura della memoria *.kxx ./loader.exe simos prog1 prog2 prog3 ... progN memory Esecuzione di un le *.exx o *.kxx

./simcpu.exe nome_programma ./simpcu.exe memory

Appendice B

Codice getkey.c

Il Codice C dal quale è stato tratto spunto per la scrittura del thread della tastiera viene qui riportato ed analizzato.

#include <s t d i o . h> #include <u n i s t d . h> #include <f c n t l . h> #include <errno . h> #include <termios . h> #include <sys / i o c t l . h>

struct termios old_attr ; int set_raw_mode ( void ) { int fd = STDIN_FILENO; struct termios t ; i f ( t c g e t a t t r ( fd , &t ) < 0) { p e r r o r ( " t c g e t a t t r " ) ; return −1; } old_attr = t ;

t . c _ l f l a g &= ~ICANON; /∗ no per l i n e b u f f e r i n g ∗/ t . c _ l f l a g &= ~ECHO; /∗ no s t d i n echo ∗/

i f ( t c s e t a t t r ( fd , TCSANOW, &t ) < 0) { p e r r o r ( " t c s e t a t t r " ) ; return −1; } s e t b u f ( stdin , NULL) ; return 0 ; }

int reset_mode ( void ) {

t c s e t a t t r (STDIN_FILENO, TCSANOW, &old_attr ) ; } int getkey ( ) { char ch = 0 ; int i n _ b uf f e r = 0 ; 107

#i f 0

/∗ not needed ∗/ do { /∗ wait data ∗/

i o c t l (STDIN_FILENO, FIONREAD, &i n _ b u f f er ) ; } while ( ! i n _ b u f f e r ) ;

#e n d i f

read ( 0 , &ch , 1) ; /∗ read f i r s t b y t e ∗/ return ch ;

}

int main ( int argc , char∗ argv [ ] ) { int ch ; set_raw_mode ( ) ; for ( ; ; ) { ch = getkey ( ) ; p r i n t f ( " %x\n" , ( unsigned ) ch ) ; } reset_mode ( ) ; }

Il principio di funzionamento si basa sulla modica degli attributi della strut-tura dati che caratterizza il dispositivo di standard input, ovvero la tastiera.

set_raw_mode() La seguente funzione si occupa di inizializzare il dispositivo di standard input, creando inizialmente un le di backup degli attributi di default e memorizzandolo in una variabile struttura globale denominata old_attr. Se-guono le modiche ai ag di CANONIC INPUT (ICANON) e di ECHO (ritorno a video del carattere premuto) che, mediante l'applicazione di opportune maschere vengono disabilitati. In seguito si procede all'applicazione allo standard input dei nuovi attributi appena modicati e allo svuotamento del buer di ingresso.

reset_mode() Questa funzione si occupa del ripristino dei vecchi attributi as-sociati al dispositivo della tastiera riabilitando buering ed echo a video.

Documenti correlati