Betriebssysteme KU - Einführungstutorium
Betriebssysteme KU - Einführungstutorium
Betriebssysteme KU - Einführungstutorium
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?