Samenvatting Besturingssystemen Vloeberghs Sam 2 Toegepaste Informatica 4 2007-2008 BESCHRIJVING EN BESTURING VAN PROCESSEN...................................................................................4 WAT IS EEN PROCES?.................................................................................................................................................4 Processen en besturingsblokken......................................................................................................................4 PROCESTOESTANDEN..................................................................................................................................................4 Creëren en beëindigen van processen..............................................................................................................4 Procesmodel met 2 toestanden.........................................................................................................................5 Procesmodel met 5 toestanden.........................................................................................................................6 Redenen voor het opschorten van processen:..................................................................................................7 BESCHRIJVING VAN PROCESSEN....................................................................................................................................7 Beheersstructuren in het besturingssysteem....................................................................................................7 Beheersstructuren voor processen...................................................................................................................7 PROCESBESTURING.....................................................................................................................................................9 Uitvoeringsmodi...............................................................................................................................................9 Creëren van processen.....................................................................................................................................9 Wisselen van processen..................................................................................................................................10 Uitvoering van het besturingssysteem............................................................................................................11 PROCESBEHEER IN UNIX SVR4..............................................................................................................................12 Procestoestanden...........................................................................................................................................12 Beheer van processen.....................................................................................................................................12 THREADS , SMP EN MICROKERNELS.........................................................................................................14 PROCESSEN EN THREADS...........................................................................................................................................14 Multithreading................................................................................................................................................14 Functionaliteiten van threads........................................................................................................................15 Voorbeeld : Adobe Pagemaker......................................................................................................................16 Threads op gebruikersniveau en op kernelniveau.........................................................................................16 Andere indelingen..........................................................................................................................................17 SYMMETRISCHE MULTIPROCESSING..............................................................................................................................17 Architectuur van SMP....................................................................................................................................18 Ontwerpen van besturingssystemen voor SMP..............................................................................................19 MICROKERNELS.......................................................................................................................................................19 Architectuur van een microkernel..................................................................................................................19 Voordelen van een microkernel.....................................................................................................................20 Prestaties van een microkernel......................................................................................................................20 Ontwerp van een microkernel........................................................................................................................21 BEHEER VAN THREADS EN SMP IN SOLARIS...............................................................................................................22 Architectuur met multithreading....................................................................................................................22 Motivering......................................................................................................................................................23 Interrupts als threads.....................................................................................................................................23 BEHEER VAN PROCESSEN EN THREADS IN LINUX...........................................................................................................23 Taken in Linux................................................................................................................................................23 Threads in Linux............................................................................................................................................24 GELIJKTIJDIGHEID : WEDERZIJDSE UITSLUITING EN SYNCHRONISATIE..................................25 PRINCIPES VAN GELIJKTIJDIGHEID...............................................................................................................................25 Een eenvoudig voorbeeld...............................................................................................................................26 Aandachtspunten voor het besturingssysteem................................................................................................27 Interactie van processen................................................................................................................................27 Vereisten voor wederzijdse uitsluiting...........................................................................................................28 WEDERZIJDSE UITSLUITING : HARDWAREONDERSTEUNING................................................................................................28 Uitschakelen van interrupts...........................................................................................................................28 Speciale machine instructies..........................................................................................................................29 SEMAFOREN............................................................................................................................................................30 Wederzijdse uitsluiting...................................................................................................................................31 Implementatie van semaforen........................................................................................................................31 MONITOREN...........................................................................................................................................................31 Monitor met signal.........................................................................................................................................32 GELIJKTIJDIGHEID : DEADLOCKS EN UITHONGERING.....................................................................33 BEGINSELEN VAN DEADLOCK.....................................................................................................................................33 Herbruikbare hulpbronnen............................................................................................................................33 Verbruikbare hulpbronnen.............................................................................................................................33 Condities voor deadlock.................................................................................................................................34 VOORKOMEN VAN DEADLOCK....................................................................................................................................35 Wederzijdse uitsluiting...................................................................................................................................35 Vasthouden en wachten..................................................................................................................................35 Geen preëmptieve onderbreking....................................................................................................................36 Cirkelvormig wachten....................................................................................................................................36 VERMIJDEN VAN DEADLOCK......................................................................................................................................36 Weigeren van een nieuw proces.....................................................................................................................37 Weigeren om bronnen toe te wijzen...............................................................................................................37 DETECTEREN VAN DEADLOCK....................................................................................................................................38 Algoritmen voor detecteren deadlock............................................................................................................38 Herstel............................................................................................................................................................39 GEÏNTEGREERDE AANPAK VAN DEADLOCK....................................................................................................................39 PROBLEEM VAN DE DINERENDE FILOSOFEN...................................................................................................................40 MECHANISMEN VOOR GELIJKTIJDIGHEID IN UNIX........................................................................................................41 Pijpen.............................................................................................................................................................41 Berichten........................................................................................................................................................41 Gedeeld geheugen..........................................................................................................................................41 Semaforen.......................................................................................................................................................41 Signalen..........................................................................................................................................................41 GEHEUGENBEHEER.........................................................................................................................................42 VEREISTEN VOOR GEHEUGENBEHEER...........................................................................................................................42 Relocatie.........................................................................................................................................................42 Bescherming...................................................................................................................................................43 Delen..............................................................................................................................................................43 Logische indeling...........................................................................................................................................43 Fysieke indeling.............................................................................................................................................43 PARTITIONEREN VAN GEHEUGEN.................................................................................................................................44 Vaste indeling van Partities...........................................................................................................................44 Dynamische indeling van partities.................................................................................................................45 Buddysysteem.................................................................................................................................................46 Relocatie.........................................................................................................................................................47 PAGINEREN.............................................................................................................................................................48 SEGMENTEREN........................................................................................................................................................50 VIRTUEEL GEHEUGEN....................................................................................................................................51 HARDWARE EN BESTURINGSSTRUCTUREN.....................................................................................................................51 Lokaliteit en virtueel geheugen......................................................................................................................51 Pagineren.......................................................................................................................................................52 Segmenteren...................................................................................................................................................58 Gecombineerd pagineren en segmenteren.....................................................................................................60 Bescherming en delen....................................................................................................................................60 BESTURINGSSYSTEEMSOFTWARE.................................................................................................................................61 Strategie bij ophalen (fetch policy )...............................................................................................................61 Strategie bij plaatsing....................................................................................................................................61 Strategie bij vervanging.................................................................................................................................62 Beheer van de residente set............................................................................................................................63 Opschoon strategie.........................................................................................................................................66 Toezicht op de procesbelasting......................................................................................................................66 Beschrijving en besturing van processen Wat is een proces? Processen en besturingsblokken We kunnen een proces voorstellen als een entiteit die bestaat uit een aantal elementen. Twee essentiële: 1. de programma code 2. verzameling van gegevens die bij de code hoort Een proces is gekenmerkt door een aantal elementen uit het procesbesturingsblok: o Identificatienummer o Toestand o Prioriteit o Programmateller o Geheugenwijzers o Contextgegevens o IO-toestandsinformatie o Beheersinformatie Het procesbesturingsblok moet voldoende informatie bevatten om een proces dat uitgevoerd wordt te kunnen onderbreken en op een later moment gewoon terug te kunnen starten alsof het nooit onderbroken werd. Het procesbesturingsblok is het belangrijkste hulpmiddel voor een besturingssysteem bij de ondersteuning van verschillende processen, waardoor multiprocessing mogelijk wordt. PROCES = PROGRAMMACODE & BIJHORENDE GEGEVENS + procesbesturingsblok Procestoestanden We kunnen het gedrag van een individueel proces beschrijven aan de hand van de volgorde van instructies die voor dat proces worden uitgevoerd: deze volgorde wordt een spoor ( trace ) van het proces genoemd. Er kunnen meerdere processen tegelijk uitgevoerd worden. De toedeler ( dispatcher ) wijst de processor wisselend toe aan de verschillende processen. De sporen van deze verschillende processen worden dus ‘ verweven ‘ Creëren en beëindigen van processen Creëren van processen Nieuwe batchtaak Interactieve aanmelding Gecreëerd door het besturingssysteem om een dienst te verzorgen Verwerkt door een bestaand proces Besturingssysteem ontvangt een jobbesturingsopdracht. Als het besturingssysteem bereid is de nieuwe taak uit te voeren, zal het de volgende reeks opdrachten lezen . Een gebruiker van het werkstation meld zich aan bij het systeem Het besturingssysteem kan een proces aanmaken om een bepaalde dienst af te werken waar de gebruiker om vraagt: bijvoorbeeld printen Een bestaand proces kan kind processen aanmaken die bepaalde bewerkingen afzonderlijk afwerken en het moederproces ondersteunen Beëindigen van processen Normale voltooiing Tijdslimiet overschreden Onvoldoende geheugen beschikbaar Overtreding geheugengrens Beschermingsfout Rekenkundige fout Tijd verstreken I/O-fout Ongeldige instructie Geprivilegieerde instructie Onjuist gebruik van gegevens Ingreep van de gebruiker of het besturingssysteem Beëindiging van het ouderproces Verzoek van het ouderproces Proces roept een dienst aan om te melden dat uitvoering voltooid Proces wordt afgesloten omdat het zijn uitvoeringstijd heeft overschreden … Proces probeert toegang te krijgen tot geheugenlocaties die niet voor hem bestemd zijn Het proces probeert iets te doen waar het geen rechten voor heeft, bijvoorbeeld schrijven naar een alleen-lezen bestand. Delen door nul,… Het proces heeft langer gewacht op een gebeurtenis als aangegeven Er is een fout opgetreden bij de invoer of uitvoer van gegevens naar/van het proces Proces probeert instructie uit te voeren die niet bestaat Proces probeert gereserveerde instructie uit te voeren. De gegevens zijn mogelijk niet van het juiste type of zijn nog niet geinitialiseerd. De gebruiker of besturingssysteem roept een instructie aan om het proces te beëindigen Als het ouderproces beëindigt wordt , worden meestal ook de kindprocessen beindigd Het ouderproces kan verzoeken aan een kindproces om er mee te stoppen. Procesmodel met 2 toestanden Procesmodel met 5 toestanden Actief ( running ) Gereed ( ready) Geblokkeerd ( blocked ) Nieuw ( new ) Einde ( exit ) Het proces dat op deze moment wordt uitgevoerd. In dit hoofdstuk gaan we uit van een single core processor => max 1 proces in deze toestand. Een proces dat direct kan worden uitgevoerd als het daar de gelegenheid voor krijgt. Een proces dat niet kan worden uitgevoerd totdat er zich een bepaalde gebeurtenis heeft afgespeeld. Een proces dat onlangs is aangemaakt maar zich nog niet in de ready state bevindt. Het is dus nog niet in het werkgeheugen geladen maar bevat al wel een procesbesturingsblok. Een proces dat door het besturingssysteem wordt ontslagen uit de groep uitvoerbare processen. Opgeschorte processen ( proces dat zich NIET in het hoofdgeheugen bevindt ) Soms is er het probleem dat de processor sneller is dan I/O dus alle processen kunnen wachten op I/O. De oplossing hiervoor is het ‘swappen’ : dit is processen geheel of gedeeltelijk naar de schijf verplaatsen om hoofdgeheugen vrij te maken. Dit zorgt voor 2 nieuwe toestanden: Geblokkeerd – opgeschort Gereed - opgeschort Het proces bevindt zich in het secundaire geheugen en wacht op een gebeurtenis Het proces bevindt zich in het secundaire geheugen maar is beschikbaar voor uitvoering zodra het in het hoofdgeheugen is geladen. Redenen voor het opschorten van processen: Swapping Andere reden van het BS Verzoek van interactieve gebruiker Timing Verzoek van het ouderproces Het besturingssysteem moet voldoende hoofdgeheugen vrijmaken voor het binnenhalen van een proces dat gereed is om te worden uitgevoerd. Het besturingssysteem kan een achtergrond of hulpproces opschorten of een proces dat ervan wordt verdacht een probleem te veroorzaken Een gebruiker kan de uitvoering van een programma opschorten om fouten te zoeken of om een bron te gebruiken Een proces kan periodiek worden uitgevoerd ( bijvoorbeeld een proces voor administratie of systeembewaking ) en kan worden opgeschort terwijl wordt gewacht op de volgende tijdsinterval Een ouderproces kan de uitvoering van een kindproces opschorten om het te onderzoeken of te wijzigen. Beschrijving van processen Het besturingssysteem bestuurt gebeurtenissen binnen het computersysteem en verzorgt het inroosteren ( scheduling ) en de toedeling ( dispatching ) van processen voor uitvoering door de processor, wijst bronnen toe en reageert op vragen van gebruikersprogramma’s. Besturingssysteem = Entiteit die het gebruik van systeembronnen door processen beheert Beheersstructuren in het besturingssysteem Het BS moet informatie bezitten over de huidige status van elk proces/bron. Het BS maakt en onderhoudt tabellen met informatie over elke entiteit die het beheert. Geheugentabellen - de toewijzing van hoofdgeheugen aan processen - de toewijzing van secundair geheugen aan processen - eventuele beschermingsattributen ( machtigingen v processen? ) - alle informatie die nodig is voor het beheren van het virtueel geheugen. I/O tabellen - informatie voor het beheren van I/O-kanalen en – apparaten. Bestandstabellen - informatie over het bestaan van bestanden, locatie, status en andere attributen. Procestabellen - informatie voor het beheren van processen. ( volgende puntje ) - 1 entry per proces = bevat identificatie nummer vh proces. Beheersstructuren voor processen Proceslocatie De locatie van een procesbeeld is afhankelijk van het geheugenbeheersysteem dat wordt gebruikt. In het eenvoudigste geval wordt het procesbeeld bijgehouden als een aaneengesloten blok geheugen. Dit blok is opgeslagen in het secundaire geheugen, doorgaans op schijf. Het besturingssysteem moet dus de locatie van elk proces op schijf kennen en moet voor elk proces dat zich in het hoofdgeheugen bevindt, bovendien de locatie vh proces in het hoofdgeheugen kennen. Procesbeeld: Gebruikersgegevens Gebruikersprogramma Systeemstack Procesbesturingsblok Het deel van de gebruikersruimte dat kan worden gewijzigd. Dit kan bestaan uit programmagegevens, een stackgebied voor de gebruiker en programma’s die kunnen worden gewijzigd. Het uit te voeren programma Met elk proces zijn 1 of meer LIFO systeemstacks verbonden. Een stack wordt gebruikt voor het opslaan van parameters en aanroepadressen voor procedure- en systeemaanroepen. Gegevens die het besturingssysteem nodig heeft voor het beheren van het proces. Procesattributen We kunnen de informatie in het procesbesturingsblok groeperen tot drie algemene categorieën: Procesidentificatie - unieke numerieke identificatiecode - gebruikersidentificatiecode - ouderidentificatie Processortoestandsinformatie - Registers die zichtbaar zijn voor de gebruiker - Stuur- en statusregisters Programmateller Conditiecodes Statusinformatie - Stackwijzers Program Status Word ( PSW ) : Een register of een verzameling registers die statusinformatie bevat. Bvb: * EFLAGS register in Pentium Machines Procesbesturingsinformatie - Scheduling en toestandsinformatie Procestoestand Prioriteit Scheduling informatie Gebeurenis (code) - Gegevensstructuur - Communicatie tussen processen - Procesprivileges - Geheugenbeheer - Eigendom en gebruik van bronnen. Rol van het procesbesturingsblok Elke procesbesturingsblok bevat alle informatie die het BS nodig heeft. De verzameling van procesbesturingsblokken definieert de toestand van het besturingssysteem. Procesbesturing Uitvoeringsmodi De meeste processors ondersteunen ten minste 2 uitvoeringsmodi: De gebruikersmodus : o Minder geprivilegieerd. Modus voor normale uitvoering van gebruikersprogramma’s De systeem of kernel modus: o Meer privileges. Modus voor uitvoering van kernelfuncties ( IO , proces , geheugen beheer ) Standaardfuncties van de kernel van een BS: Procesbeheer Geheugenbeheer I/O-beheer Ondersteunende functies Creëren en beëindigen van processen Inroosteren en toedelen van processen Wisselen tussen processen Synchroniseren van processen + communicatie Beheren van PSB Toewijzen van adresruimte Swapping Beheren van pagina’s en segmenten Beheren van buffers Toewijzen van IO-kanalen en apparaten aan processen Afhandelen van interrupts Administratie + toezicht De reden voor het gebruik van twee modi is dat het besturingssysteem en de belangrijkste tabellen moeten beschermd worden tegen verstoringen door gebruikersprogramma’s. De processor weet in welke modus hij moet werken en naar welke modus hij moet veranderen door bepaalde bits in het PSW dat de uitvoeringsmodus aanduidt. Deze bits worden veranderd als reactie op bepaalde gebeurtenissen. Creëren van processen Als het besturingssysteem besloten heeft tot creatie van een nieuw proces dan kan het als volgt gaan: 1. Het BS wijst een unieke procesidentificatie toe aan het nieuwe proces a. Nieuwe ingang bij de primaire procestabel 2. Het BS wijst ruimte toe aan het proces a. Alle elementen van het procesbeeld 3. Het procesbesturingsblok moet worden geïnitialiseerd. a. 4. De juiste koppelingen moeten worden ingesteld 5. Soms moeten andere gegevenstructuren worden gemaakt of uitgebreid. Wisselen van processen Wanneer moeten processen worden gewisseld Een proceswisseling kan steeds optreden wanneer het besturingssysteem de besturing heeft overgenomen van het proces dat op dit moment wordt uitgevoerd. Mechanismen voor het onderbreken van de procesuitvoering: Mechanisme Oorzaak Interrupt Extern aan de uitvoering van het huidige proces Val Verbonden aan de uitvoering van de huidige instructie Aanroep supervisor Expliciet verzoek Gebruik Reactie op een asynchrone externe gebeurtenis Afhandelen van een fout of een uitzonderlijke conditie Aanroep van een functie van het besturingssysteem Systeeminterrupts: Interrupt o Klokinterrupt Het besturingssysteem bepaald of het actieve proces de maximale toegestane uitvoeringstijd benut heeft. Zoja wordt er een ander proces geactiveerd. o I/O interrupt Is een I/O actie een gebeurtenis waarop één of meerdere processen wachten dan brengt het BS alle processen die hierop wachtten in de toestand Gereed , Gereed-opgeschort. o Geheugenfout De processor krijgt een verwijzing naar een woord adres dat zich niet in het hoofdgeheugen bevindt en zal het blok geheugen dat de verwijzing bevat naar het hoofdgeheugen moeten brengen. o Bij een val controleert het besturingssysteem of de fout al dan niet fataal is. Is deze fataal dan wordt het proces overgebracht naar de toestand Einde en treedt een proceswisseling op Val Supervisoraanroep Wisseling van modus Als er een interrupt wacht dan doet de processor het volgende: 1. De processor stelt de programmateller in op het beginadres van de routine voor de interruptafhandeling 2. De processor wisselt van gebruikersmodus naar kernelmodus, zodat de code voor de interruptverwerking geprivilegieerde instructies kan bevatten. De interruptafhandeling is meestal een kort programma dat enkele basistaken uitvoert die samenhangen met een interrupt. Het stelt bijvoorbeeld de vlag of indicator die de aanwezigheid van een interrupt signaleert, opnieuw in. In de meeste BS leidt het optreden van een interrupt echter niet noodzakelijk tot een proceswisseling. Het is mogelijk dat nadat de interruptafhandeling is uitgevoerd, de uitvoering van het actieve proces wordt voortgezet. Wisseling van procestoestand Een volledig proceswisseling bestaat uit de volgende stappen: 1. Het opslaan van de context van het proces , inclusief de programmateller en andere registers 2. Het bijwerken van het PSB van het afgebroken proces 3. Het verplaatsen van het betreffende PSB naar de juiste wachtrij ( gereed , geblokkeerd ,.. ) 4. Het selecteren van een ander uit te voeren proces. 5. Het bijwerken van het PSB van het geselecteerde proces 6. Het bijwerken van de gegevensstructuren voor het geheugenbeheer 7. Het terugbrengen van de context van dit proces naar de context zoals deze was op het moment dat het geselecteerd proces het laatst uit de toestand Actief werd gewisseld. Uitvoering van het besturingssysteem Het besturingssysteem werkt hetzelfde als gewone computersoftware: het is een programma dat wordt uitgevoerd door de processor. Het besturingssysteem geeft de besturing vaak uit handen en is voor het terugkrijgen ervan afhankelijk van de processor. Procesloze kernel De code van het besturingssysteem wordt uitgevoerd als een afzonderlijke entiteit die werkt in een geprivilegieerde modus Uitvoering binnen gebruikersprocessen Het uitvoeren van vrijwel alle software van het besturingssysteem in de context van een gebruikersproces. Hierbij wordt het besturingssysteem vooral gezien als een verzameling routines die het gebruikersproces aanroept voor het verzorgen van diverse functies die worden uitgevoerd binnen de omgeving van het gebruikersproces. Op processen gebaseerd besturingssysteem Het besturingssysteem wordt geïmplementeerd als een verzameling van systeem processen (modules). Er zijn duidelijke interfaces tussen de modules. De kernelsoftware wordt uitgevoerd in kernelmodus. Dit is een goede aanpak in multi- Procesbeheer in UNIX SVR4 Procestoestanden User running Kernel running Ready to run , in memory Asleep in memory Ready to Run , swapped Sleeping , swapped Preempted Created Zombie Uitvoering in gebruikersmodus Uitvoering kernelmodus Gereed om te worden uitgevoerd zodra de kernel het proces inroosterd Kan niet worden uitgevoerd totdat een gebeurtenis optreedt; het proces bevindt zich in hoofdgeheugen ( geblokkeerd ) Het proces is gereed om te worden uitgevoerd, maar moet eerst naar het hoofdgeheugen worden geswapped. Het proces wacht op een gebeurtenis en is naar secundaire opslag geswapt. Het proces keert terug van kernel naar gebruikersmodus, maar de kernel onderbreekt het preemptief en voert een proceswisseling uit om een ander proces in te roosteren Het process is zojuist gecreëerd en is nog niet gereed om te worden uitgevoerd Het proces bestaat niet meer maar laat een record achter voor verwerking door ouderproces Beheer van processen In Unix wordt een proces gecreëerd met de systeemaanroep fork() in de kernel: 1. het wijst een positie ( slot ) in de procestabel toe aan het nieuwe proces 2. Het wijst een unieke procesidentificatiecode toe aan het kindproces 3. het maakt een kopie van het procesbeeld van de ouder 4. Het verhoogt de tellers voor alle bestande die in het bezit zijn van het ouderproces om aan te geven dat een extra proces deze bestanden nu ook in bezit heeft. 5. Het plaats het kindprocess in een toestand Ready to Run 6. Het geeft de identificatiecode van het kindproces terug aan het ouderproces en geeft waarde 0 aan het kindproces Al deze bewerking worden uitgevoerd in kernelmodus bij het ouderproces. Als de kernel klaar is met deze functies, dan kan hij één van de volgende bewerking uitvoeren, als onderdeel van het toedelen: 1. In het ouder proces blijven. De besturing gaat terug naar de gebruikersmodus op het punt na de fork aanroep van ht ouderproces 2. De besturing overdragen aan het kindproces. De uitvoering van het kindproces begint op hetzelfde punt in de code als het ouderproces, namelijk bij de return van de fork aanroep 3. De besturing overdragen aan een ander proces. Threads , SMP en Microkernels Processen en threads Tot nu toe hebben we 2 proceskenmerken besproken: 1. Bezit van bronnen a. Virtuele adresruimte wordt toegewezen voor de opslag van het procesbeeld 2. Inroosteren en uitvoering a. Een proces is een uitvoeringspad door één of meer programma’s ( kan verweven worden ) In de meeste BS vormen deze kenmerken de kern van een proces. Ze worden onafhankelijk behandeld door het besturingssysteem. Onderscheid: Eenheid voor toedeling: thread of lichtgewicht proces Eenheid voor bronbezit: proces of taak Multithreading Het besturingssysteem ondersteunt de mogelijkheid meerdere threads te gebruiken bij de uitvoering van één proces. Voorbeelden: MS-DOS : 1 gebruikersproces,1 thread UNIX : meerdere gebruikersprocessen , 1 thread per proces WINDOWS : meerdere gebruikersprocessen , meerdere threads per proces In een multithreading omgeving wordt een proces gedefinieerd als een eenheid voor brontoewijzing en voor beveiliging. Het volgende is verbonden met processen: Virtuele adresruimte ( bevat het procesbeeld Beveiligde toegang tot processors, andere processen , bestanden en I/O-bronnen Een thread wordt gedefinieerd als een eenheid van uitvoering. Het volgende is verbonden met threads : Een uitvoeringstoestand ( Actief , Gereed , … ) Context ( opgeslagen als de thread niet uitgevoerd wordt ) Uitvoeringsstack Statische opslagcapaciteit voor lokale variabelen per thread Toegang tot het geheugen en de bronnen van het bijhorende proces(gedeeld door alle threads) De grootste voordelen van threads hangen samen met de gevolgen voor de prestaties: 1. Minder tijd nodig om een thread te creëren dan om een proces te starten 2. Minder tijd nodig om een thread te beëindigen dan om een proces te beëindigen. 3. Minder tijd nodig om over te schakelen tussen twee threads binnen het zelfde proces 4. een efficiëntere manier van communicatie tussen threads: gedeeld geheugen en bestanden. Dit zonder het activeren van de kernel Voorbeeld : De File Server Een nieuwe bestandsaanvraag = een nieuwe thread Een file server krijgt veel bestandsaanvragen : de communicatie loopt snel ( creatie en het beëindigen van de threads gaat snel ) Er is snelle en efficiënte communicatie nodig omdat de toegang tot de bestanden gecoördineerd moet worden : Het is sneller om threads te gebruiken i.p.v. processen die uitwisseling van berichten gebruiken. Nog enkele algemene voorbeelden : o Werk op de voorgrond en achtergrond - terwijl de gebruiker invoer geeft kan het programma deze invoer op de achtergrond verwerken ( opslaan , berekeningen maken , … ) o Asynchrone verwerking - Bijvoorbeeld het geregeld wegschrijven van de RAM-buffer naar schijf om eventueel gegevensverlies te voorkomen o Uitvoeringssnelheid - 1 thread kan de volgende gegevens lezen, terwijl een andere thread de vorige gegevens verwerkt. o Modulaire programma structuur - Programma’s met uiteenlopende activiteiten , verschillende bronnen/uitvoer hebben zijn met threads gemakkelijker te ontwerpen/implementeren Functionaliteiten van threads Sommige acties op het proces hebben invloed op ALLE threads van het proces: bijvoorbeeld: • Opschorten : alle threads worden opgeschort . • Beëindigen : alle threads worden beëindigt. Threadtoestanden Er zijn 4 basisbewerkingen met threads die samenhangen met een verandering van de threadtoestand : Verwekken Als een nieuw proces wordt verwerkt wordt er automatisch een nieuwe thread verwekt, welke op zijn beurt nieuwe threads kan opwekken. => Gereed voor uitvoering Blokkeren Als de thread moet wachten op gebeurtenis => Geblokkeerd Deblokkeren Optreden van gebeurtenis => Gereed voor uitvoering Beëindigen Thread voltooid : registercontext + stacks worden ongedaan gemaakt. Leidt het blokkeren van 1 thread tot het blokkeren van het volledige proces? Synchronisatie van threads Alle threads van een proces delen dezelfde adresruimte en andere bronnen , zoals open bestanden. Een wijziging van een bron door een thread heeft invloed op de omgeving van de andere threads binnen hetzelfde proces. Daarom is het noodzakelijk de activiteiten van de verschillende threads te synchroniseren om te voorkomen dat ze elkaar storen of beschadigen. Voorbeeld : Adobe Pagemaker Zie boek Threads op gebruikersniveau en op kernelniveau Threads op gebruikersniveau Al het thread -beheer wordt uitgevoerd door de toepassing De kernel is zich niet bewust van het bestaan van threads. Elk proces heeft zijn threadbibliotheek : pakket van routines voor ULT-beheer Voordelen: Threadwisseling vereist geen privileges van kernel modus Schedulingsalgoritme kan aangepast worden zonder scheduler van het BS te moeten aanpassen ULT’s kunnen uitgevoerd worden op elk BS : vereist geen aanpassing van onderliggende kernel. De Threadbibliotheek bevindt zich op toepassingsniveau. Nadelen: Als de ULT een systeemaanroep doet wordt de thread geblokkeerd + ook alle andere threads van hetzelfde proces Bij een zuivere ULT is er geen voordeel van multiprocessing. Scheduler wijst processor toe aan een proces : slecht 1 thread kan tegelijk uitgevoerd worden. Threads op kernelniveau Al het werk voor threadbeheer wordt uitgevoerd op kernelniveau Kernel houdt contet informatie bij voor de processen + alle threads binnen de processen Scheduling gebeurt op thread-basis Voordelen: Kernel kan meerdere threads van het zelfde proces schedulen op meerdere processors Geblokkeerde thread blokkeert niet het ganse proces Nadelen: Moduswisseling is vereist : overhead Er is dus weliswaar een significante snelheidswinst bij het gebruik van multithreading met KLT’s in plaats van processen met één thread, maar is de snelheidswinst nog groter bij het gebruik van ULT’s. Gecombineerde benaderingen Thread reatie wordt op gebruikersniveau gedaan Grootste deel van de scheduling en de synchronisatie gebeurt binnen de toepassing. ULT’s worden gekoppeld aan evenveel of minder KLT’s Goed ontwerp : combinatie van voordelen van beide benaderingen Andere indelingen Threads : processen 1:1 M:1 1:M M:N Beschrijving Elke uitvoeringsthread is een uniek proces met een eigen adresruimte en bronnen Een proces definieert een adresruimte en dynamisch bezit van bronnen. Binnen het proces kunnen meerdere threads worden gecreëerd en uitgevoerd Een thread kan migreren van de ene naar de andere procesomgeving. Hierdoor kan een thread eenvoudig worden verplaatst tussen verschillende systemen Combineert de eigenschappen van de voorgaande gevallen Voorbeeldsystemen De oorspronkelijke implementaties van UNIX Windows NT, Solaris, Linux, OS/2, OS/3900 MACH Ra ( Clouds ), Emerald TRIX Symmetrische multiprocessing Traditioneel werd de computer bezien als een sequentiële machine. ( instructie per instructie, proces per proces , … ) Naarmate de computertechnologie zich verder ontwikkelde en de kosten van de computerhardware daalden, hebben ontwerpers van computers gezocht nar steeds meer mogelijkheden voor parallelle verwerking, meestal om de prestaties te verbeteren en de vertrouwbaarheid te verhogen. Architectuur van SMP Flynn onderscheidde de volgende computersystemen: SIMD-stroom ( single instruction, multiple data ) Één machine-instructie bestuurd de gelijktijdige uitvoering van een aantal verwerkingselementen in een vast patroon. Met elk verwerkingselement is een gegevensgeheugen verbonden zodat elke instructie door de verschillende processors wordt uitgevoerd met een andere verzameling gegevens. MISD-stroom ( multiple instruction , single data ) Een reeks gegevens wordt verzonden naar een verzameling processors, die elk een andere instructiereeks uitvoeren. ( nog nooit geïmplementeerd ) MIMD-stroom ( multiple instruction , multiple data ) Een verzameling processors voert tegelijk verschillende instructiereeksen uit met verschillende gegevensverzamelingen. MIMD-’s kunnen verder worden onderverdeeld op basis van de wijze waarop hun processors communiceren. Hebben de processors elk een eigen geheugen, dan is elke processor een eigen computer. Geen gedeeld geheugen => onafhankelijke computers. De communicatie gebeurd via vaste paden of netwerkvoorzieningen = Cluster of MultiComputer LOOSELY COUPLED Gedeeld geheugen => Communicatie verloopt via dat geheugen. TIGHTLY COUPLED • MASTER / SLAVE Kernel op 1 bepaalde processor , de andere processors voeren enkel gebruikersprogramma’s uit. De master is verantwoordelijk voor het inroosteren van processen en threads. • SMP ( symmetrische multiprocessor ) Bij een SMP kan de kernel op eender welke processor uitgevoerd worden. Elke processor zorgt voor de scheduling van zijn eigen threads en processen. Het ontwerp van SMP’s en clusters is complex want men krijgt te maken met problemen zoals: o De fysieke organisatie o De structuur van onderliggende verbindingen o Communicatie tussen processors o Ontwerp van het BS o Technieken voor softwaretoepassingen Ontwerpen van besturingssystemen voor SMP Een besturingssysteem voor SMP beheert de processors en andere computerbronnen op zo’n manier dat de gebruiker het systeem op dezelfde wijze kan zijn als een systeem met één processor en multiprogrammering. De belangrijkste aandachtspunten voor het ontwerp zijn : Gelijktijdig samenwerkende processen of threads Bij meerdere processors die dezelfde/verschillende delen vd kernel uitvoeren , moet kerneltabellen en beheerstructuren goed worden beheerd om deadlocks en ongeldige bewerkingen te voorkomen Scheduling Conflicten moeten worden vermeden. Synchronisatie De synchronisatie is een voorziening die zorgt voor wederzijdse uitsluiting en het ordenen van gebeurtenissen. Een gebruikelijk mechanisme hiervoor zijn grendels ( locks ) Geheugenbeheer De pagineringmechanismen van verschillende processors moet worden gecoördineerd om consistentie te waarborgen wanneer verschillende processors een pagina / segment delen of besluiten een pagina te vervangen Betrouwbaarheid en fouttolerantie Microkernels Een microkernel is een kleine kern van een besturingssysteem die de basis vormt voor modulaire uitbreidingen. Dit is een vrij populair concept. Het begrip microkernel en zijn eigenschappen zijn vrij vaag: Hoe groot moet een microkernel zijn om microkernel te mogen heten? Moet de uitvoering ervan in kernel of gebruikersruimte plaatsvinden? Hoe moet het ontwerp gebeuren en wat moet er allemaal geïmplementeerd worden? Architectuur van een microkernel De eerste besturingssystemen van de jaren 50 waren monolithische besturingssystemen: Ze hadden geen structuur en waren onbeheersbaar Elke procedure kon bijna elke andere procedure aanroepen Later kwamen er gelaagde besturingssystemen : Met modulaire programmeertechnieken voor het beheersen van software ontwikkeling De meeste of alle lagen worden uitgevoerd in de kernelmodus Nadelen: o Veel interactie tussen aangrenzende lagen o Veranderingen hebben talrijke gevolgen o Beveiliging moeilijk in te bouwen De filosofie achter een microkernel is dat alleen de essentiële kernfuncties van het besturingssysteem in de kernel zijn opgenomen. Vele diensten die traditioneel tot het BS horen zijn nu geïmplementeerd als externe subsystemen : o Apparaat stuur programma’s ( Drivers ) o Bestandssystemen o Manager voor virtueel geheugen o Venstersysteem o Beveiligingsdiensten Voordelen van een microkernel o Uniforme interface bij verzoeken van een proces Processen hoeven geen onderscheid te maken tussen diensten op kernel en gebruikers niveau Alle diensten worden verleend via het uitwisselen van berichten o Uitbreidbaarheid Eenvoudig toevoegen van nieuwe diensten o Flexibiliteit Nieuwe voorzieningen kunnen gemakkelijk toegevoegd worden Bestaande voorzieningen kunnen gemakkelijk verwijderd worden o Overdraagbaarheid Alle processorspecifieke code bevindt zich in de microkernel: Veranderingen om een het BS aan te passen moet hier gebeuren en niet in andere diensten o Betrouwbaarheid Modulair ontwerp Kleine microkernel kan uitgebreid getest worden Beperkt aantal API’s o Ondersteuning van gedistribueerde systemen Berichten worden verstuurd naar diensten : Een verzendend proces moet niet weten op welke machine de dienst zich bevindt o Ondersteuning voor objectgeoriënteerde besturingssystemen ( OOOS ) Componenten zijn objecten met duidelijk gedefinieerde interfaces, en die onderling verbonden kunnen worden om software te bouwen. Prestaties van een microkernel Een mogelijk nadeel van microkernel dat vaak genoemd wordt zijn de prestaties : Het opstellen en versturen van een bericht en het accepteren en decoderen het antwoord kost meer tijd dan het uitvoeren van 1 dienstaanroep. Veel is afhankelijk van de grootte en de functionaliteit van de microkernel. Ontwerp van een microkernel Aangezien de functionaliteit en de grootte van verschillende microkernels variëren kunnen geen vaste regels worden opgesteld qua structuur en functionaliteiten. Hier lichten we de minimale verzameling van functies en diensten van de microkernel toe om de indruk te geven van het ontwerp van microkernels. Deze functies worden ingedeeld in de volgende 3 categorieën: Primitief geheugenbeheer De microkernel moet het hardware concept adresruimte ondersteunen om de implementatie van bescherming op procesniveau mogelijk te maken. Zolang de microkernel verantwoordelijk blijft voor het afbeelden van alle virtuele pagina’s op fysieke pagainframes, kan het grootste deel van het geheugenbeheer worden geïmplementeerd buiten de kernel. 1. Thread in toepassing verwijst naar een pagina niet in het hoofdgeheugen. 2. Paginafout en uitvoering valt terug op kernel 3. Kernel stuurt bericht naar pagineerder met de aangeving naar welke pagina verwezen wordt. 4. Pagineerder kan besluiten de pagina te laden 5. Is de pagina eenmaal beschikbaar , dan stuurt de pagineerder een hervattingbericht naar de toepassing Communicatie tussen processen De elementaire vorm van communicatie tussen processen of threads in een BS met een microkernel is het bericht. Een bericht bestaat uit: Een kop : info over verzendende en ontvangende proces Een romp : directe gegevens , verwijzing naar een blok gegevens en/of besturingsinformatie Vaak kunnen we zeggen dat IPC ( Inter Proces Communication ) gebaseerd is op poorten die verbonden zijn met processen. Een poort is hier in wezen een wachtrij met berichten die bestemd zijn voor een bepaald proces ( een proces kan verschillende poorten hebben ) I/O en interruptbeheer Bij een microkernel architectuur is het mogelijk hardware-interrupts af te handelen als berichten en I/ O poorten op te nemen in adresruimten. De microkernel kan interrupts herkennen maar handelt ze niet af. In plaats daarvan genereert de microkernel een bericht voor het proces op gebruikersniveau dat op dit moment is verbonden met die interrupt. Is een interrupt ingeschakeld , dan is een bepaald proces op gebruikersniveau toegewezen aan de interrupt en onderhoudt de kernel de mapping. Het omzetten van interrupts in berichten moet worden uitgevoerd door microkernel maar de microkernels is niet betrokken bij de interruptafhandeling voor specifieke apparaten. Beheer van threads en SMP in Solaris Solaris gebruikt een ongewone threadvoorziening met meerdere niveaus die ontworpen is met het oog op een hoge flexibiliteit bij het benutten van processorbronnen. Architectuur met multithreading Solaris gebruikt 4 afzonderlijke, aan threads verwante concepten: 1. Proces: normale UNIX proces , omvat de adresruimte , stack en procesbesturingsblok 2. Threads op gebruikersniveau : geïmplementeerd als een threadbibliotheek in de adresruimte van een proces 3. Lichtgewichtprocessen : Elk LWP ondersteund één of meer ULT’s en is een ‘ afbeelding ‘ naar één kernelthread. 4. Kernelthreads : basisentiteiten die kunnen worden ingeroosterd en toegedeeld worden om te worden uitgevoerd op een van de processors van het systeem Deze figuur illustreert de relatie tussen deze 4 entiteiten. Er is precies 1 kernelthread voor elk LWP. Elke LWP is verbonden aan 1 toedeelbare kernelthread. • • • • • Proces 1 bestaat uit één ULT die is gebonden aan één LWP. Proces 2 komt overéén met een zuivere ULT benadering. Alle ULT’s worden ondersteund door 1 kernelthread en daardoor kan maar een ULT tegelijk uitgevoerd worden. Proces 3 toont meerdere threads die veelvoudig zijn verboden aan een kleiner aantal LWP’s. Proces 4 heeft voor elke ULT een kernelthread Proces 5 toont een combinatie van 3 en 4 Motivering De combinatie van threads op gebruikersniveau en threads op kernelniveau biedt de programmeur van toepassingen de mogelijkheid gelijktijdigheid toe te passen op de wijze die het meest efficiënt en het meest geschikt is voor een bepaalde toepassing. Interrupts als threads De meeste besturingssystemen kennen twee basisvormen van asynchrone activiteit : processen en interrupts. Processen of threads werken met elkaar samen en beheren het gebruik van gedeelde gegevensstructuren door middel van verschillende primitieven die zorgen voor wederzijdse uitsluiting en die hun uitvoering synchroniseren. De reden voor het omzetten van interrupts in threads is het terugbrengen van de overhead. Dit zorgt voor een betere performantie. Oplossing in Solaris: 1. Solaris gebruikt verzameling Kernelthreads voor het afhandelen van interrupts. Zoals elke kernelthread heeft een Interruptthreads een eigen ID , prioriteit , context en stack 2. Voor het afhandelen van interrupts worden de gebruikelijke synchronisatie technieken voor threads gebruikt 3. Interruptthreads krijgen een hogere prioriteit dan alle andere Kernelthreads. Beheer van processen en threads in Linux Taken in Linux In Linux wordt een proces of taak weergegeven door een task_struct gegevensstructuur. Deze bevat informatie over een aantal onderwerpen: Toestand of status v/h proces ( Uitvoering , Gereed , geblokkeerd , opgeschort , zombie ,… ) Schedulinginformatie ( informatie nodig om processen in te roosteren ) Identificatiecodes : uniek ID per proces + ID voor gebruiker en groep Interprocescommunicatie Verwijzingen ( naar bijvoorbeeld ouder processen of zus-processen ) Tijden en klokken ( creatietijdstip + processortijd die al benut is door het proces ) Bestandssysteem : verwijzigen naar alle gerelateerde bestanden Adresruimte ( definieert de virtuele adresruimte die toegewezen is aan het proces ) Specifieke processorcontext : inhoud van de registers en stack Bovenstaande figuur toon de uitvoeringstoestanden van een proces/thread in Linux : o o o o o Actief ( running ) In Uitvoering of Gereed Onderbreekbaar ( Interruptable ) Het proces wacht op een gebeurtenis Ononderbreekbaar ( Uninterruptable ) Het proces wacht op een hardwareconditie en zal op niets anders reageren Gestopt ( stopped ) Het proces is gestopt en kan alleen worden hervat wanneer een ander proces hiervoor actie onderneemt Zombie Het proces in geëindigd maar beschikt nog wel over zijn taakstructuur in de procestabel Threads in Linux Oudere Linux-versies: geen multithreading Geen onderscheid tussen threads en processen: threads op gebruikersniveau komen overeen met processen op kernelniveau Threads van eenzelfde gebruikersproces: zelfde groepsidentificatiecode op kernelniveau proces creëren: attributen van huidig proces kopiëren a.h.v. clone() fork() geïmplementeerd a.h.v. clone() traditionele fork() wordt geïmplementeerd als clone() met alle clone-vlaggen uit Gelijktijdigheid : wederzijdse uitsluiting en synchronisatie De hoofdthemas van het ontwerp van besturingssystemen hangen alle samen met het beheer van processen en threads: Multirogrammering ( beheer van meerdere processen in een systeem met 1 processor ) Multiprocessing (het beheer van meerdere processen in een systeem met meerdere processors) Gedistribueerde verwerking ( beheer van meerdere processen op verschillende computersystemen ) Aan de basis van al deze zaken ligt gelijktijdigheid. Gelijktijdigheid treedt op in 3 situaties : o Meerdere toepassingen ( multiprogrammatie ) o Gestructureerde toepassing ( een applicatie kan geprogrammeerd worden als een verzameling gelijktijdige processen ) o Structuur vh BS ( kan ook beschouwd worden als een verzameling van processen of threads. ) Enkele belangrijke termen met betrekking tot gelijktijdigheid: Kritieke sectie Deadlock Livelock Wederzijdse uitsluiting Race-conditie Verhongering Een stuk programmacode binnen een proces waarvoor toegang tot gedeelde bronnen noodzakelijk is en dat mogelijk uitgevoerd wordt terwijl een ander proces in een corresponderend stuk programmacode uitgevoerd wordt. Een situatie waarin 2 of meer processen niet verder verwerkt kunnen worden omdat elk van de processen op een of meerdere andere wacht tot deze iets doen. Een situatie waarin 2 of meer processen continu hun toestand wijzigen als respons op veranderingen in het andere proces/de andere processen, zonder daarvoor enig werk van betekenis te doen. De eis dat wanneer een proces zich in kritieke toestand bevindt waarbij gedeelde bronnen gebruikt worden, geen van de andere processen zich in een kritieke sectie mag bevinden die gebruik kan maken van een of meerdere van de gedeelde bronnen. Een situatie waarin verschillende threads of processen een gedeeld gegeven lezen en schrijven en het uiteindelijke resultaat afhangt van de timing van de uitvoering van de lees- en schrijf bewerkingen. Een situatie waarin een uitvoerbaar proces eindeloos genegeerd wordt door de scheduler; het komt nooit aan de beurt hoewel het gereed is voor uitvoering. Principes van gelijktijdigheid Bij het verweven en overlappen van processen is er dezelfde problematiek : nl. de relatieve snelheid van uitvoering van processen kan niet voorspeld worden en dit brengt complicaties met zich mee zoals: o Het delen van bronnen kent tal van gevaren. ( tegelijke lees en schrijfbewerkingen kan de integriteit van gegevens in gevaar brengen o Het optimaal beheren van de toewijzing van deze bronnen is een uitdaging voor het besturingssysteem o Programmeerfouten zijn zeer lastig op te sporen omdat fouten niet reproduceerbaar zijn. Een eenvoudig voorbeeld void echo () { chin = getchar(); chout = chin; putchar =(chout); } Dit programma toont de basiselementen voor de registratie en uitvoer van een toetsaanslag op het scherm. Het delen van hoofdgeheugen door processen is nuttig voor een efficiënte en sterke interactie tussen processen. Dit delen kan echter tot problemen leiden : 1. Proces 1 start echo() en wordt onderbroken net na getchar(). Het laatst ingevoerde teken, x , is in chin opgeslagen. 2. Proces 2 wordt geactiveerd en start echo() die volledig wordt uitgevoerd en de invoer en uitvoer van 1 teken , y , op het scherm weergeeft. 3. Proces 1 wordt hervat . Op dat moment is de waarde in chin overgeschreven en daarmee verloren gegaan. chin bevat nu de waarde , y, en voert deze dan ook uit. => De gedeelde globale variabelen ( en andere gedeelde bronnen ) moeten worden beschermd en dat dit alleen mogelijk is door het bewaken van de code die toegang heeft tot de variabele. Veronderstel nu het zelfde probleem maar dan bij een systeem met meerdere processors, die dezelfde procedure echo aanroepen en dat er geen mechanisme is voor het toegangsbeheer tot de gedeelde globale variabele. Proces P1 . chin = getchar(); . chout = chin; putchar(chout); . . Proces P2 . . chin = getchar(); chout = chin; . putchar(chout); . Het resultaat is dat het voor P1 ingevoerde teken verloren gaat voordat het wordt weergegeven en zowel P1 als P2 geven het ingevoerde teken van P2 weer. Nu stellen we de regel in dat er maar 1 proces tegelijk toegang mag hebben tot het proces : 1. Proces P1 en P2 worden beide verwerkt op een afzonderlijke processor en beide roepen de procedure echo aan. 2. Terwijl P1 zich binnen de procedure echo bevindt roept P2 echo aan. Aagenzien P1 zich nog in de procedure echo bevindt, wordt de toegang van P2 tot de procedure geblokkeerd. P2 wordt daarom opgeschort. 3. Voltooit P1 de uitvoering van echo , dan verlaat het de procedure en wordt de uitvoering van P2 hervat en begint P2 met de uitvoering van echo Voorgaand voorbeeld was een race-conditie. Een race conditie onstaat wanneer verschillende processen of threads gegevensitems lezen en schrijven, waardoor het uiteindelijke resultaat afhankelijk is van de volgorde waarin de instructies in de verschillende processen worden uitgevoerd. Aandachtspunten voor het besturingssysteem 1. Het besturingssysteem moet de verschillende actieve processen kunnen volgen. ( dit gebeurd door middel van de procesbesturingsblokken ) 2. Het besturingssysteem moet bronnen toewijzen en terug afnemen. Bronnen : a. Processortijd b. Geheugen c. Bestanden d. I/O-apparaten 3. Het besturingssysteem moet de gegevens en fysieke bronnen van elk proces beschermen tegen verstoringen door andere processen 4. Resultaat van een proces en de uitvoer ervan moet onafhankelijk zijn van de snelheid van de uitvoering ervan ten opzichte van de snelheid van andere concurrerende processen. Interactie van processen Mate van bewustzijn Processen zijn zich niet bewust van elkaar Processen zijn zich indirect bewust van elkaar ( gedeeld object) Processen zijn zich direct bewust van elkaar ( communicatie – primitieven ) Relatie Invloed van proces op een ander proces o Resultaten van een proces zijn onafhankelijk van de actie van andere processen o Timing van proces kan beïnvloed zijn Samenwerking o Resultaten van een proces kunnen afhankelijk zijn van informatie van door delen andere processen. o Timing van proces kan beïnvloed zijn Concurrentie Samenwerking o Resultaten van een proces kunnen afhankelijk zijn van informatie van door andere processen. communicatie o Timing van proces kan beïnvloed Mogelijke besturings - problemen o Wederzijdse uitsluiting o Deadlock o Uithongering o Wederzijde uitsluiting o Deadlock o Uithongering o Gegevenssamenhang o Deadlock o uithongering zijn Concurrentie tussen processen om bronnen Er is behoefte aan wederzijdse uitsluiting. Er is een kritieke bron en een kritieke sectie. o Een kritieke bron is een niet deelbare bron: Bijvoorbeeld een printer. o Een kritieke sectie is een deel van programma dat de kritieke bron gebruikt ( slechts 1 programma tegelijk mag zich in zijn kritieke sectie bevinden ) Dit veroorzaakt twee andere besturingsproblemen : o Deadlock BS wijst Bron1 toe aan Proces2 en Bron2 aan Proces1. Elk proces wacht op een van de twee bronnen. Beide zullen de bron die al bezig is pas vrijgeven wanneer ook de andere bron in bezit gekomen is en vervolgens de functie waarvoor beide bronnen nodig was is uitgevoerd. o Starvation Dit gebeurd wanneer een proces constant genegeerd wordt alhoewel het gereed is om uit te voeren. Samenwerking tussen processen door delen Aangezien gegevens toegankelijk zijn vanuit bronnen ( apparaten / geheugen ) spelen nu ook de beheersproblemen wederzijdse uitsluiting, deadlocks en uithongering een rol. Het enige verschil is dat gegevenselementen toegankelijk kunnen zijn in 2 verschillende modi ( lezen / schrijven ) en dat alleen het schrijven wederzijds uitgesloten hoeft te zijn. Naast deze problemen bestaat echter een nieuwe belangrijkere vereiste: gegevenssamenhang ( data coherence ) Samenwerking tussen processen door communiceren Werken processen samen door te communiceren, dan nemen de verschillende processen gezamenlijk deel aan een gemeenschappelijke inspanning, die alle processen verenigt. De communicatie is daarbij een middel om de verschillende activiteiten te synchroniseren of te coördineren. De communicatie verloopt via de uitwisseling van berichten. Bij het uitwisselen van berichten wordt niets gedeeld door processen dus wederzijdse uitsluiting is geen controle eis voor dit soort samenwerking. De problemen deadlock en uithongering doen zich wel voor. Vereisten voor wederzijdse uitsluiting 1. Wederzijde uitsluiting moet dwingend opgelegd worden: slechts 1 proces van alle processen met kritieke secties voor dezelfde bron of hetzelfde gedeelde object wordt tegelijkertijd in de kritieke sectie toegelaten. 2. Een proces dat stopt in zijn niet kritieke sectie moet dat doen zonder andere processen te verstoren 3. Deadlocks en starvation mogen niet voorkomen 4. Een proces dat toegang wil tot een kritieke sectie moet zonder vertraging toegang krijgen, wanneer er geen enkel ander proces zich in zijn kritieke sectie bevindt 5. Geen veronderstellingen gebruikt over de relatieve snelheiden van processen/ aantal processen 6. Een proces mag zich maar een beperkte tijd in zijn kritieke sectie bevinden Wederzijdse uitsluiting: hardwareondersteuning Uitschakelen van interrupts systeem met 1 processor: concurrerende processen kunnen elkaar niet overlappen een proces wordt afgebroken door een interrupt => ervoor zorgen dat een proces niet kan onderbroken worden door interrupts uit te schakelen (achterliggende theorie: wanneer een interrupt optreedt gaat de processor in kernelmode en voert daar de gewenste code uit, dus, andere code wordt uitgevoerd tussen de kritieke sectie, in het slechtste geval verandert die code iets waarmee het proces in usermode mee bezig was waardoor alles in het water valt. Een ander probleem kan zijn dat de interrupt vereist dat een ander proces wordt toebedeeld aan de processor waardoor het eerste proces geblokkeerd wordt temidden van zijn kritieke sectie. Het kan dan even duren vooraleer dat proces weer vrijkomt (denk maar aan FIFO) waardoor de bron die het proces gebruikt lange tijd geblokkeerd blijft. while(true) { schakel interrupts uit; voer kritieke sectie uit; schakel interrupts in; rest; } => omdat de kritieke sectie niet kan worden onderbroken is mutual exclusion gegarandeerd! Nadelen: efficiëntie uitvoering daalt want processor wordt beperkt in zijn mogelijkheid om processen te verweven werkt niet in multiprocessoromgeving (!!daar heeft het geen zin om de interrupts op 1 processor even af te zetten met de reden dat de code daarom atomair kan verlopen want op de andere processoren kunnen er processen lopen die tegelijkertijd dingen gaan veranderen aan variabelen die het eerste proces in zijn kritieke sectie gebruikt. een oplossing zou dan zijn om op de gebruikte processor interrupts te disablen en op de andere processen de processen te blokkeren maar dat is zo inefficiënt dat dat geen goed idee is) Speciale machine instructies de testset en de exchange instructie Beiden zijn machineïnstructies die ervoor zorgen dat de kritieke sectie op atomair niveau wordt uitgevoerd! Parbegin betekent dat het programma deze processen parallel moet uitvoeren Instructie test and set testandset gaat controleren of een integer == 0, zo ja, dan wordt die op 1 gezet en wordt er true gereturnd => uit de while lus en de kritieke sectie wordt uitgevoerd, als er dan ondertussen een ander proces ook zijn kritieke sectie wil uitvoeren, dan wordt er false gereturnd en zit dat proces vast in de lus tot wanneer het vorige proces bolt terug op 0 zet. De processen die zo in de loop terechtkomen zijn zijn dan niet geblokkeerd maar busy waiting (processor wordt maw gebruikt maar is niet nuttig aan het doen, proces zit immers in een loop); busy waiting wil zeggen: een proces kan niets doen tot het toestemming krijgt de kritieke sectie te betreden. Welk het volgende proces wordt dat wordt uitgevoerd wanneer bolt terug 0 is, is het eerste proces dat test of bolt == 0. Dus eigenlijk is dit vrij random (afhankelijk van de schedulingsstrategie) Instructie exchange Wisselt de inhoud van een register met die van een geheugenlocatie. In het voorbeeld is het iets simpeler, daar worden een 0 en een 1 gewisseld. Enkel het proces waarvoor geldt dat keyi == 0 (en dus bolt == 0 bij het begin van de uitvoering) mag de kritieke sectie betreden, al de rest moet wachten tot het eerste proces bolt terug op 0 heeft gezet. Eigenschappen van de benadering met machine-instructies Voordelen van het werken met machine-instructies: 1. toepasbaar op alle processen op een machine met 1 processor en op alle processen op een systeem van multiprocessing die het hoofdgeheugen delen <-> als ze geen geheugen delen, dan delen ze ook geen variabelen en kan er dan ook niet met de waarde van variabelen gewerkt worden!! 2. eenvoudig => makkelijk te controleren 3. kan worden gebruikt voor het ondersteunen van meerdere kritieke secties waarbij elke kritieke sectie zijn eigen variabele kan hebben Nadelen van het werken met machine-instructies: 1. busy-waiting: proces blijft processortijd verbruiken terwijl het niets nuttig aan get doen is 2. starvation kan nog steeds: aangezien het willekeurig is welk proces een proces opvolgt dat uit zijn kritieke sectie komt en als er meerdere processen zijn die 'busy waiting' zijn, dan kan het zijn dat een proces zeer lang in de wachtrij staat 3. deadlock: P1 gaat in kritieke sectie maar wordt onderbroken door P2 dat een hogere prioriteit heeft, echter, om te voltooien heeft P2 dezelfde bron nodig als P1 maar die is geblokkeerd door P2 en P1 wacht op de voltooiing van P2... (dan maakt het niet uit of er even een ander proces wordt geactiveerd want de clue is dat deze twee processen niet verder kunnen, tenzij het OS P2 plots een lagere prioriteit geeft dan P1 waardoor P1 weer actief kan worden...) Semaforen Grondbeginsel : Twee of meer processen kunnen samenwerken dmv signalen waarbij een proces gedwongen wordt te stoppen op een opgegeven plaats totdat het een signaal ontvangt dat het mag verdergaan. Voor het verzenden van een signaal via semafoor s voert een proces de primitieve semSignal(s) uit. Voor het ontvangen van een signaal de primitieve semWait(s). Principe: semWait(s) => een proces wordt onderbroken totdat semSignal(s) door een ander proces verzonden is. Om het gewenste effect te bereiken kunnen we de semafoor beschouwen als een variabele die een gehele waarde heeft en waarvoor drie bewerkingen zijn gedefinieerd : 1. semafoor wordt geïnitialiseerd op een niet-negatieve waarde 2. semWait(s) verlaagt de waarde van s met 1, wordt de waarde negatief, dan wordt dat proces geblokkeerd 3. semSignal(s) verhoogt de waarde van s, was de waarde niet positief en nu wel, dan wordt een proces dat geblokkeerd was door semWait(s) nu gedeblokkeerd. semWait() en semSignal() zijn primitieven en worden atomair uitgevoerd ( zonder onderbreking ). Een binaire semafoor kan worden geïnitialiseerd op waarde 0 of 1 en kan ook alleen maar deze twee waarden hebben. 1. Bewerking semWaitB() controleert waarde van de semafoor. Als de waarde nul is wordt het proces dat semWaitB() uitvoert geblokkeerd. Als de waarde 1 is wordt het proces verder uitgevoerd en de waarde in 0 veranderd. 2. De bewerking semSignalB() controleeert of er processen op deze semafoor geblokkeerd zijn. Als dat het geval is , wordt een proces dat geblokkeerd is door een bewerking semWaitB vrijgegeven. Zijn er geen geblokkeerde processen , waarde => 1 Niet binaire semaforen worden vaak een tellende of algemene semafoor genoemd. Het proces dat het langst is geblokkeerd wordt als eerste vrijgelaten uit de wachtrij. Bij deze strategie is een semafoor STERK. Als de volgorde van processen uit de wachtrij niet is vastgelegd wordt het een ZWAKKE semafoor. STERKE semaforen garanderen de afwezigheid van uithongering, zwakke niet. !!!Voordeel t.o.v. machine-instructies: de processen worden hier geblokkeerd => de processor voert ze niet meer uit en verdoet er dan ook zijn tijd niet mee <-> busy waiting bij machine-instructies!!! Wederzijdse uitsluiting Op elk moment kan de waarde van de semafoor daarbij als volgt worden geïnterpreteerd: De waarde van de semafoor ( bij >= 0 ) is het aantal processen dat semWait(s) zonder onderbreking kan uitvoeren De waarde van de semafoor ( bij < 0 ) is het aantal processen dat is onderbroken in de wachtrij van de semafoor. Implementatie van semaforen Zoals eerder gezegd is het essentieel dat de bewerkingen semWait en semSignal worden geïmplementeerd als atomaire primitieven. Mogelijkheden : in hard-of firmware software: probleem: als je bvb naar het algoritme van Dekker kijkt, dan is er veel overhead omdat de processor een proces aan het uitvoeren kan zijn dat in wezen niets doet, buiten dan controleren of de vlaggen wel goed staan mutual exclusion door mechanisme in de hardware: testandset en interrupts Bij testandset wordt de de testset gebruikt bij de wait en de signal. Er kan maar 1 proces per keer een semwait(s) doen => wanneer een eerste proces dit wil uitvoeren, dan wordt s.flag op 1 gezet waardoor, als er een tweede proces is dat ook een semWait(s) wil oproepen, even moet wachten vooraleer het de semafoor kan aanpassen => in de while loop (= busy waiting). Wanneer dan het eerste proces de wait heeft uitgevoerd, dan wordt s.flag weer op 0 gezet zodat een proces dat hierop aan het wachten was, uit de loop kan en de semafoor kan aanpassen. Dit staat los van het feit of het proces al dan niet geblokkeerd gaat geraken wanneer de waarde van de semafoor < 0, het zorgt er gewoon voor dat er geen 2 processen tegelijkertijd de semafoor kunnen aanpassen Nadeel is dat er dan gedaan wordt aan busy waiting maar omdat een semwait niet zo lang duurt is dat nog redelijk. Idem voor bij het enabelen en disabelen van interrupts (alleen bij systemen met 1 processor!!!!!). Dit wordt gedaan zodat een semwait en semsignal atomaire acties kunnen zijn (ze kunnen dan niet worden onderbroken door een interrupt) het kleine nadeel is dan wel dat de processor dan even geen processen kan verweven maar omdat semWait en semSignal zo kort duren valt dit nadeel vrij goed mee. Monitoren Semaforen hebben nadelen : verantwoordelijkheid voor plaatsing van semWait en semSignal ligt volledig bij de programmeur wat dus de kans op fouten groter maakt dan bij monitors waar deze verantwoordelijkheid gedeeltelijk wordt afgeschoven op het vertaalprogramma. semWait en semSignal kunnen overal verspreid staan over een programma en het is soms moeilijk om te zien wat hun invloed juist is <-> een monitor is meer afgelijnd, het is het creëren van een atomair blok daar waar er eerst geen was Monitor is een constructie in een programmeertaal die een functionaliteit biedt die vergelijkbaar is met die van semaforen, maar die gemakkelijker te besturen is. Ook is ze geïmplementeerd als een programmabibliotheek. Dit biedt de mogelijkheid grendels op elk object te plaatsen. Monitor met signal Een monitor is een softwaremodule die bestaat uit een reeks procedures, een initialisatiereeks en een lokale gegevens. Kenmerken : 1. Lokale gegevensvariabelen zijn uitsluitend toegankelijk voor de procedures van de monitor en niet voor andere externe procedures. 2. Een proces benadert de monitor door een van de procedures ervan aan te roepen. 3. Slecht één proces tegelijk kan worden uitgevoerd in de monitor. Door slechts 1 proces tegelijk toe te laten kan de monitor worden gebruikt als een voorziening voor wederzijdse uitsluiting. Een monitor ondersteunt ook synchronisatie door gebruik te maken van conditievariabelen die zijn opgenomen binnen de monitor en die alleen binnen de monitor toegankelijk zijn. 2 functies werken hiermee : 1. cwait(c) : stelt de uitvoering van het aanroepende proces uit op conditie c. De monitor is daarna beschikbaar voor gebruik door een ander proces. 2. csignal(c) : hervat de uitvoering van een bepaald proces dat werd onderbroken na een cwait op dezelfde conditie. Zijn er meerdere van dergelijke processen, kies dan één proces; zijn er geen wachtende , doe dan niets! wanneer er bij monitors een signal wordt verstuurd maar er is helemaal geen proces dat wacht op de conditievariabele (er zit geen proces in de wachtrij van de variabele), dan gebeurt er helemaal niets <> semaforen Dus: monitor toegankelijk voor slechts 1 proces per keer, als eerste proces binnenkomt, dan wordt de conditie gewijzigd waardoor een tweede proces door cwait(c) uit te voeren terechtkomt in een wachtrij van de conditie totdat eerste proces een signal uitvoert dat de monitor vrij is => 1 proces uit de wachtrij hervat zijn uitvoering net na de cwait(x). De verantwoordelijkheid voor de correctheid van de synchronisatie ligt nog steeds bij de programmeur, maar : Voordelen tov semaforen: de synchronisatiefuncties blijven beperkt tot de monitor => overzichtelijker en makkelijker te controleren <-> semaforen: kunnen over het hele programma staan. Nadelen van monitors: een goede synchronisatie vereist dat procedures worden aangeroepen voor en na het gebruik van de gedeelde bron. Gebeurt dit niet of verkeerd, dan bestaat de kans dat een thread of een proces toch nog toegang heeft tot een gedeelde bron terwijl een ander proces daar ook mee bezig is geneste monitoren kunnen deadlocks veroorzaken: P1 zit in een procedure van een high-level monitor en gaat over naar een procedure van een lower-level monitor, daar wordt het proces in een wachtrij geplaatst. Alles goed en wel voor de lower-level monitor, die komt zo vrij voor een ander proces maar de high-level monitor is nog steeds bezet => geen ander proces kan die gebruiken => deadlock Gelijktijdigheid : Deadlocks en uithongering Deadlock en starvation zijn twee problemen ten gevolge van de oplossingen om gelijktijdige verwerking te ondersteunen Beginselen van deadlock Deadlock: een permanente blokkering van processen die met elkaar wedijveren om bronnen of die met elkaar communiceren fig 6-2 p 285!! Herbruikbare hulpbronnen Reusable resource <-> consumable resource bvb.: hoofdgeheugen, secundair geheugen, processor, databases en semaforen Een herbruikbare (hulp)bron is een bron die veilig door 1 proces tegelijkertijd kan worden gebruikt en na dit gebruik is de bron er nog steeds, ze geraakt door gebruik niet op Deadlock: wanneer twee processen een bron vasthouden en verzoeken om een andere bron zie voorbeeld p288 voorbeeld van deadlock bij geheugen: wanneer er gevraagd wordt om geheugen dat nog moet vrijgezet worden door een ander proces dat echter zelf nog om geheugen vraagt en niets kan vrijzetten omdat het wacht op geheugen Verbruikbare hulpbronnen Consumable resource: een bron die kan worden gemaakt en vernietigd; het aantal verbruikbare bronnen van een bepaald soort is meestal onbeperkt bvb.: interrupts, signalen, berichten(!!! processen die met elkaar communiceren!!) Deadlock: P1 wacht op een bericht van P2 om naar P2 te versturen terwijl P2 wacht op een bericht van P1 om naar P1 te versturen => een deadlock treedt op als het ontvangen blokkerend is brontoewijzingsschema's Een punt is een voorstelling van een bron, hierboven is er van elke bron maar 1 instantie een proces vraagt om een bron maar die nog niet toegewezen, pas wanneer er een pijl van een bron naar een proces gaat is de bron toegewezen aan dat proces. Voorbeeld van een deadlocksituatie: Wanneer er meerdere instanties van een herbruikbare bron kunnen toegewezen worden (bvb van I/O apparaten) aan een proces is de kans op een deadlock kleiner Condities voor deadlock Er zijn drie voorwaarden die er voor zorgen dat een situatie in een deadlock kan verzeild geraken: 1. wederzijdse uitsluiting: een bron mag maar aan 1 proces gelijktijdig worden toegewezen 2. vasthouden en wachten: een proces mag een bron vasthouden terwijl het wacht op de toewijzing van andere bronnen 3. geen preëmptieve onderbreking: een bron kan niet zomaar worden afgenomen van een proces dat de bron vasthoudt Deze drie voorwaarden zijn echter wenselijk!! mutual exclusion: consistentie van gegevens en gelijktijdigheid geen preëmptieve onderbreking: tenzij met een zeer goed rollback-mechanisme (stel: een proces is bezig met bewerkingen op gegevens uit een bestand, opeens wordt dat bestand afgenomen van dat proces en dat bestand gaat lezen uit dat bestand => een fout) Noodzaak aan een 4e voorwaarde voor deadlock: 4. Cirkelvormig wachten: een ketting van wachtende processen waarbij de processen wachten op het vrijkomen van een bron dat een ander proces vasthoudt De eerste drie condities kunnen leiden tot de vierde. Wanneer de vierde voorwaarde waar is, dan is er een deadlock. Er zijn drie strategiën om om te gaan met een deadlock: voorkomen, vermijden en detecteren Samenvatting: aanpak Toewijzing bronnen Verschillende vormen Voordelen Nadelen Voorkomen bronnen worden met mondjesmaat toegewezen alle bronnen tegelijk aanvragen + preëmptieve ingreep is niet nodig + werkt goed bij processen die activiteiten in één klap uitvoeren - inefficiënt - vertraagt het starten van processen - toekomstige behoefte aan bronnen moet gekend zijn preëmptieve ingreep + goed voor gebruik bij processen waarbij de toestand gemakkelijk kan worden opgeslaan en hersteld - preëmptieve onderbrekingen treden vaker op dan nodig ordenen van bronnen + implementatie dmv controles tijdens compilatie - maakt toenemende vragen om bronnen onmogelijk Vermijden middenweg tussen detecteren en voorkomen bijsturen om minstens 1 veilige weg te vinden + preëmptieve onderbreking - toekomstige is niet noodzakelijk behoeften aan bronnen moeten bekend zijn - processen kunnen lange tijd geblokkeerd zijn Detecteren aangevraagde bronnen indien mogelijk altijd vrijgeven periodiek aanroepen om te testen op deadlock + vertraagt nooit het starten van een proces + maakt online afhandeling mogelijk - verlies door preëmptieve onderbreking Voorkomen van deadlock deadlock wordt uitgesloten twee mogelijkheden: 1. indirecte methode: voorkomen van 1 van de 3 noodzakelijke voorwaarden 2. directe methode: voorkomen van het cirkelvormig wachten Wederzijdse uitsluiting kan niet onmogelijk worden gemaakt: sommige bronnen (bvb naar een bestand schrijven) vereisen nu eenmaal wederzijdse uitsluiting en dan vereist dit ook ondersteuning door OS! Vasthouden en wachten het proces vraagt in één keer alle vereiste bronnen aan en wordt geblokkeerd zolang er een of meerdere bronnen niet beschikbaar zijn inefficiënt: op die manier kan een proces lang geblokkeerd blijven terwijl het mss al gedeeltelijk kan uitgevoerd worden met slechts een deel van de bronnen reeds toegewezen bronnen aan een dergelijk geblokkeerd proces zijn ontoegankelijk voor andere processen terwijl deze bronnen niet worden gebruikt Dit vereist ook dat een proces vanaf het begin weet welke bronnen het zal nodig hebben en dat het weet waar het deze kan vinden Geen preëmptieve onderbreking er zijn verschillende manieren om tóch preëmptief te onderbreken: een proces bezet een aantal bronnen, verzoekt om een andere -> verzoek wordt geweigerd => proces moet alle bronnen vrijgeven en er een volgende keer terug om verzoeken OS onderbreekt preëmptief een proces dat om een bron vraagt dat bezet is door een ander proces en eisen dat dit zijn bronnen vrijgeeft(voorkomt enkel een deadlock wanneer beide processen een andere prioriteit hebben => preëmptief onderbreken proces met laagste prioriteit) Onderbreken heeft alleen zin bij bronnen waarvan de toestand gemakkelijk kan worden opgeslagen en hersteld, zoals bij de processor Cirkelvormig wachten Dit is de directe manier door het definiëren van een lineaire rangorde van soorten voorzieningen: aan een proces zijn bronnen toegewezen van het soort R, dan mag dit proces enkel nog maar verzoeken om bronnen met een hogere rangorde dan R volgende situatie kan dan niet meer: P1 heeft bron Ri bezet en vraagt om bron Rj P2 heeft bron Rj bezet en verzoekt om Ri Dit kan niet want als i < j dan kan j !< i dus deze deadlock is opgelost want P2 mag Ri niet aanvragen Inefficiënt want het vertraagt de processen en weigert onnodig de toegang tot bronnen (omdat dit in een bepaalde volgorde moet gebeuren, zelfs al zijn de bronnen vrij) Vermijden van deadlock voorkomen deadlock: beperkingen opleggen aan bronaanvragen om zo minstens 1 van de vier voorwaarden te omzeilen => inefficiënt gebruik van systeembronnen en inefficiënte uitvoering van processen vermijden van deadlock: de eerste drie voorwaarden zijn toegestaan maar er worden keuzes gemaakt om er voor te zorgen dat het nooit tot een deadlock komt => er is meer ruimte voor gelijktijdigheid maar, dit vereist wel dat op voorhand geweten is om welke bronnen zal gevraagd worden 2 benaderingen om deadlock te vermijden: 1. een proces waarvan de bronaanvragen tot een dead lock kunnen leiden niet starten 2. wanneer een bronaanvraag van een proces kan leiden tot een deadlock, dan wordt deze aanvraag niet verwerkt Weigeren van een nieuw proces Zeer inefficiënt: Gaat ervan uit dat alle processen tegelijkertijd hun maximale claim kunnen maken => een nieuw proces wordt alleen gestart als het systeem alle bronnen die de reeds bestaande processen kunnen opvragen aan die processen kunnen worden toegewezen en als de bronnen die het nieuw proces kan aanvragen ook kunnen worden toegewezen Probleem: het is niet omdat twee processen een bron tegelijkertijd kunnen opvragen dat dat daarom ook zo is Weigeren om bronnen toe te wijzen Dit werkt volgens het bankiersalgoritme van Dijkstra. Er worden 2 soorten toestanden onderscheiden: veilige toestand: er is op zijn minst 1 manier waarop de processen bronnen toegewezen kunnen krijgen die niet leidt tot een deadlock onveilige toestand: een mogelijke deadlocksituatie (die wordt vermeden door het systeem door de bronaanvraag niet te behandelen en het proces dat de aanvraag doet te blokkeren) zie fig 6-7 op die figuur is een voorbeeld te zien van een veilige toestand, immers, er is op zijn minst 1 manier waarop de verschillende processen kunnen uitgevoerd worden die niet leidt tot een deadlock fig 6-8 p301: onveilige situatie P1 verzoekt om 1 allocatie van bron 1 en 1 van bron 3 => er zijn geen instanties meer van bron 1 terwijl er daar minstens 1 van nodig is opdat er een proces is dat volledig kan uitgevoerd worden => het toewijzen van de bronnen aan proces 1 leidt tot een deadlock en dit wordt voorkomen door deze aanvraag te negeren en P1 te blokkeren waardoor een ander proces actief wordt (hopelijk P2) dat een aanvraag doet die NIET leidt tot een deadlock m.a.w. er is geen deadlock opgetreden, er was alleen een toestand waarin er een kon optreden. Want het kan bvb zijn dat P1 achtereenvolgens weer 1 instantie van R1 en R3 vrijgeeft voordat het deze op een later tijdstip weer nodig heeft. Dus: het op deze manier vermijden van een deadlock gaat ook voor de zekerheid (terwijl het niet altijd zeker is dat een onveilige toestand ook daadwerkelijk leidt tot een deadlock) maar het is al wel efficiënter dan de andere vermijdingsstrategie. Er wordt voorkomen dat een deadlock voorkomt, zelfs al kan het zijn dat deze er nooit zou gekomen zijn had men de bronaanvraag wel verwerkt Dus: proces doet verzoek om bron => stel dat aan verzoek wordt tegemoetgekomen: is het resultaat een veilige toestand? => als (veilige toestand) voldoe aan verzoek anders blokkeer proces en geef geen gehoor aan verzoek Voordelen vermijdingsstrategie: het is niet nodig processen preëmptief te onderbreken <-> detecteren het is minder beperkend dan deadlock voorkomen Beperkingen voor het gebruik: per proces moet het maximaal aantal vereiste bronnen gekend zijn de processen die zo worden beoordeeld moeten onafhankelijk zijn: hun volgorde mag nog niet beperkt zijn door een vereiste synchronisatie er moet een vast aantal toe te wijzen bronnen zijn een proces mag niet worden beëindigd terwijl het bronnen vasthoudt, want dan is er geen nood aan dit systeem, dan kan men gewoon bij een tekort aan bronnen, een proces beëindigen en zijn bronnen recupereren Nadeel van vermijden: het is een (zeer) voorzichtige strategie (bij het niet starten van een nieuw proces zeker) wat leidt tot inefficiëntie want het kan zijn dat men een proces niet uitvoert/blokkeert terwijl dat mss helemaal niet nodig was geweest (maar dat weet het systeem pas als het mss te laat is so 'better safe than sorry') Detecteren van deadlock Deadlocks vermijden: beperkingen opleggen aan processen en het beperken van toegang tot voorzieningen Deadlocks detecteren: geen beperkingen er wordt, in de mate van het mogelijke aan alle bronaanvragen tegemoetgekomen periodiek voert het OS een algoritme uit om 'cirkelvormig wachten' vast te stellen Algoritmen voor detecteren deadlock Ingrediënten: een matrix van nodige bronnen per proces matrix van reeds gealloceerde bronnen per proces vector nog beschikbare bronnen vector totaal aantal instanties per bron Stappen: 1. markeren van alle processen waaraan geen enkele bron is toegewezen (dus overal nullen in de 'Allocation' matrix) 2. initialisatie van een tijdelijke vector W die gelijk is aan de vector van nog beschikbare bronnen 3. op zoek naar een proces waarvoor geldt dat het aantal geclaimde instanties van bronnen (matrix Q) kleiner of gelijk is aan het aantal nog beschikbare instanties 4. => wordt zo een proces niet gevonden => algoritme beëindigen; wordt dat wel gevonden => dat proces markeren en de instanties van bronnen uit de matrix Allocation die bij dat proces horen worden bij W opgeteld en we gaan verder Wanneer deadlock: er is sprake van een deadlock als er aan het einde van het algoritme nog ongemarkeerde processen zijn (deze zitten in een deadlock); een proces wordt immers gemarkeerd wanneer het geen bronnen meer vasthoudt en dus ook niet nuttig is voor het vrijgeven van bronnen na uitvoering van het proces Herstel 4 mogelijke methoden; 1 is de minst geavanceerde -> 4, de meest geavanceerde 1. afbreken van alle processen met een deadlock: meest gebruikte methode in OS 2. rollback van elk proces met een deadlock tot een bepaald punt en herstart alle processen (vereiste is dat rollback en restart zijn ingebouwd in het systeem). Risico dat de deadlock opnieuw zal gebeuren maar aangezien de volgorde bij gelijktijdige verwerking niet vastligt en de processen dus hoogstwsl in een andere volgorde zullen worden uitgevoerd is de kans groot dat de deadlock niet plaatsgrijpt 3. beëindig na elkaar de processen met een deadlock totdat de deadlock niet meer bestaat. Na elke beëindiging moet het algoritme worden uitgevoerd om na te gaan of er nog een deadlock is. De volgorde van beëindiging moet zo zijn dat dit minimale kosten met zich meebrengt 4. Preëmptief bronnen afnemen van de processen totdat deadlock niet meer bestaat. Na elke preëmptieve onderbreking moet het algoritme worden uitgevoerd om na te gaan of er nog een deadlock is + rollback van een dergelijk proces tot het punt voorafgaand aan de toewijzing van de zojuist afgenomen bron aan dat proces. Op basis waarvan worden in 3 en 4 processen beëindigd of bronnen afgenomen: processen die het minste processortijd hebben ingenomen processen met de laagste prioriteit de langste resterende duur heeft de kleinste hoeveelheid toegewezen bronnen heeft Geïntegreerde aanpak van deadlock Het zou beter zijn dat een systeem, ipv 1 strategie te gebruiken, er meerdere kan toepassen, al naargelang de vereiste daartoe. Zo kan het handig zijn: de bronnen in te delen in een aantal klassen de strategie ter vermijding van cirkelvormig wachten te gebruiken om deadlock te voorkomen tussen klassen van bronnen te voorkomen om per klas een strategie te gebruiken die het best past bij de soorten van bronnen in die klasse Mogelijke klassen van bronnen: swap-ruimte: geheugen gebruikt voor geswapte processen procesbronnen: apparaten die kunnen worden toegewezen(diskettestation, bestanden) hoofdgeheugen: pagina's of segmenten die aan processen kunnen worden toegekend interne bronnen: bvb I/O kanalen aanpak om deadlock te vermijden binnen elke klasse: swap-ruimte: voorkomen van deadlock door te eisen dat een proces in één keer alle bronnen aanvraagt en dit zolang te blokkeren zolang een bron niet vrij is (vasthouden en wachten); dit kan hier werken omdat dit vereist dat de maximaal vereiste opslagruimten bekend zijn, wat hier zo is vermijden van deadlock procesbronnen: voorkomen door een rangorde aan te brengen (=> cirkelvormig wachten opheffen) vermijden van deadlocks: gaat omdat de processen in deze klasse vooraf aangeven welke voorzieningen ze denken te zullen nodig hebben hoofdgeheugen: voorkomen: processen preëmptief te onderbreken => proces wordt geswapt naar swapgeheugen => er komt ruimte vrij om deadlock op te lossen interne bronnen: voorkomen door gebruik van rangorde Probleem van de dinerende filosofen Beginsituatie: 5 filosofen 1 tafel met 5 borden en 5 vorken spaghetti wordt gegeten met de twee vorken naast het bord Beperkingen: moet voldoen aan wederzijdse uitsluiting: een vork mag niet tegelijkertijd door meerdere filosofen worden gebruikt geen deadlock of uithongering p306flock://favorites/urn:flock:feed:http%3A%2F%2Fwww.deredactie.be%2Fcm%2Fde.redactie %2Fnewswire%3Fmode%3Datom 6.6.1 Een oplossing met semaforen uitsluiting van deadlock door het aantal processen aan tafel te beperken tot aantal processen – 1 => er is minstens 1 proces dat de nodige bronnen kan gebruiken en volledig kan uitgevoerd worden 6.6.2 Een oplossing met een monitor vector met 5 conditievariabelen: 1 per vork vector met 5 booleans: na te gaan of een vork beschikbaar is, als dat niet is, dan moet het proces in de wachtrij van die vork Mechanismen voor gelijktijdigheid in UNIX Pijpen een cirkelvormige buffer waarmee 2 processen kunnen communiceren (producent/consumentmodel) => FIFO wachtrij die wordt geschreven door het ene en gelezen door het andere proces de pijp heeft een vaste grootte aan bytes => wil een proces meer schrijven dan erin kan of wil een proces meer bytes lezen dan erin staan => proces wordt geblokkeerd, zoniet, dan wordt het schrijf-of leesverzoek meteen ingewilligd twee soorten: benoemde(named) en naamloze(nameless) pipe: gerelateerde processen kunnen een nameless pipe gebruiken <-> processen zonder relatie kunnen alleen een benoemde pipe gebruiken Berichten Bericht: tekst dat vergezeld gaat van een type proces heeft een wachtrij (postvak); een ander proces stuurt een bericht naar een ander proces zijn postvak. Dat proces kan berichten lezen, ofwel FIFO, ofwel op basis van het type proberen sturen naar een vol postvak => opschorten vd zender proberen lezen uit een leeg postvak => opschorten vh proces een proces wordt NIET opgeschort wanneer het een bericht niet kan lezen Gedeeld geheugen snelste vorm van communicatie tss processen processen lezen en schrijven van en naar een gedeeld stuk virtueel geheugen processen kunnen alleen-lezen of alleen-schrijven zijn wederzijdse uitsluiting is een vereiste aangezien er niet én gelezen en tegelijkertijd geschreven mag worden of door twee processen tegelijkertijd mag geschreven worden Semaforen Door het gebruik van gewone (dus geen binaire) semaforen kunnen verschillende processen tegelijkertijd worden uitgevoerd de kernel voert alle gevraagde bewerkingen uit op atomair niveau: geen enkel ander proces krijgt toegang tot de semafoor tot de bewerkingen gedaan zijn Signalen softwaremechanisme dat een proces informeert over asynchrone gebeurtenissen gelijkwaardig aan interrupt maar kent geen prioriteit => worden allemaal gelijkwaardig behandeld wordt verstuurd door processen onderling of door de kernel reactie van een proces op een signaal: signaal negeren standaardactie functie voor signaalafhandeling uitvoeren Geheugenbeheer Effectief geheugenbeheer is essentieel bij een systeem met multiprogrammering. Geheugen moet efficiënt worden toegewezen om zoveel mogelijk processen in het geheugen te laden zodat de processortijd optimaal benut wordt. Vereisten voor geheugenbeheer Relocatie De programmeur weet meestal niet waar het programma in het geheugen geplaatst zal worden bij uitvoering. Tijdens uitvoering van het programma kan het terug naar schijf geswapt worden om dan terug naar het geheugen geplaatst te worden op een andere locatie. Het OS moet de locatie kennen van de procesbesturingsinformatie en van de uitvoeringsstack. Het moet ook weten op welk adres de uitvoering van het programma begint. De processor moet echter ook in staat kunnen zijn om verwijzingen naar code, die in het programma gebeuren, te kunnen omzetten naar een echt adres in het geheugen. Sprongopdrachten bevatten een adres dat verwijst naar de volgende uit te voeren instructie. Dit heeft natuurlijk ook implicaties voor het OS, dat verwijzingen in de code gaat moeten omzetten/translateren naar echte fysische adressen. Bescherming Processen moeten beschermd worden tegen verstoringen door andere processen : • Processen mogen niet zonder toestemming naar geheugenlocaties in andere processen verwijzen. • Bij Relocatie is de locatie van een programma in het hoofdgeheugen onbekend, dus is het onmogelijk absolute geheugenadressen te controleren bij het compilen. • Geheugenverwijzingen moeten dus at run time gecontroleerd worden. • De vereisten voor geheugenbescherming moeten voldaan zijn door de processor ( hardware ) in plaats van door het besturingssysteem ( software ) o Het BS kan niet anticiperen op alle geheugenverwijzingen die een programma kan gebruiken. Delen Bescherming van de processen is noodzakelijk maar het moet wel mogelijk zijn dat processen bepaalde delen van het geheugen delen. Het is ook beter om elk proces toegang te geven tot hetzelfde exemplaar van het programma , in plaats van dat elk proces zijn eigen kopie gebruikt. Dit is het overmatig gebruiken van het werkgeheugen. Logische indeling De meeste programma’s zijn ingedeeld in modules, waarvan sommige niet kunnen worden gewijzigd (alleen lezen, … ) en waarvan andere modules gegevens bevatten die wel mogen worden gewijzigd. Voordelen van modules : • Modules kunnen onafhankelijk worden geschreven en gecompileerd. Waarbij alle verwijzingen van de ene naar de andere module tijdens de uitvoering worden ingevuld door het systeem • Verschillende modules kunnen andere beschermingsniveaus krijgen ten koste van wat overhead. • Het wordt mogelijk mechanismen te maken waarbij processen modules kunnen delen. Fysieke indeling Hoofdgeheugen(main memory) Secundair geheugen(secondary memory) snelle toegang langzaam vluchtig: geen permanente opslag wel permanente opslag duur goedkoop Het hoofdgeheugen wordt gebruikt voor programma’s die in gebruik zijn en de secundaire voor het opslagen van andere programma’s. Er moet informatie kunnen worden uitgewisseld tussen hoofdgeheugen en secundair geheugen. De verantwoordelijkheid hiervoor ligt echter niet bij de programmeur want: het kan zijn dat het beschikare geheugen kleiner is dan de plaats die nodig is voor een programma => de programmeur moet een techniek toepassen (overlay): meerdere modules kunnen worden toegekend aan hetzelfde geheugengebied, het is aan het hoofdprogramma om te zorgen dat de modules gewisseld worden. Het gebruik van overlays is echter tijdsabsorberend bij een systeem van multiprogrammering weet een programmeur op voorhand niet hoeveel ruimte er zal vrij zijn en waar die ruimte zal zijn => de programmeur kan geen boodschappen inbouwen waarbij er iets gezegd wordt over geheugenlocaties omdat deze niet vastliggen Partitioneren van geheugen Belangrijkste taak geheugenbeheer: het inladen van processen zodat ze kunnen uitgevoerd worden. In bijna alle moderne systemen wordt daarvoor virtueel geheugen gebruikt: d.i. gebaseerd op twee basistechnieken: pagineren en segmenteren. Vaste indeling van Partities Bij de meeste vormen voor geheugenbeheer mogen we aannemen dat het besturingssysteem een vast deel van het hoofdgeheugen bezet en dat de rest van het hoofdgeheugen beschikbaar is voor gebruik door meerdere processen. Grootte van Partities Partities met een vaste grootte kennen twee problemen. • Een programma kan te groot zijn om in een partitie te passen. Dan moet de programmeur het programma ontwerpen dat overlays gebruikt, zodat altijd maar een deel van het programma zich in het hoofdgeheugen hoeft te bevinden. Is er een module nodig die nog niet aanwezig is , dan moet het gebruikersprogramma dit in de partitie van het programma laden en de programma’s of gegevens die zich daar bevinden vervangen. • Er is een inefficiënt gebruik van het geheugen: Elk proces hoe klein ook , bezet meteen een hele partitie => interne fragmentatie Bij gebruik van Partities van ongelijke grootte is er minder interne fragmentatie. Plaatsingsalgoritme Bij Partities van gelijke grootte speelt de plaatsing van processen nauwelijks een rol. Zolang maar een partitie beschikbaar is, kan een proces in die partitie geplaatst worden. Bij Partities met een ongelijke grootte kan: 1. men een proces vast toewijzen aan de kleinste partitie waar het in past. Elke partitie heeft een wachtrij en processen Voordeel: er is een minimalisatie van interne fragmentatie 2. men gebruik maken van 1 wachtrij : als er bvb een proces van < 8mb ingeroosterd moet worden en de Partities van 8 mb zijn op, dan zal er niet gewacht worden maar het proces zal worden geplaatst in een partitie van een grotere grootte. Bovendien kan gezegd worden dat systemen met vaste partitionering relatief eenvoudig zijn en nauwelijks besturingssysteemsoftware en verwerkingsoverhead vereisen. Er zijn echter nadelen : • beperking van het aantal ( niet – opgeschorte ) processen in het geheugen • kleine processen zorgen voor inefficiënt geheugengebruik ( interne fragmentatie ) Dynamische indeling van partities Bij dynamisch Partitioneren wordt een variabel aantal Partities van variabele grootte gebruikt. => wordt een proces overgebracht naar het geheugen, dan krijgt het de hoeveelheid geheugen dat het nodig heeft en niet meer. Nadeel: na verloop van tijd ontstaan er vele kleine gaten in het geheugen die elk apart te klein zijn om een proces te kunnen bevatten: externe fragmentatie : het geheugen wordt buiten de partities gefragmenteerd <-> interne fragmentatie: binnen de partities zelf. Een oplossing voor deze externe fragmentatie is compaction: van tijd tot tijd worden de processen herschoven binnen het geheugen zodat ze aanééngesloten zijn en al het vrije geheugen 1 blok vormt. Er is wel een nadeel : compaction is verspilling van veel processortijd. Een vereiste voor compaction is dynamische Relocatie : het moet mogelijk zijn een programma te verplaatsen van het ene naar het andere gebied zonder de geheugenverwijzingen in het programma ongeldig te maken. Plaatsingsalgoritme 1. Best-fit het toewijzen van een zo klein mogelijke, niet-bezet blok geheugen aan een proces 2. First-fit doorzoekt het geheugen vanaf het begin en wijst het eerste niet-bezette blok toe aan een proces. Dit werkt het snelst. 3. Next-fit doorzoekt het geheugen vanaf de plaats waar de laatste plaatsing is gebeurd en wijst het volgende beschikbare blok toe dat groot genoeg is. Dit algoritme zal vaker geheugen toewijzen dat zich aan het einde van het geheugen bevindt Nadelen per strategie: 1. Best-Fit: Geheugencompactie moet vaker gebeuren dan bij de andere algoritmes: hoofdgeheugen raakt veel sneller vervuild met kleine blokken vrij geheugen die niet bruikbaar zijn om processen aan toe te wijzen => best-fit presteert het slechtst 2. First-fit: het voorste deel van het geheugen gaat snel volzitten met kleine blokken die té klein zijn voor processen. Het probleem is dat deze toch worden doorzocht bij aanvang van het algoritme 3. Next-fit: het grootste blok vrije geheugen (einde van het geheugen) wordt vrij snel opgesplitst in kleine delen => compaction zal vaker nodig zijn Vervangingsalgoritme Om te voorkomen dat processortijd wordt verspild aan wachten tot een wachtend proces gedeblokkeerd raakt, swapt het besturingssysteem een van de processen uit het hoofdgeheugen om ruimte vrij te maken voor een nieuw proces of een proces in de toestand Gereed-opgeschort. Het besturingssysteem moet hierbij beslissen welk proces wordt vervangen. Buddysysteem Zowel vaste als dynamische partitionering hebben nadelen: vast: beperkt het aantal actieve processen en inefficiënt geheugengebruik dynamisch: veel onderhoud en overhead door compaction volledig beschikare ruimte = 2u wanneer nu een proces moet worden toegewezen aan geheugen, dan wordt gecontroleerd of 2u-1 < s < 2u ->als dat zo is, dan wordt het hele geheugenblok toegewezen aan het proces -> als dat niet zo is, dan wordt het blok opgedeeld in twee gelijke 'buddies' en wordt terug nagekeken of 2u-1 < s < 2u totdat dit zo is en het proces kan worden toegewezen Het buddysysteem omzeilt de problemen van vaste en dynamische partitionering MAAR het virtueel geheugen, gebaseerd op pagineren en segmenteren is veel beter. Relocatie vaste partitionering met één wachtrij per partitie (fig 7-3a): een proces heeft een vaste partitie => lader met relocatie: wanneer een proces de eerste keer wordt geladen worden de relatieve verwijzingen in de code veranderd in absolute adressen adhv het basisadres van het in te laden proces(dit kan aangezien het altijd aan dezelfde partitie wordt toegewezen) partities van gelijke grootte (fig 7-2) + vaste partitionering met 1 wachtrij voor het hele geheugen(7-3b) + dynamische partitonering: een proces kan per keer dat het ingeladen wordt toegewezen worden aan een andere partitie (bij dyn. zelfs bij compactie) => de uitvoeringscode staat telkens op een ander adres Om dit probleem op te lossen maakt men een onderscheid tussen verschillende soorten adressen: logisch adres: verwijzing naar een locatie onafhankelijk van de huidige toewijzing van gegevens aan het geheugen; een logisch adres moet eerst vertaald worden naar een fysisch adres voordat geheugentoegang mogelijk is relatief adres: een verwijzing naar een locatie vanaf een bepaald punt, doorgaans is dit punt het begin van het programma fysisch adres: het absolute of de echte locatie in het hoofdgeheugen Om een programma te kunnen uitvoeren moeten de relatieve adressen worden omgezet naar absolute adressen, dit gebeurt hardwarematig proces wordt actief => beginadres wordt ingeladen in basisregister <-> grensregister, bevat het eindadres van het programma (beginadres en einde worden bepaald wanneer een programma in het geheugen wodt geladen of wanneer het procesbeeld naar het geheugen wordt geswapt) elk relatief adres ondergaat twee bewerkingen in de processor: 1. eerst wordt de waarde van het basisregister opgeteld bij het relatief adres om een absoluut adres te krijgen (beginadres + relatief adres = absoluut adres) 2. dat absoluut adres wordt vergeleken met het adres in het grensregister => ligt het verkregen adres niet tussen de grenzen => er wordt een interrupt gegenereerd naar het OS dat moet reageren op deze fout ligt het wel tussen de grenzen, dan mag er verdergegaan worden met de uitvoering van de instructie Pagineren Partities met een vaste of variabele grootte maken beide inefficiënt gebruik van het geheugen. De vaste grootte leidt tot interne fragmentatie De variabele grootte leidt tot externe fragmentatie Pagineren is het geheugen opdelen in kleine stukken van vaste grootte en welke allemaal even groot zijn. Deel nu elk proces op in stukken van dezelfde grootte. Dergelijke stukken worden pagina’s genoemd. De stukken van het geheugen worden frames genoemd. Het besturingssysteem houdt een pagina tabel bij voor elk proces. Deze tabel bevat • De frame locatie voor elke pagina in het proces • Een geheugenadres bestaande uit een paginanummer en een offset binnen die pagina. Bovenstaande figuur illustreert het gebruik van pagina’s en frames. Op een bepaald moment zijn sommige frames in het geheugen bezet en zijn andere vrij. Het besturingssysteem houdt een lijst bij van vrije frames. De figuur verduidelijkt zichzelf. Het logische adres is de relatieve locatie van een byte of woord ten opzichte van het begin van het programma. De processor vertaalt dit in een fysiek adres. Voor adresvertaling bij paginering zijn volgende stappen nodig: • Haal het paginanummer uit de linker n bits van het logische adres • Gebruik het paginanummer als inde in de procespaginatabel om het framenummer k te vinden. • Het fysieke beginadres van het frame is k * 2m , en het fysieke adres van de gezochte bye is gelijk aan dit nummer plus de positie. Dit fysieke adres hoeft niet te worden berekend. Het wordt eenvoudig gevormd door het framenummer toe te voegen aan de positie. Segmenteren Het alternatief voor het opdelen van een gebruikersprogramma is het segmenteren. Het programma met zijn bijhorende gegevens wordt opgedeeld in een aantal segmenten. Alle segmenten van alle programma’s hoeven niet dezelfde grootte te hebben , maar er is wel een maximumgrootte vastgesteld. Vermits segmenten niet even groot zijn , is segmenteren gelijkaardig aan dynamische partitionering. Segmentatie voorkomt interne fragmentatie maar leidt, net als een dynamische partitionering tot externe fragmentatie. Net als bij paginering gebruikt eenvoudige segmentatie een segmenttabel voor elk proces en een lijst van vrije blokken in het hoofdgeheugen. Elke ingang in een segmenttabel vebat het beginadres van het bijbehorende segment in het hoofdgeheugen. De ingang bevat ook informatie over de lengte van het segment, om te voorkomen dat ongeldige adressen worden gebruikt. Voor adresvertaling bij segmenteren zijn de volgende stappen nodig: • Haal het segment nummer uit de linker n bits van het logische adres. • Gebruik het segmentnummer als index in de segmenttabel van het proces om het fysieke beginadres van het segment te vinden. • Vergelijke de positie, die is vastgelegd in de rechter m bits, met de segment lengte. Is de positie groter dan de lengte , dan is het adres ongeldig. Virtueel geheugen Hardware en besturingsstructuren Eigenschappen pagineren en segmenteren: 1. relocatie: een proces kan gedurende verschillende momenten verschillende geheugenlocaties innemen wanneer het wordt weggeswapt en weer wordt teruggeswapt. Dit komt omdat de adressering die gebruikt wordt dit toelaat (= at runtime vertaling <-> tijdens compilen want de adressen staan niet hard gecodeerd) 2. proces kan opgebroken worden in meerdere stukken (pagina's of segmenten) 3. de stukken moeten niet aaneengesloten zijn om te kunnen uitgevoerd worden GEVOLG: het is niet nodig dat een volledig proces(alle pagina's/segmenten) in het hoofdgeheugen staat wanneer het uitgevoerd wordt (het stuk met de volgend uit te voeren instructie en met de volgende te gebruiken geheugen locatie is genoeg) Werking: nieuw proces moet worden ingeladen: OS laadt het begin van het proces in en het deel dat de gegevens bevat waarnaar de instructies verwijzen (residente set = deel v/e proces dat zich werkelijk in het hoofdgeheugen bevindt) de processor kan nagaan of de geheugenverwijzingen nog steeds ingeladen zijn. Dit wordt gecontroleerd adhv de logische adressen enerzijds adhv de segment-of paginatabel anderzijds wanneer logisch adres niet meer in het hoofdgeheugen => processor genereert interrupt => OS blokkeert proces => I/O verzoek om het nodige deel van het proces te lezen vd harde schijf => terwijl dat bezig is wordt een ander proces uitgevoerd OS krijgt een interrupt dat I/O bewerking compleet is en zet proces terug in de wachtrij 'Gereed' Gevolgen: 1. er kunnen zich meer processen in het geheugen bevinden => efficiënter gebruik van de processor omdat de kans hoger is dat er ten minste één proces 'Gereed' is 2. een proces kan groter zijn dan het totale hoofdgeheugen: (dit geldt uiteraard niet voor de residente set) <-> geen segmenteren of pagineren, dan moet de programmeur zich wenden tot het gebruik van overlay terwijl nu is er voor de programmeur 1 groot geheugen dat beheerd wordt door de hardware en het OS Twee soorten geheugen: 1. reële geheugen (de plaats waar processen uitgevoerd worden) 2. virtuele geheugen (de ruimte die wordt toegewezen op schijf) Lokaliteit en virtueel geheugen Virtueel geheugen op basis van uitsluitend pagineren of de combinatie van pagineren en segmenteren is een essentieel onderdeel geworden van de meeste hedendaagse besturingssystemen. Trashing: wanneer de processor meer bezig is met het in en uitswappen van processen dan met de uitvoering ervan. Dit gebeurt wanneer het reële geheugen overvol zit en er continu processen moeten uitgeswapt worden om plaats te maken voor andere stukken van een proces. Wanneer een uitgeswapt deel echter meteen weer nodig is, dan moet dit worden ingeswapt. Veel swappen dus en weinig uitvoer. Trashing voorkomen door te voorspellen welke delen van een proces in de nabije toekomst zullen nodig zijn op basis van het recente verleden. Dit is gebaseerd op het lokaliteitsbeginsel: verwijzingen naar programma's en gegevens van processen hebben de neiging op te hopen tot een cluster => het is geldig om te veronderstellen dat slechts een deel van een proces nodig is voor een beperkte tijd => het is mogelijk om een voorspelling te maken van de stukken die zullen nodig zijn in de nabije toekomst wat trashing voorkomt fig8-1 illustratie van lokaliteitsbeginsel => virtueel geheugen kan werken aangezien er een voorspelling kan gemaakt worden en trashing kan voorkomen worden, anders was het maar een slecht idee aangezien het na verloop van tijd aanleiding zou geven tot trashing Wat nodig voor virtueel geheugen: 1. hardwareondersteuning: toepassen paginering en segmentering + vertaling van adressen 2. softwareondersteuning: beheren van de verplaatsing van delen proces tussen hoofd-en secundair geheugen Pagineren Elk proces heeft paginatabel: iedere ingang = framenummer voor de bijhorende pagina in het hoofdgeheugen. Pagineren + gebruik van virtueel geheugen => complexer want het kan nu zijn dat er slechts een deel van een proces in het geheugen staat => elke page table entry (PTE) bevat nu ook een bit die aangeeft of de pagina in het hoofdgeheugen zit of niet (de present- bit of de p-bit) Een andere bit die aanwezig is in de PTE, is de m(odify)-bit: geeft aan of de pagina gewijzigd is, is dat niet zo, dan moet de pagina niet worden weggeschreven naar het virtueel geheugen bij het swappen aangezien beide versies nog gelijk zijn => efficiënter gebruik maken van het systeem. Paginatabelstructuur lezen van een woord uit het geheugen: vertalen van een virtueel (logisch) adres(paginanummer en offset) in een fysiek adres(framenummer en offset) paginatabel heeft variabele grootte (afhankelijk van grootte proces) => niet opslaan in registers maar in hoofdgeheugen (zie fig 8-3) proces wordt uitgevoerd => register bevat beginadres van de paginatabel van het proces het paginanummer wordt gebruikt als index in de tabel om het bijhorende framenummer op te zoeken reëel adres = framenummer + offset De meeste systemen gebruiken 1 paginatabel per proces <-> VAX: ieder proces kan 231 (2 G) groot zijn. Stel: paginagrootte: 512 byte => 222 PTE's => Paginatabel = enorm => paginatabel wordt ook ingedeeld in pagina's en wordt opgeslaan in virtueel geheugen. => wordt een proces uitgevoerd, dan moet er een deel van de paginatabel in het hoofdgeheugen staan en al zeker de PTE van de huidige pagina. Sommige systemen gebruiken een systeem met twee niveaus: bevat een paginadirectory (elke ingang van deze directory verwijst naar een paginatabel). Is de lengte van het paginaoverzicht X en is de lengte vd paginatabel Y, dan bestaat een proces uit X*Y pagina's stel: adressen van 32 bits paginagrootte: 212 (kB) => virtueel geheugen van 232 bytes (4GB) kan 220 aantal pagina's bevatten iedere PTE = 4B => de volledige paginatabelgrootte = 220 * 4 = 222 bytes(4MB) => mogelijkheid om een gebruikerspaginatabel van 210 pagina's in het virtueel geheugen te hebben en bereikbaar te maken a.d.h.v. een basispaginatabel met 210 PTE's en een grootte van 212 (4 kB) in het hoofdgeheugen. De basispaginatabel blijft altijd in het hoofdgeheugen! fig 8-5 adresvertaling bij een systeem met twee niveaus: eerste 10 bits van virtuele adres = index in de basispaginatabel om de PTE te verkrijgen voor een pagina in de gebruikerspaginatabel(paginafout: refereren naar een pagina die niet aanwezig is in hoofdgeheugen). is de pagina wel aanwezig in het hoofdgeheugen, dan zijn de volgende 10 bits in het adres de index in de gebruikersPTE-pagina om de PTE te vinden van de pagina waarnaar verwezen wordt in het virtuele adres Geinventeerde paginatabel Nadeel van hogergenoemde paginatabellen is dat de grootte ervan evenredig is met de omvang van de virtuele adresruimte. Bij een ander type paginatabel is dit niet, hierbij wordt er gewerkt met een geïnverteerde paginatabelstructuur (indexeert de items op framenummer ipv op virtueel paginanummer) waarbij het paginanummer (onderdeel van virtueel adres) gehashed wordt en deze hash verwijst naar de geïnverteerde paginatabel. Deze tabel heeft een vaste grootte, namelijk als een fysiek geheugen 2m frames bevat dan is er plaats in de tabel voor 2m items waarbij item z verwijst naar frame i. De geïnverteerde paginatabel bevat 1 item voor elke werkelijke frame ipv 1 item per virtuele pagina collision (de hashes van twee verschillende paginanummers zijn gelijk) is mogelijk => er wordt gewerkt met een kettingtechniek om toch tot het juiste adres te komen Ieder item in de geïnverteerde paginatabel bevat volgende gegevens: Paginanummer: (paginanummer virtueel adres) PID: proces dat deze pagina in bezit heeft (combinatie paginanummer-PID is uniek => kan gebruikt worden als er collision is bij hashing) Besturingsbits: bvb.: modified, referenced, valid, beveiligings- en vergrendelingsinfo Kettingpointer: is 0 als er geen koppelingen zijn met andere pagina's. bevat een nummer van 2m-1 dat het rangnummer is in de tabel van het volgende item in de ketting Translation lookaside buffer Elke virtuele verwijzing naar het virtuele geheugen kan twee dingen veroorzaken in het fysieke geheugen: ophalen van gegevens ophalen van de juiste PTE Als beiden moeten gebeuren tgv dezelfde verwijzing, dan moet er eerst gezocht worden naar de juiste PTE èn dan nog eens naar de juiste gegevens op de schijf => verdubbeling van geheugentoegangstijd. Dit wordt opgelost door TLB = speciale cache voor paginatabelingangen; bevat de PTE's die recent het meest gebruikt zijn Werking: processor ontvangt een virtueel adres is de gewenste PTE in de TLB, dan wordt het framenummer opgevraagd en wordt het reële adres gevormd, samen met de offset TLB-miss => met paginanummer als index kijken of de 'present' bit van de pagine in de PTE in de paginatabel op 1 staat => pagina staat in het hoofdgeheugen => het framenummer wordt opgevraagd uit de PTE en het reële adres wordt gevormd + de TLB wordt bijgewerkt door deze nieuwe PTE toe te voegen is de p-bit 0 => paginafout en dan verlaten we de hardware om het OS de pagina re laten laden en om de paginatabel bij te werken Opmerking bij stroomschema p379 (fig 8-8): wanneer I/O bewerking gebeurt voert processor ondertussen ander proces(sen) uit. Overeenkomstig het beginsel van lokaliteit: de meeste verwijzingen naar virtueel geheugen zijn verwijzingen naar locaties in recent gebruikte pagina's Het opzoeken in de TLB gaat sneller dan het opzoeken in de paginatabel omdat het gaat om cachegeheugen! associatieve vertaling (associative mapping): de hardware is in staat om verschillende TLB entries tegelijkertijd te doorzoeken (daarom is het nodig dat iedere TLB ingang naast het paginanummer ook de volledige PTE bevat) Directe vertaling die gebruikt wordt om op te zoeken in de paginatabel Het gebruik van een TLB vereist interactie met de hoofdgeheugencache. Stel dat de PTE zich in de TLB bevond of in de paginatabel na een TLB-miss, dan wordt het reëel adres gevormd. Dan wordt er in de hoofdgeheugencache nagekeken of het blok met het vereiste woord zich daarin bevindt. Is dat niet zo, dan moet de processor het inladen uit het hoofdgeheugen. Paginagrootte Afweging: hoe groot moet een pagina nu zijn? Is een kleine beter dan een grote? hoe kleiner een pagina des te kleiner is de interne fragmentatie MAAR des te groter is het aantal pagina's dat het proces nodig heeft (en dus ook meer pagina's die moeten aanwezig zijn in het geheugen => kans ++ dat er veel gaat moeten ingeladen worden uit virtueel geheugen) => een deel van de paginatabellen van actieve processen gaat zich in het virtueel geheugen bevinden => bij 1 verwijzing naar het geheugen kan dan een dubbele paginafout optreden: 1 voor het binnenhalen van de nodige gegevens uit de paginatabel en 1 voor het binnenhalen van de procespagina De meeste apparaten voor secundaire opslag vereisen echter een grotere paginagrootte voor een meer efficiënte blokoverdracht van gegevens (daarvoor dienen ze, om grote hoeveelheden aaneengesloten data te verwerken) Nog iets om mee rekening te houden is de invloed die de paginagrootte heeft mbt paginafouten: paginagrootte klein => weinig paginafouten want er kunnen veel pagina's worden ingeladen in het hoofdgeheugen. Beginsel van lokaliteit: na verloop van tijd bevinden zich in het geheugen alle gedeelten van het programma in de buurt van frequente verwijzingen als de grootte toeneemt, bevat elke afzonderlijke pagina locaties die zich verder an een recente verwijzing bevinden => invloed beginsel lokaloteit neemt af en dan stijgt de foutfrequentie naarmate de pagina's nog groter worden zullen ze groot genoeg worden om ganse processen te bevatten waardoor er geen paginafouten meer optreden De foutfrequentie is ook afhankelijk van het aantal frames die worden toegewezen aan een proces. Naarmate het aantal toegewezen frames stijgt, daalt het aantal paginafouten Het ontwerp van de paginagrootte hangt ook samen met de grootte van het fysieke hoofdgeheugen en van het programma. Naarmate het geheugen groter wordt, groeit ook de adresruimte die door toepassingen kan worden gebruikt. De invloed van het beginsel van lokaliteit - - op moderne programmeertechnieken: OO-programmeren: verwijzingen worden op korte tijd sterk verspreid over een groot aantal objecten multithreading: abrupte veranderingen in de instructiestroom en tot verspreide geheugenverwijzingen Probleem: als lokaliteit afneemt, dan neemt het aantal hits in de TLB ook af en vormt het opzoeken in de TLB een bottleneck Hoe dit oplossen? grotere TLB kan maar zal minder wsl zijn grotere pagina's => iedere TLB ingang verwijst naar een groter stuk geheugen (maar het vergroten van de grootte kan leiden tot een vermindering aan prestaties) Er is geëxperimenteerd geweest met meerdere paginagrootten waardoor er een flexibiliteit ontstaat die toelaat de TLB efficiënt te gebruiken. Segmenteren Gevolgen voor het virtueel geheugen vereenvoudigt het werken met groeiende gegevensstructuren want OS wijst gegevensstructuur toe aan segment dat kan groeien en krimpen <-> geen segmentatie => programmeur moet inschatten hoeveel plaats hij gaat nodig hebben voor zijn gegevensstructuur moet een segment uitgebreid worden en is er daarvoor onvoldoende ruimte, dan kan het verplaatst worden naar een deel van het geheugen waar er wel genoeg ruimte is of wordt het weggeswapt als er geen blokken zijn die groot genoeg zijn programma's kunnen onafhankelijk van elkaar worden gecompileerd 1 segment kan door meerdere processen gedeeld worden (tabel apart in een segment plaatsen zodat meerdere processen het kunnen gebruiken) de programmeur kan rechten toekennen aan segmenten => bescherming van de gegevens Organisatie elk proces heeft een eigen segmenttabel Aangezien niet alle segmenten moeten worden ingeladen in het hoofdgeheugen bevat elke segmenttabelingang (STE) naast het beginadres van het overeenkomende segment in het hoofdgeheugen + lengte van het segment ook nog een p-bit en een m-bit + nog eventuele andere besturingsbits. basismechanisme voor lezen van een woord uit het geheugen: vertalen van een virtueel adres(segmentnummer en offset) naar een reëel adres mbv de segmenttabel Een register bevat het beginadres van de segmenttabel, segmentnummer in virtueel adres dient als index voor de juist STE in de tabel. De STE geeft dan weer aan wat het basisadres is van het segment in het hoofdgeheugen. Dat basisadres + offset = reëel adres. Gecombineerd pagineren en segmenteren Pagineren is transparant voor de programmeur en elimineert externe fragmentatie en zorgt daarmee voor een efficiënt gebruik van het hoofdgeheugen. Segmentatie is zichtbaar voor de gebruiker en heeft de mogelijkheid van werken met groeiende gegevensstructuren , modulariteit en de ondersteuning van delen en bescherming. Elk segment wordt opgedeeld in een pagina’s van vaste grootte. Bescherming en delen Bescherming: elke STE: een lengte en basisadres => een programma kan geen toegang krijgen buiten de grenzen van een segment Deling: er kan naar een segment verwezen worden in de segmenttabellen van meerdere processen Dit kan ook in een pagineringssysteem maar dan is het onzichtbaar voor de programmeur. Besturingssysteemsoftware het ontwerp van het geheugenbeheer van een OS is afhankelijk van 3 fundamentele keuzes: 1. gebruik van virtueel geheugen? 2. pagineren, segmenteren of beide? 3. kiezen van algoritmes die worden toegepast voor allerlei aspecten van het geheugenbeheer Ophaalstrategie vraag herpagineren Beheer residente set grootte residente set vast variabel vervangingsbereik globaal lokaal Plaatsingsstrategie Opschoonstrategie vraag vooral opschonen Vervangingsstrategie optimaal Least recently used (LRU) First in first out Klok Paginabuffering Beheer van procesbelasting multiprogrammeringsgraad Strategie bij ophalen (fetch policy ) Deze strategie bepaalt wanneer een pagina moet worden overgebracht naar het hoofdgeheugen. Twee mogelijkheden: 1. vraagpaginering (demand paging): een pagina wordt alleen maar overgebracht naar het hoofdgeheugen bij een verwijzing naar een locatie binnen de pagina (bij de start van een nieuw proces => veel paginafouten want de pagina's waarnaar verwezen wordt zitten nog niet in het geheugen => paginafout; beginsel van lokaliteit stelt dat: naarmate meer en meer pagina's worden ingeladen, de meest toekomstige verwijzingen verwijzingen zullen zijn naar pagina's die nog maar recent zijn gebruikt geweest => aantal paginafouten daalt mettertijd) 2. prepaginering(prepaging): naast de pagina waarnaar verwezen wordt, worden ook nog andere pagin's ingeladen => efficiënter gebruik maken van de harde schijf want nu worden in 1 keer meerdere blokken gelezen ipv telkens te moeten zoeken en lezen (nu maar 1 keer zoektijd en rotatietijd !!). Dit is op het gebied van aantal paginafouten uiteraard pas interessant als de pagina's die worden ingeladen ook gebruikt worden !!!!!!!!Wordt een proces uit het geheugen geswapt ('Opgeschort'), dan worden alle pagina's van de residente van dat proces verwijderd. Wordt het proces opnieuw hervat, dan worden de pagina's die zich van dat proces in het geheugen bevonden terug ingeladen.!!!!!!!!!!! Strategie bij plaatsing Deze strategie bepaalt waar een stuk van het proces terechtkomt in het geheugen. best-fit, first-fit,... Belangrijk bij segmentering. Bij zuiver pagineren of een combinatie van segmentering en paginering maakt deze strategie niets uit omdat de hardware voor de adresvertaling en de hardware voor geheugentoegang even efficiënt kunnen werken voor elke pagina/framecombinatie Strategie bij vervanging Welke pagina moet worden vervangen uit de verzameling pagina's doe voor vervanging in aanmerking komen wanneer alle frames in het hoofdgeheugen bezet zijn en er moet een nieuwe pagina worden binnengehaald om te reageren op een paginafout. Iedere aanpak heeft als doel dat de pagina die verwijderd wordt, de pagina is waarbij de kans dat er in de nabije toekomst naar zal worden gerefereerd het kleinst is. Naarmate een strategie uitgebreider en geavanceerder wordt, stijgt de hard-en softwareoverhead. Framevergrendeling Wanneer een frame vergrendeld is (grendelbit staat op 1 in de frame- of de paginatabel) => pagina kan niet worden verwijderd in het hoofdgeheugen om te worden vervangen Elementaire algoritmen 1. Optimaal: vervangt de pagina waarnaar het verst in de toekomst gerefereerd zal worden. Dit is echter puur theoretisch omdat dit van het OS vereist dat het op de hoogte is van alle toekomstige referenties 2. Least recently used (LRU): vervang de pagina waarnaar het minst recent is gerefereerd: volgens beginsel van lokaliteit is dit de pagina met de kleinste kans om in de toekomst naar gerefereerd te worden 3. FIFO: pagina's worden om beurten verwijderd (round robin) => de pagina die het langst in het geheugen is wordt vervangen. Dit is nadelig want het zou kunnen zijn dat die in de nabije toekomst weer nodig is => paginafout. Maar, het voordeel is dat dit gemakkelijk te implementeren is. 4. Klok: aan elk frame wordt een extra bit toegevoegd: de u(se)-bit. Wanneer een pagina voor het eerst in het geheugen wordt geladen, dan wordt de pointer naar het volgende frame gezet. Als naar de pagina verwezen wordt, dan wordt de use bit op 1 gezet. Wanneer een pagina vervangen moet worden, dan wordt het eerste frame dat tegengekomen wordt met een use bit op 0 vervangen. Tijdens het zoeken voor vervanging wordt elke use bit die op 1 staat, op 0 gezet (zie fig 8-15) Het verschil met FIFO is dat sommige frames (met u-bit==1) worden overgeslagen en dat het niet altijd de oudste pagina moet zijn die vervangen wordt. Men heeft gevonden dat, naarmate er meer frames worden toegewezen aan een proces, het verschil in paginafouten kleiner en kleiner wordt tussen de verschillende strategieën => kan het lonen om te opteren voor een simpele strategie omdat deze minder tijd in beslag neemt om uit te voeren. Het klokalgoritme kan krachtiger worden gemaakt wanneer er rekening wordt gehouden met een tweede bit naast de u-bit: de m-bit => 4 categorieën: 1. geen recente toegang, ongewijzigd (u:0;m:0) 2. recente toegang, ongewijzigd (u:1;m:0) 3. geen recente toegang, gewijzigd (u:0;m:1) 4. recente toegang, gewijzigd (u:1;m:1) Het klokalgoritme werkt dan zo: 1. zoek naar frames waarbij u==0 en m==0; het eerste frame dat hieraan voldoet wordt vervangen; 2. mislukt dat, dan wordt het eerste frame met u==0 en m==1 vervangen; 3. mislukt ook dat, dan gaan we nog eens door de frames want nu zijn alle u-bits die daarvoor 1 waren 0 geworden en is er dus zeker 1 frame dat voldoet aan u==0;m==0 OF u==0;m==1 Waarom u==0 en m==1 als tweede keuze: omdat dit frame niet recent is gebruikt en dus is de kans dat het binnenkort opnieuw gaat moeten gebruikt worden klein. Het f rame moet wel weggeschreven worden voordat het wordt vervangen maar dat weegt op tegen het feit dat het mss niet nodig is in de toekomst. Paginabuffering LRU en klok zijn superieur aan FIFO MAAR complexer en meer overhead de kosten van vervanging van een gewijzigde pagina > die van een ongewijzigde pagina Paginabuffering: Vervangen pagina gaat niet verloren maar wordt toegevoegd aan volgende lijsten: één van Lijst van vrije pagina’s als de pagina niet gewijzigd is Lijst van gewijzigde pagina’s (moeten weggeschreven worden naar secundair geheugen) de pagina wordt niet verwijderd uit het hoofdgeheugen maar de PTE wordt verwijderd uit de paginatabel en in de juiste lijst (vrije/gewijzigde) geplaatst. VOORDELEN paginabuffering: het kost weinig om de pagina terug in te laden in de residente set, gewoon de PTE uit de lijst halen en in de paginatabel zetten gewijzigde pagina's worden weggeschreven in clusters, niet 1 per 1, dat vermindert het aantal I/Obewerkingen en daarmee ook de schijftoegangstijd Paginabuffering werkt dan als een soort van cache voor pagina's Beheer van de residente set Grootte van de residente set vaste toewijzing(fixed allocation): een proces krijgt een vast aantal pagina's waarbinnen het moet worden uitgevoerd; dat aantal wordt bepaald bij de eerste keer dat het proces geladen wordt. Wanneer tijdens de verwerking een paginafout optreedt, dan moet een procespagina vervangen worden door een nieuw aangevraagde pagina variabele toewijzing(variable allocation): het aantal frames dat is toegewezen aan een proces kan variëren gedurende de levensloop van het proces. Een proces dat veel paginafouten genereert geeft aan dat het beginsel van lokaliteit slechts in beperkte mate geldt voor dat proces. Dan kan het aantal toegewezen frames aangepast(verhoogd) worden. Omgekeerd kan ook, als er zeer weinig paginafouten gegenereerd worden, dan kunnen er gerust minder frames worden toegewezen. Variabele toewijzing hangt samen met het concept 'Vervangingsbereik' Vervangingsbereik twee methodes die allebei worden geactiveerd wanneer er geen vrije frames zijn en er is een paginafout Lokaal: bij het vervangen wordt een pagina uit de residente set gekozen van het proces Globaal: alle onvergrendelde pagina's kunnen vervangen worden, van wel proces ze ook zijn Vervangingsbereik hangt samen met grootte residente set: lokale vervanging vaste toewijzing variabele toewijzing globale vervanging - het aantal aan een proces toegewezen frames ligt vast - de te vervangen pagina wordt gekozen uit de frames die zijn toegewezen aan het proces gaat niet: om de grootte van de residente set gelijk te houden moet een pagina van de residente set vervangen worden door een andere pagina van de residente set - het aantal toegewezen frames kan wijzigen voor het behoud van de werkset (working set) van het proces - de te vervangen pagina wordt gekozen uit de frames die zijn toegewezen aan het proces - de te vervangen pagina's worden gekozen uit alle beschikbare (nietvergrendelde) frames in het hoofdgeheugen => de grootte van de residente set kan variëren Vaste toewijzing met lokaal bereik proces wordt uitgevoerd in hoofdgeheugen met vast aantal pagina's paginafout => welke pagina vd residente set gaat vervangen worden? van tevoren moet worden beslist hoeveel ruimte wordt toegewezen aan een proces; nadelen: als dit te weinig is: paginafouten te veel: er kunnen te weinig processen ingeladen worden in het hoofdgeheugen => er wordt veel tijd besteed aan het swappen van processen Variabele toewijzing met globaal bereik gemakkelijkste vorm om te implementeren paginafout => vrij frame toevoegen aan de frames die zijn toegewezen aan het proces en de pagina daaraan toewijzen zijn er geen vrije frames meer, dan wordt een pagina vervangen van om het even welk proces. De moeilijkheid is deze keuze maken. Dit kan verholpen worden door gebruikt te maken van paginabuffering omdat een pagina opnieuw kan worden gebruikt als die nog niet is weggeschreven naar de harde schijf Variabele toewijzing met lokaal bereik robeert de problemen die ontstaan door het werken met globaal bereik te omzeilen: wordt een nieuw proces in het hoofdgeheugen geladen, wijs daar dan een bepaald aantal frames aan toe en gebruik prepaginering of vraagpaginering voor het vullen van de rest van de toewijzing paginafout => selecteer de te vervangen pagina uit de residente set van het proces dat de fout heeft veroorzaakt evalueer de toewijzing aan het proces zo nu en dan en verhoog of verlaag het aantal toegewezen frames indien nodig een veelbesproken methode: de werksetbenadering werkset = een verzameling pagina's van een proces waarnaar verwezen is binnen een bepaald tijdsvenster => als tijdsvenster groter wordt, dan wordt de werkset groter De working set hangt nauw samen met lokaliteit: door dat beginsel gebruikt het proces een stabiele set aan pagina's waarvan de inhoud van de werkset slechts minimaal verandert, volgende overgansperioden wijzen op een verandering naar een nieuwe lokaliteit. Tijdens een overgangsfase blijven een aantal pagina's uit de oude lokaliteit binnen het venster wat leidt tot een forse toename van de grootte van de werkset bij verwijzingen naar nieuwe pagina's. Verschuift het venster over deze paginaverwijzingen, dan neemt de werksetgrootte af totdat de werkset uitsluitend pagina's bevat die behoren tot de nieuwe lokaliteit Werkset kan worden gebruikt als leidraad bij een strategie voor de grootte van de residente set: 1. controleer de grootte van de werkset van elk proces 2. verwijder regelmatig pagina's uit de residente set van een proces die niet voorkomen in de residente set van een proces (vergelijkbaar met LRU) 3. een proces mag alleen worden uitgevoerd als zijn werkset zich in het hoofdgeheugen bevindt = als zijn residente set zijn werkset bevat => minder initiële paginafouten Beperkingen van de werksetbenadering: de toekomst kan niet worden voorspeld op basis van het verleden; zowel de grootte als de samenstelling van de werkset zullen na verloop van tijd veranderen het nauwkeurig meten van de werkset van ieder proces is onpraktisch want dit vereist een timestamp voor iedere paginaverwijzing van elk proces = nogal veel optimale waarde van Δ is onbekend en zal wisselen desalniettemin is de gedachte goed en daarom zijn er een aantal OS'en die het trachten te implementeren In plaats van de werksetgrootte rechtstreeks te bewaken kunnen er vergelijkbare resultaten gehaald worden door de frequentie van paginafouten te bewaken omdat, als de grootte van de residente set stijgt, dan daalt het aantal paginafouten. De werksetgrootte is een punt op een kromme (zie p404). => Ligt de foutfrequentie onder een bepaald minimum, dan is het beter voor het systeem om een kleinere residente set toe te wijzen aan een proces => Ligt de foutfrequentie boven een bepaald maximum, dan is het beter dat er een grotere residente set wordt toegewezen aan het proces Een algoritme die deze benadering volgt is pagina foutfrequentie. Dit vereist dat een use-bit verbonden is aan elke pagina in het geheugen. Bij toegang tot de pagina wordt die ingesteld op 1. Bij paginafout: registratie van de virtuele tijd sinds de laatste paginafout voor dat proces Er wordt een drempel F gedefinieerd. Is de tijd sinds de laatste paginafout < F => er is een fout opgetreden, sneller dan verwacht werd => er wordt een pagina toegevoegd aan de residente set van het proces; is die tijd > F, dan worden alle pagina's met een use-bit die gelijk is aan 0 verwijderd => residente set wordt kleiner en tegelijkertijd worden de use-bits van de resterende pagina's op 0 gezet. Deze strategie kan verfijnd worden door gebruik te maken van een minimum- en maximumdrempel om respectievelijk het verkleinen en het vergroten van de residente set te activeren De tijd tussen paginafouten is omgekeerd evenredig met de foutfrequentie. PFF heeft één groot nadeel: presteert niet goed tijdens overgangsfasen waarin een verschuiving plaatsvindt naar een nieuwe lokaliteit => veel paginafouten Benadering die probeert het fenomeen van overgangen tussen lokaliteiten op te lossen en die een relatief lage overhead heeft => Variable-interval Sampled Working Set Op basis van steekproef-tijdsinterval grootte van residente set aanpassen Gedurende tijdsinterval: pagina’s aan werkset toevoegen waarvoor paginafout optreedt -> Use bit op 1 bij verwijzing naar pagina tijdens tijdsinterval Op einde van tijdsinterval: alle pagina’s met use bit op 0 uit werkset verwijderen 3 parameters 1. M: minimumduur 2. L: maximumduur 3. Q: aantal paginafouten dat mag optreden 4. t >= L : schort proces op en controleer use bits t < L en Q paginafouten bereikt: t < M: wacht tot M, schort proces op en controleer use bits t >= M : schort proces op en controleer use bits Opschoon strategie een opschoonstrategie bepaalt wanneer een gewijzigde pagina moet worden weggeschreven naar het secundaire geheugen Twee mogelijkheden: vraagopschoning: een pagina wordt alleen weggeschreven wanneer die geselecteerd is voor vervanging precleaning: gewijzigde pagina's worden weggeschreven voordat hun frames nodig zijn => pagina's kunnen in batches worden weggeschreven Nadelen: vraagopschoning: het schrijven van een vervuilde pagina moet gekoppeld zijn aan het inlezen van een nieuwe pagina. Het processorgebruik kan afnemen omdat het proces dat de paginafout veroorzaakte moet wachten op twee paginaoverdrachten. precleaning: de overdrachtscapaciteit van het secundair geheugen is beperkt en mag niet worden verspild aan onnodig wegschrijven en het wegschrijven van een pagina die toch in het hoofdgeheugen blijft en nog eens gewijzigd wordt, dat is een onnodige schrijfbewerking geweest p407 een betere benadering is paginabuffering: schoon alleen pagina's op die kunnen worden vervangen en koppel de bewerkingen voor het opschonen en vervangen los. Pagina's worden in twee lijsten geplaatst: (on)gewijzigd. De pagina's in de gewijzigde lijst worden periodiek in batches weggeschreven. Een pagina in de lijst van de ongewijzigde pagina's wordt opnieuw gebruikt wanneer ernaar gerefereerd wordt en gaat verloren wanneer zijn frame aan een andere pagina wordt toegewezen. Toezicht op de procesbelasting dit heeft betrekking op het aantal processen dat resident is in het hoofdgeheugen, het zgn. niveau van multiprogrammering De strategie voor het beheer van procesbelasting is belangrijk voor de efficiëntie van het geheugenbeheer. Zijn er te weinig processen in het geheugen => de kans is groot dat deze processen allemaal geblokkeerd zijn en dat er veel tijd wordt gespendeerd aan swapping. Zijn er te veel processen, dan is de omvang van de residente set van de processen te klein => veel paginafouten => trashing Niveau van multiprogrammering Naarmate er meer processen worden ingeladen, hoe kleiner wordt de kans dat daar een geblokkeerd proces bij is (dus dat alle processen geblokkeerd zijn) waardoor het processorgebruik stijgt. Echter, vanaf een bepaald punt zijn er te veel processen wat ertoe leidt dat de gemiddelde grootte van de residente set te klein wordt => veel paginafouten => er moeten veel pagina's worden ingeladen uit virtueel geheugen => weinig echt processorgebruik Er is een algoritme dat dit probleem oplost: PFF: dit beheert impliciet de procesbelasting; alleen processen met een voldoende grote werkset mogen worden uitgevoerd Opschorten van processen wanneer het niveau van multiprogrammering worden verlaagd, dan moet één of meer van de residente processen worden opgeschort (uit het hoofdgeheugen worden weggeswapt); zes mogelijkheden: 1. proces met de laagste prioriteit 2. proces dat een paginafout veroorzaakt: er is een grotere kans dat de werkset van dit proces niet resident is => de prestaties zullen het minst lijden onder het opschorten van dit proces 3. Laatst geactiveerd proces: hierbij is de kans het grootst dat het geen residente werkset heeft 4. Proces met de kleinste residente werkset: dit vereist de kleinste toekomstige inspanning om het proces weer te laden. Het is echter nadelig voor programma's met een beperkte lokaliteit 5. grootste proces => bij een overvol geheugen onstaan hierdoor de meeste vrije frames waardoor extra inactiveringen in de nabije toekomst onwsl maakt 6. Proces met de grootste resterende uitvoeringstijd: dit neemt immers ook plaats in aangezien het nog even kan duren vooraleer het uit het hoofdgeheugen is verdwenen wanneer het volledig is uitgevoerd