17.01.2014 Aufrufe

Betriebssysteme KU - Einführungstutorium

Betriebssysteme KU - Einführungstutorium

Betriebssysteme KU - Einführungstutorium

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Booting SWEB Running SWEB Hilfe<br />

<strong>Betriebssysteme</strong> <strong>KU</strong> - <strong>Einführungstutorium</strong><br />

SWEB-Tutoren<br />

irc://irc.at.euirc.net/bs


Booting SWEB Running SWEB Hilfe<br />

Teamwork<br />

Arbeitsaufteilung?<br />

Zeiteinteilung?<br />

Codeeinteilung?<br />

Kommunikation!


Booting SWEB Running SWEB Hilfe<br />

Kommunikation<br />

Kommunikation mit dem Team<br />

Gruppentreffen<br />

Email<br />

Chat<br />

Kommunikation mit anderen<br />

Newsgroup: tu-graz.lv.bs.sweb<br />

Helpline: bs-helpline-2013@iaik.tugraz.at<br />

IRC- Channel: irc://irc.at.euirc.net/bs


Booting SWEB Running SWEB Hilfe<br />

1 Booting SWEB<br />

2 Running SWEB<br />

3 Hilfe


Booting SWEB Running SWEB Hilfe<br />

Booting<br />

Grub, boot.s, Paging, call startup (main.cpp:77)<br />

main.cpp:182 ff.<br />

char const * user_progs [ ] = {<br />

"/ user_progs / helloworld . sweb " ,<br />

0<br />

} ;<br />

Scheduler : : instance()−>addNewThread (<br />

new MountMinixAndStartUserProgramsThread (<br />

new FileSystemInfo (* root_fs_info ) , user_progs )<br />

) ;<br />

// [ . . . ]<br />

ArchInterrupts : : enableInterrupts ( ) ;<br />

Scheduler : : instance()−>yield ( ) ;


Booting SWEB Running SWEB Hilfe<br />

MountMinix<br />

ist ein Kernel Thread (läuft nur im Kernel-space)<br />

mounted die Minix Partition<br />

lädt die User-Programme und startet diese<br />

wartet bis das letzte Programm terminiert und ...<br />

... unmounted die Partition dann wieder.


Booting SWEB Running SWEB Hilfe<br />

UserProcess<br />

von Thread abgeleitet<br />

führt Code eines executables aus<br />

hat einen virtuellen Adressraum (Loader)<br />

im Userspace


Booting SWEB Running SWEB Hilfe<br />

Loader<br />

setzt Adressraum für UserProcess auf<br />

lädt den Executable Code (ELF32-Format)<br />

Constructor: lädt nur den Dateiheader<br />

der eigentliche Code wird on demand geladen<br />

Loader.cpp:351 ff.<br />

void Loader::loadOnePageSafeButSlow ( uint32 virtual address );


Booting SWEB Running SWEB Hilfe<br />

Timer-Interrupt<br />

Interrupts werden in den InterruptUtils behandelt. Beispiele:<br />

Timer / Clock Interrupt (IRQ0)<br />

Tritt immer nach Ablauf einer definierten Zeitspanne auf.<br />

InterruptUtils::irqHandler_0()<br />

. . .<br />

heart_beat_value = ( heart_beat_value + 1) % 4 ;<br />

Scheduler : : instance()−>incTicks ( ) ;<br />

uint32 ret = Scheduler : : instance()−>schedule ( ) ;<br />

switch ( ret )<br />

{<br />

case 0 :<br />

ArchInterrupts : : EndOfInterrupt ( 0 ) ;<br />

arch_switchThreadKernelToKernelPageDirChange ( ) ;<br />

case 1 :<br />

ArchInterrupts : : EndOfInterrupt ( 0 ) ;<br />

arch_switchThreadToUserPageDirChange ( ) ;<br />

. . .


Booting SWEB Running SWEB Hilfe<br />

Page Fault Handler<br />

Zugriff auf eine Speicherstelle, die nicht aufgelöst werden kann →<br />

PageFault. Muss richtig behandelt werden:<br />

Code aus binary nachladen<br />

Prozess wegen Speicherzugriffsverletzung terminieren<br />

...


Booting SWEB Running SWEB Hilfe<br />

1 Booting SWEB<br />

2 Running SWEB<br />

3 Hilfe


Booting SWEB Running SWEB Hilfe<br />

Scheduler<br />

hält Liste mit allen Threads<br />

führt schedule() immer bei irq 0 aus, nächster freier Thread<br />

kommt dran<br />

yield() → irq 65 → schedule()<br />

Methoden zum verwalten von Threads<br />

Scheduler : : addThread ( Thread * thread ) ;<br />

beinhaltet den IdleThread, löscht tote Threads


Booting SWEB Running SWEB Hilfe<br />

Prozessstart<br />

Prozessobjekt erstellen<br />

Stack und ArchThreadInfo für User- und Kernelspace wird<br />

reserviert<br />

Loader läd executable<br />

Im ELF-Header im executable steht die Einsprungadresse<br />

Instruction Pointer für den Userspace wird auf diese Adresse<br />

gesetzt<br />

switch_to_userspace_ = 1


Booting SWEB Running SWEB Hilfe<br />

Prozessausführung<br />

Wenn der Scheduler den Prozess (bzw. Thread) an die Reihe<br />

nimmt:<br />

Überprüfe switch_to_userspace_ (Beim Prozessstart immer 1)<br />

Lade entsprechende Registerwerte aus ArchThreadInfo<br />

Damit ist der EIP gleich der Einsprungadresse<br />

CPU führt den sich dort befindenden Code aus


Booting SWEB Running SWEB Hilfe<br />

Einsprungspunkt: arch/x86/userspace/start.s<br />

arch/x86/userspace/start.s:1-9<br />

BITS 32<br />

extern<br />

extern<br />

main<br />

__syscall<br />

global _start<br />

_start :<br />

; we dont touch parameters on stack<br />

call main


Booting SWEB Running SWEB Hilfe<br />

Ausführung von helloworld<br />

userspace/tests/helloworld.c<br />

# include <br />

int main ( )<br />

{<br />

puts ( " hello , world " ) ;<br />

return 0 ;<br />

}<br />

Handelsübliches Hello World Programm<br />

Brian Kernigham, 1974


Booting SWEB Running SWEB Hilfe<br />

Ausführung von helloworld<br />

userspace/libc/printf.c:510<br />

int puts ( const char * output_string )<br />

{<br />

. . .<br />

characters_written = write ( STDOUT_FILENO ,<br />

( void *) output_string ,<br />

string_length ) ;<br />

. . .<br />

}<br />

Library Funktion<br />

Sanity Check des Arguments<br />

Aufruf des Systemcalls write


Booting SWEB Running SWEB Hilfe<br />

Ausführung von helloworld<br />

userspace/libc/write.c:61<br />

size_t write ( int file_descriptor , const void * buffer ,<br />

size_t count )<br />

{<br />

return __syscall ( sc_write , file_descriptor , ( long ) buffer ,<br />

count , 0x00 , 0 x00 ) ;<br />

}<br />

Library Teil des Syscalls<br />

Ruft Low-Level Teil __syscall auf


Booting SWEB Running SWEB Hilfe<br />

Ausführung von helloworld<br />

arch/x86/userspace/start.s:7<br />

__syscall :<br />

; s e t u p s t a c k<br />

...<br />

; ok , we have to s a v e ALL r e g i s t e r s we a r e now g o i n g to<br />

; o v e r w r i t e f o r our s y s c a l l<br />

...<br />

int 0 x80 ;<br />

...<br />

ret<br />

Kopiert Argumente in Register (eax, ebx, ...)<br />

Erzeugt CPU-Interrupt 0x80 (= 128 10 )<br />

→ Wechsel in Kernelspace


Booting SWEB Running SWEB Hilfe<br />

Userspace/Kernelspace<br />

Im Source<br />

Userspace: userspace/<br />

Kernelspace: common/, arch/<br />

Scheduler, UserProcess, etc.<br />

In der Ausführung: Unterschiedliche Contexte<br />

CPU-Register (eax, ...)<br />

Stack (esp, ebp)<br />

Memory (Page Directory, cr3)<br />

Kernel und Userspace teilen sich Memorylayout<br />

Aber: unterschiedliche Zugriffsrechte<br />

ThreadInfosUserspaceThread, ThreadInfosKernelThread<br />

(in arch/common/include/ArchThreads.h)


Booting SWEB Running SWEB Hilfe<br />

Definition von Syscalls<br />

arch/x86/source/arch_interrupts.s<br />

Einsprungspunkt im Kernel<br />

Speichern des (User-) Contexts<br />

Ruft syscallHandler (Low-Level) auf<br />

arch/x86/source/InterruptUtils.cpp:673<br />

extern "C" void syscallHandler ( )<br />

{<br />

currentThread−>user_arch_thread_info_−>eax =<br />

Syscall : : syscallException ( currentThread−><br />

user_arch_thread_info_−>eax , . . . ) ;<br />

. . .<br />

}


Booting SWEB Running SWEB Hilfe<br />

Syscalls im Kernel<br />

common/source/kernel/Syscall.cpp:19<br />

uint32 Syscall : : syscallException ( uint32 syscall_number ,<br />

uint32 arg1 , . . .<br />

{<br />

. . .<br />

switch ( syscall_number )<br />

{<br />

. . .<br />

case sc_write :<br />

return_value = write ( arg1 , arg2 , arg3 ) ;<br />

break ;<br />

. . .<br />

}<br />

return return_value ;<br />

}<br />

High-Level<br />

Dispatch für alle Syscalls


Booting SWEB Running SWEB Hilfe<br />

Definition von Syscalls<br />

TODO:<br />

1 Neue Syscall Nummer in<br />

common/include/kernel/syscall-definition.h eintragen<br />

2 Syscall Library Funktion schreiben<br />

3 Syscall Handler in Syscall::syscallException hinzufügen


Booting SWEB Running SWEB Hilfe<br />

Syscall::write<br />

common/source/kernel/Syscall.cpp:58<br />

// s a n i t y c h e c k s<br />

if ( ( buffer >= 2U *1024 U *1024 U *1024 U ) | |<br />

( buffer+size > 2U *1024 U *1024 U *1024 U ) )<br />

{<br />

return −1U ;<br />

}<br />

if ( fd == fd_stdout ) // s t d o u t<br />

{<br />

debug ( SYSCALL , " Syscall :: write : %B\n" , ( char *) buffer , size ) ;<br />

kprint_buffer ( ( char *) buffer , size ) ;<br />

}<br />

return size ;


Booting SWEB Running SWEB Hilfe<br />

debug( uint32 flag, const char *fmt, ...)<br />

schreibt auf die Commandline in der qemu ausgeführt wird<br />

in common/include/console/debug.h sind die flags.<br />

const uint32 SYSCALL = 0 x00080008 | OUTPUT_ENABLED ;<br />

Für neue Bereiche, neue Flags erstellen.<br />

in common/source/console/kprintf.cpp:422 kann man<br />

die Tags sowie deren Farbe einstellen<br />

Für keine Farbausgabe NO_COLOR definieren.


Booting SWEB Running SWEB Hilfe<br />

kprint_buffer, kprintf und Co<br />

kprint_buffer, kprintf, schreibt un-/formatted auf das<br />

Sweb-Terminal<br />

kprintd_buffer, kprintfd geht un-/formatted auf die<br />

Debug-Console<br />

Für Debug Ausgaben besser debug verwenden!


Booting SWEB Running SWEB Hilfe<br />

Prozessterminierung<br />

userspace/tests/helloworld.c<br />

# include <br />

int main ( )<br />

{<br />

puts ( " hello , world " ) ;<br />

return 0 ;<br />

}<br />

Was macht return 0 oder Funktionsende? Nichts<br />

besonderes...


Booting SWEB Running SWEB Hilfe<br />

Prozessterminierung (2)<br />

arch/x86/userspace/start.s:9 ff.<br />

call main<br />

push 0 x00<br />

push 0 x00<br />

push 0 x00<br />

push 0 x00<br />

push eax ; eax i s t h e r e t u r n v a l u e from main<br />

push 0 x01 ; s y s c a l l code f o r e x i t == 1<br />

call __syscall<br />

Was passiert wenn __syscall returniert?<br />

Was macht __syscall mit 0x1 und eax?


Booting SWEB Running SWEB Hilfe<br />

Prozessterminierung (3)<br />

common/source/kernel/Syscall.cpp (Fragmente bzgl. exit)<br />

uint32 Syscall : : syscallException ( uint32 syscall_number , . . .<br />

{<br />

. . .<br />

case sc_exit :<br />

exit ( arg1 ) ;<br />

break ;<br />

. . .<br />

}<br />

void Syscall : : exit ( uint32 exit_code )<br />

{<br />

currentThread−>kill ( ) ;<br />

}


Booting SWEB Running SWEB Hilfe<br />

Prozessterminierung (4)<br />

common/source/kernel/Thread.cpp:89 ff.<br />

void Thread : : kill ( )<br />

{<br />

switch_to_userspace_ = false ;<br />

state_=ToBeDestroyed ;<br />

if ( currentThread == this )<br />

{<br />

ArchInterrupts : : enableInterrupts ( ) ;<br />

Scheduler : : instance()−>yield ( ) ;<br />

}<br />

}


Booting SWEB Running SWEB Hilfe<br />

Prozessterminierung (5)<br />

Scheduler ruft delete auf, wenn Status ToBeDestroyed<br />

UserProcess/Thread Destruktor<br />

UserProcess : : ˜ UserProcess ( ) {<br />

if ( fd_ > 0) { vfs_syscall . close ( fd_ ) ; }<br />

process_registry_−>processExit ( ) ;<br />

}<br />

Thread : : ˜ Thread ( ) {<br />

if ( loader_ ) { loader_−>cleanupUserspaceAddressSpace ( ) ; }<br />

delete loader_ ;<br />

ArchThreads : : cleanupThreadInfos (<br />

user_arch_thread_info_ ) ;<br />

ArchThreads : : cleanupThreadInfos (<br />

kernel_arch_thread_info_ ) ;<br />

if ( fs_info_ ) { delete fs_info_ ; }<br />

}


Booting SWEB Running SWEB Hilfe<br />

1 Booting SWEB<br />

2 Running SWEB<br />

3 Hilfe


Booting SWEB Running SWEB Hilfe<br />

SWEBWiki<br />

https://swebwiki.student.iaik.tugraz.at/<br />

Viele Tutorials und Infos zu SWEB<br />

Wird laufend erweitert


Booting SWEB Running SWEB Hilfe<br />

Live Programming<br />

Live Programming am 15.10. (Dienstag)<br />

Gut evaluiert, scheint also sinnvoll zu sein<br />

Wir implementieren einen Syscall<br />

Aufzeichnung


Booting SWEB Running SWEB Hilfe<br />

Prozessstart<br />

Prozessobjekt erstellen<br />

Stack und ArchThreadInfo für User- und Kernelspace wird<br />

reserviert<br />

Loader läd executable<br />

Im ELF-Header im executable steht die Einsprungadresse<br />

Instruction Pointer für den Userspace wird auf diese Adresse<br />

gesetzt<br />

switch_to_userspace_ = 1


Booting SWEB Running SWEB Hilfe<br />

Prozessausführung<br />

Wenn der Scheduler den Prozess (bzw. Thread) an die Reihe<br />

nimmt:<br />

Überprüfe switch_to_userspace_ (Beim Prozessstart immer 1)<br />

Lade entsprechende Registerwerte aus ArchThreadInfo<br />

Damit ist der EIP gleich der Einsprungadresse<br />

CPU führt den sich dort befindenden Code aus


Booting SWEB Running SWEB Hilfe<br />

Einsprungspunkt: start.s<br />

BITS 32<br />

extern<br />

extern<br />

main<br />

__syscall<br />

global _start<br />

_start :<br />

; we dont touch parameters on stack<br />

call main


Booting SWEB Running SWEB Hilfe<br />

C-Programm: helloworld.c<br />

helloworld.c<br />

# include <br />

int main ( )<br />

{<br />

puts ( " hello , world " ) ;<br />

return 0 ;<br />

}<br />

Wie funktioniert puts?


Booting SWEB Running SWEB Hilfe<br />

Fragen?

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!