• No results found

Proces-computers 2

N/A
N/A
Protected

Academic year: 2021

Share "Proces-computers 2"

Copied!
129
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

Proces-computers 2

Citation for published version (APA):

Rooda, J. E., & Boot, W. C. (1985). Proces-computers 2. (TH Eindhoven. Afd. Werktuigbouwkunde, Vakgroep Produktietechnologie : WPB; Vol. WPB0252). Technische Hogeschool Eindhoven.

Document status and date: Gepubliceerd: 01/01/1985

Document Version:

Uitgevers PDF, ook bekend als Version of Record

Please check the document version of this publication:

• A submitted manuscript is the version of the article upon submission and before peer-review. There can be important differences between the submitted version and the official published version of record. People interested in the research are advised to contact the author for the final version of the publication, or visit the DOI to the publisher's website.

• The final author version and the galley proof are versions of the publication after peer review.

• The final published version features the final layout of the paper including the volume, issue and page numbers.

Link to publication

General rights

Copyright and moral rights for the publications made accessible in the public portal are retained by the authors and/or other copyright owners and it is a condition of accessing publications that users recognise and abide by the legal requirements associated with these rights. • Users may download and print one copy of any publication from the public portal for the purpose of private study or research. • You may not further distribute the material or use it for any profit-making activity or commercial gain

• You may freely distribute the URL identifying the publication in the public portal.

If the publication is distributed under the terms of Article 25fa of the Dutch Copyright Act, indicated by the “Taverne” license above, please follow below link for the End User Agreement:

www.tue.nl/taverne

Take down policy

If you believe that this document breaches copyright please contact us at:

openaccess@tue.nl

(2)

Auteurs: Prof.dr.ir. J.E. Rooda Ir. W.C. Boot

(3)

Dit boek is voortgekomen ult een collegedictaat bij het vak Proces-computers 2, zoals dat wordt gegeven aan derdejaars studenten werktuig-bouwkunde aan de Technische Hogeschool Twente. Het doel van het boek is de lezer vertrouwd te maken met het gebruik van computers voor de besturing van zich buiten de computer afspelende processen ("real time process control").

Dit boek is, ter onderscheid van het boek "Procescomputers, basis-begrippen" [Rooda, Boot, 1984], met name bedoeld voor de besturing van complexe processen. Evenals in "Procescomputers, basisbegrippen" wordt in dit boek gebruik gemaakt van een hogere programmeertaal (Modulair Pascal) voor het beschrijven van de algorithmen. Daarnaast wordt gebruik gemaakt van (quasi-)parallelle processen.

Na een inleiding over de begrippen proces en interactie wordt uitvoerig ingegaan op de synchronisatie van parallelle processen. Als basis voor de synchronisatie worden de semaphoren [Dijkstra, 1965] en de conditionele kritieke secties [Brich, Hansen, 1972; Hoare, 1972] uitvoerig behandeld. Vervolgens wordt de implementatie van processen en semaphoren op een eeo-proces machine toegelicht. Tevens wordt uitvoerig ingegaan op de synchronisatie van interne- en externe processen, waarbij begrippen als polling en interrupt worden behandeld.

Aao de orde komt tevens het gebruik van excepties voor het schrijven van zogenaamde robuuste programma's.

Tevens worden verschillende aspecten als de tijd en de in- en uitvoer van computer randapparaten behandeld. Tenslotte wordt een aantal cases behandeld waarbij de eerder ontwikkelde concepten nader zullen worden geillustreerd. Voor lezers die niet bekend zijn met de taal Modulair Pascal wordt verwezen naar Rooda, Boot (1984).

Wij zijn dank verschuldigd aan ire T.J. Rossingh voor de implementatie van de behandelde concepten op de beschikbare computers, aan ir. R. Overwater voor zijn bijdrage over de ontwerpmethode voor het vervaardigen van software en aan ir.J.H.A. Arentsen voor zijn bijdrage over het voorbeeld van een stapelaar.

Enschede I Eindhoven 1985

J.E. Rooda W.C. Boot

(4)

HOOFDSTUK 1 HOOFDSTUK 2 2.1 2.2 2.3 HOOFDSTUK 3 HOOFDSTUK 4 4.1 4.2 4.3 4.4 HOOFDSTUK 5 5.1 5.2 5.3 HOOFDSTUK 6 INLEIDING

DAISY (DESIGN AND ANALYSIS OF INDUSTRIAL SYSTEMS) HET PROCESS INTERACTION DIAGRAM • • • • • • • 2-1 DE DATA DICTIONARY • • • • • • • • • • • 2-3 SLOTOPMERKINGEN •• • • • • • • • •• • • • • 2-4

PROCESSEN EN INTERACTIES

SYNCHRONlSATIE

SYNCHRONISATIE TUSSEN INTERNE PROCESSEN SEMAPHOREN • • • • • • • • • •

CONDITIONELE KRITIEKE SECTIES • • • • • SYNCHRONISATIE TUSSEN INTERNE- EN EXTERNE

. . . 4-1 • • • • • 4-5

• 4-9

PROCESSEN • • • • • • • • • • • • • • • • 4-12

IMPLEMENTATIE VAN PROCESSEN EN SYNCHRONISATIES

PROCESSEN • • • • • • • • • • • • • • • • • • • • 5-1 SYNCHRON I SAT IE TUSSEN INTERNE PROCESSEN • • • • • 5-4 SYNCHRONISATIE TUSSEN INTERNE- EN EXTERNE

PROCESSEN • • • • • • • • • • • • • • • • • • 5-5 EXCEPTIES 6.1 EXTERNE EXCEPTIES • • • • • • • • • • • • • • • • 6-5 HOOFDSTUK 7 HOOFDSTUK 8 8.1 8.2 HOOFDSTUK 9 9.1 9.2 9.3 TIJDASPECTEN

TERMINAL INVOER EN UITVOER EEN COMMANDO INTERPRETATOR • PROGRAMMA TRACING •• • • STAPELAAR •• 8-8 • • • • • . . 8-9 ORIENTATIEFASE • • • • • 9-1 ONTWERPFASE • • • • • • • • • • • • • • • • • • • 9-1 BOUWFASE • • • • • • • • • • • • • • 9-8

(5)

HOOFDSTUK 10 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 HOOFDSTUK 11 APPENDIX A APPENDIX B B.l B.2 B.3 TREINBESTURING

INTERFACES TUSSEN COMPUTER EN SPOORBAAN De hardware interface

De software interface

HET BESTURINGSPROBLEEM •

.

.

.

.

.

. .

Besturing voor eenrichtingsverkeer •

Besturing voor eenvoudig tweerichtingsverkeer Besturing voor complex tweerichtingverkeer • •

LITERATUUR

ROSKIT QUICK REFERENCE MANUAL

TREIN PROGRAMMATUUR EENRICHTINGSVERKEER • • • • • EENVOUDIG TWEERIGHTINGSVERKEER • COMPLEX TWEERICHTINGSVERKEER • • • 10-1 10-3 10-4 10-6 10-6 10-9 10-13 • B-3 • B-8 B-15

(6)

INLEIDING

In de vorige eeuw onstond de mogelijkheid om door middel van mechanisch aangedreven werktuigen de menselijke- en dierlijke arbeid te verlichten. Een belangrijk probleem hierbij was het doelmatig gebruik van de beschikbare krachten. De besturingstechniek was geboren.

In het begin betrof de besturingstechniek regelingen gebaseerd op mechanische technieken. Op het punt van continue regeling kan bijvoor-beeld de regulateur op stoommachines van James Watt (1782) worden genoemd, welke het toerental van de machine regelde. Een belangrijke vorm van discrete besturing was de nokkenas.

Later vindt men besturingen die pneumatisch, hydraulisch of electrisch (met relais) zijn uitgevoerd. De keuze hangt vaak samen met de gebruikte krachtbron. Met deze technieken is het mogelijk om tamelijk gecompliceerde werktuigen te besturen.

Door de opkomst van de elektronica. en met name van de micro-processor ontstaan nieuwe mogelijkheden. De vrije programmeerbaarheid van de hier· mee uitgeruste computers, en de daarmee verkregen flexibiliteit, vormt een belangrijke vooruitgang. Toepassing van deze apparatuur vindt men op steeds meer terreinen. Enkele zijn de besturing van automaten in flexibele fabricage systemen en de besturing van raffinageprocessen in de petro-chemische industrie. Oak worden steeds meer wetenschappelijke experimenten op deze wijze bestuurd.

Karakteristiek voor dit soort gebruik van micro-processoren is het zoge-naamde real-time aspect. Anders dan bij het gebruik voor administratieve of omvangrijke wetenschappelijke be rekenin gen is de reaktietijd van doorslaggevend belang. Sommige besturingstaken kunnen onmogelijk wachten totdat de computer even tijd heeft.

De flexibiliteit en de geringe omvang van micro-processoren maakt dat de hardware vrijwel geen bepcrking meer oplegt aan de mogelijkheden. Daar-door is het mogelijk om problemen met steeds toenemende omvang aan te pakken. Ret probleem hierbij ligt in de ontwikkeling van de benodigde programmatuur. Deze ontwikkeling loopt hoofdzakelijk via twee lijnen.

V~~r discrete besturingen is met name de PLC (Programmable Logic

Controller) zeer populair. In wezen is dit een electronische uitwerking van de mogelijkheden die relais bieden. Dit koppelt het voordeel van de programmeerbaarheid aan de bestaande kennis van besturingstechnieken met relaia. Van lieverlee zijn ook meer algemene faciliteiten beschikbaar

(7)

gekomen binnen PLC's. Aan het gebruik van FLC's kleeft echter een twee-tal belangrijke nadelen. In de eerste plaats sluit de wijze van programmeren vrij slecht aan op de moge1ijkheden die micro-processoren bieden. De pogingen om dit te verbeteren 1eiddeo tot het tweede oadeel: de meer geavanceerde uitbreidingen zijo 1astig te programmeren. doordat het compatibel moet zijo met de oude programmeerprincipes. Kortom, voor grote problemen zijn PLe's ofwel niet toereikend qua mogelijkheden, of weI zijn ze te moei1ijk programmeerbaar.

De tweede 1ijn van programmering loopt via de general-purpose computers. Dit boek zal hoofdzake1ijk voortgaan op deze lijn.

In de zeveotiger- en begin tachtiger jaren zijn beheers- of besturings-systemen (operating systems) ontwikkeld die deze computers geschikt maken voor real-time procesbesturing. Ze bieden de gebruiker een vriendelijke programmeeromgeving en zorgen ervoor dat de hardware van het computersysteem zo efficient moge1ijk wordt gebruikt. Bekende voorbeelden van real-time besturingssystemen zijn RT11 en RSX11M van Digital Equipment Corporation. Daarnaast zijn hogere programmeertalen ontwikkeld die het mogelijk maken om programmadelen parallel of quasi-parallel uit te voeren. Bekende voorbeelden van zu1ke talen Z1JO Simu1a67 [Nygaard, Dahl, 1978], Bliss [Wu1f et al., 19711, Algo168 [van Wijngaarden, 1976], Modula-2 [Wirth, 19821. Smallta1k [Goldberg, Robson, 1983]. Een overzicht van talen met de faciliteiten die deze talen bieden wordt gegeven door Andrews en Schneider (1983).

Een nadeel van deze "confectie-systemen" is dat ze of te weinig faciliteiten bieden voor een handzaam gebruik, of te veel mogelijkheden bezitten waardoor ze zo omvangrijk zijn dat men door de bomen het bos niet meer ziet. Bovendien beperken ze vaak de mogelijkheden om nieuwe concepten toe te passen, waardoor de programma's eleganter zouden kunnen worden geschreven.

Deze gedachten hebben geleid tot de ontwikke1ing van een klein beheers-systeem dat de juiste faciliteiten biedt om elegante programma's te kunnen schrijven en dat qua omvang past op kleine computersystemen. Ret is geschreven in de vorm van een "gereedschapskist" waarin aIleen de meest noodzakelijke gereedschappen aanwezig zijn. Zonodig kan de gebruiker hiermee zelf nieuwe gereedschappen vervaardigen.

Het blijkt dat deze basisgereedschappen verschil1ende concepten, die samenhangen synchronisatie, interrupt, exceptie, tijd en leggen.

erg met

in-geschikt zijn om begrippen als proces, en uitvoer, uit te

Voor de beschrijving van de a1gorithmen zal gebruik worden gemaakt van Modulair Pascal [Bron, 1982]. Dit is een uitbreiding van het door Wirth ontwikkelde Pascal [Jensen, Wirth, 1975]. Het te gebruiken real-time besturingssysteem ROSKIT is eveneens geschreven in deze taal. Ret is opgezet aan de RUG [Rebbink, 1984] en verder uitgewerkt aan de TRT

[Rossingh, Rooda, 19841.

Verondersteld wordt dat de 1ezer kennis heeft van de basisbegrippen betreffende procescomputers, zoals centrale verwerkingseenheid,

(8)

geheugen, randapparaten, polling en interrupt. Daarnaast wordt ervan uitgegaan dat de lezer over een redelijke kennis van Modulair Pascal beschikt. Een boek dat goede aansluiting biedt is Rooda, Boot (1984). Andere beheerssystemen komen niet aan de orde.

wordt hiervoor verwezen naar Peterson en inmiddels klassiek boek dat de fundamenten van is Lister (1979). Een uitvoerige bibliografie geeft Bell et al. (1983).

De geinteresseerde lezer Silberschatz (1983). Een beheerssystemen bespreekt over parallelle processen

Verwijzingen nsar de alfabetisch gerangschikte literatuurlijst zijn van de vorm auteur (jaar) of [auteur, jaar].

De bij een eerste lezing minder belangrijke tekstdelen zijn geplaatst tussen [[ en ]]. Veelal hebben ze betrekking op de implementatie van de verschillende begrippen.

(9)
(10)

DAISY (DESIGN AND ANALYSIS OF INDUSTRIAL SYSTEMS)

Bij het ontwerpen en analyseren van systemen blijkt steeds weer dat de communicatie tussen de toekomstige gebruiker en de ontwerper van het systeem slechts moeizaam verloopt. Dit is niet zo verwonderlijk, omdat beiden een verschillende "taal" spreken. De gebruiker weet precies wat zijn systeem moet gaan doen en is geinteresseerd in het uiterlijk van het systeem. De ontwerper daarentegen weet precies hoe een systeem moet worden gemaakt en denkt vanuit het innerlijk van het systeem. DAISY is ontwikkeld met het doel deze communicatiekloof te overbruggen.

DAISY staat voor Design and Analysis of Industrial SYstems. DAISY is een gestructureerde techniek voor het ontwerpen en analyseren van software en hardware van industriele systemen. Het doel van een gestructureerde techniek is tweeledig. Een dergelijke techniek moet niet aIleen de communicatie tussen ontwerper en gebruiker vergemakkelijken, maar maet tevens de complexiteit van een (te ontwerpen) systeem hanteerbaar maken. Beide aspecten beinvloeden de kwaliteit van het systeem. Voor dit doel biedt een gestructureerde techniek een denkwijze en een of meer gereedschappen (tools) die deze denkwijze ondersteunen.

De denkwijze die door DAISY wordt gehanteerd is de proces interactie benadering. In het hoofdstuk Processen en Interacties is reeds uit-gebreid op deze benadering ingegaan. De tools van DAISY zijn het PRocess INteraction Diagram (PRIND) en het Data Dictionary (DD). In het navolgende zullen deze gereedschappen nader worden beschouwd.

2.1 HET PROCESS INTERACTION DIAGRAM

Eeo Process Interaction Diagram (PRIND) is een grafische representatie van een systeem, dat de processen in dat systeem toont tezamen met de interacties tussen deze processen. Bij ieder PRIND behoort een Data Dictionary (DD), waarin de processen en interacties zijn gedocumenteerd. Figuur 1 laat een PRIND zien van een stapelsysteem, waarin dozen op pallets worden gestapeld. In het systeem zijn vier processen te herkennen, een aanvoerProces, een stapelProces, een afvoerProces en een besturingsProces. In een PRIND worden processen met bollen aangeduid en interacties met pijlen. AIle processen en interacties hebben een naam ter identificatie. In figuur 1 zijn tevens de interacties met processen in de omgeving opgenomen (dozenln, leegPallet, volPallet).

(11)

Iedere interactie kent een mechanisme via welke de samenwerking tussen de processen tot stand komt. Er worden vier basismechanismen onder-scheiden: het synchrone mechanisme, het asynchrone mechanisme, het interrupt meehanisme en het continue mechanisme. Met behulp van deze mechanismen kunnen 'objecten' van het ene naar het andere proces worden overgedragen. V~~r dit doel is ieder meehanisme uitgerust met een zend-achtige (5-) aetie en een ontvang-zend-achtige (R-) actie. Objecten kunnen al dan niet leeg zijn en zijn niet noodzakelijk fysiek van aard. Zij kunnen evengoed een data- of een signaal-achtig karakter hebben.

Het synchrone mechanisme kan worden toegepast om een precieze afstemming tussen processen te bewerkstelligen. Met behulp van dit mechanisme wordt een proces 'getriggered' door een aoder proces. Een voorbeeld hiervan is het geven van een startschot of het aflopen van een wekker. Een ontvangend proces zal aIleen op dit 'object' reageren als het daarop staat te wachten. Is het proces reeds actief dan sorteert het object geen enkel effect. In dit mechanisme is het versturen van een object de S-actie, het opvangen ervan de R-actie.

Het asynchrone meehanisme is uitgerust met een bufferfunctie. Hierdoor is het mogelijk processen onafhankelijk van elkaar in de tijd te laten verlopen. Objecten die naar een proces worden verstuurd, worden in de buffer opgeslagen (de S-actie) en eruit gehaald op het moment dat het proces eraan toe is (de R-actie). De R-actie impliceert dat het uit-voerende proces op aanvoer moet wachten als de buffer Ieeg is. Een goed voorbeeld van dit mechanisme zijn semaforen. De v-operatie komt overeen met een S-actie en de p-operatie met een R-actie. Het object dat wordt overgezonden is leeg. Dit Iaatste blijkt uit het feit dat aIleen het aantal objecten in de buffer (de integer waarde) een rol speelt.

Het interrupt-mechanisme geeft een proces de mogelijkheid een ander proces te onderbreken. Na ontvangst van een object reageert het ontvangende proces door een zogenaamde interrupt-routine af te werken. Daarna wordt het onderbroken werk hervat. Voor het interrupt-mechaoisme maakt het niet uit of het te onderbreken proces staat te wachten of actief is. Het gebruik van de telefoon illustreert dit mechanisme. Door iemand op te bellen wordt een S-actie uitgevoerd. Bij het overgaan van de telefoon reageert de aoder door zijn werk te onderbreken en de telefoon op te nemen. Dit is de R-actie. De interrupt-routine bestaat uit het afhandelen van het gesprek. Na afloop van het gesprek wordt het werk hervat.

Het continue mechanisme verschilt in een belangrijk opzicht van de drie voorgaande mechanismen. Volgens dit mechanisme worden objecten voort-dureod overgestuurd, waardoor een onafgebroken stroom van objecten naar een proces ontstaat. V~~r het ontvangende proces speelt hierdoor de beschikbaarheid van een object geen rol meer. Het is dan oak zinloos 'lege' objecten te versturen. Bij dit mechanisme gaat het om de inhoud van de objecten. De stroom van objecten kan 'statisch' worden voor-gesteld als een dataveld, waarin een waarde is opgeslagen. Een S-actie betekent dan het overschrijven van die waarde, eeo R-actie het lezen ervan.

Uft het bovenstaande blijkt dat objecten een dubbele functie in een mechanisme vervullen. Ten eerste is er de 'signaal'-functie, waarbij de aanwezigheid van een object bepalend is voor het verloop van het ontvangende proces. Op deze wijze maken de eerste drie mechanismen van

(12)
(13)

de objecten gebruik. Ten tweede is er de 'informatiedrager'-functie, waarbij de inhoud van het object invloed heeft op het verloop van het ontvangende proces. Het continue mechaoisme maakt noodzakelijk van deze functie gebruik, de andere mechanismen hebben de mogelijkheid dit te doen.

In een PRIND kunnen de pijlen met een kleur worden weergegeven am aan te duiden welk mechanisme wordt bedoeld. Een andere mogelijkheid is het type mechanisme met een letter (resp. S,A,I,e) bij de pijl aan te geven. DAISY biedt de mogelijkheid am een set van identieke processen met slechts een bol weer te geven. Het aantal betrokken processen wordt in de bol tussen rechte haken aangegeven.

Op dezelfde manier kan een set van identieke interacties worden gerepresenteerd door een enkele pijl. Het betreffende aantal wordt oak hier tussen rechte haken aangeduid.

Om beide constructies te illustreren wordt verondersteld dat het stapel-systeem is uitgerust met twee aanvoerprocessen. In dat geval kunnen de aanvoerprocessen en de bijbehorende interacties worden weergegeven zoals in figuur 2.

Iedere bol kan worden uitgewerkt tot een nieuw PRIND met dezelfde naam als die bal. Op deze manier kan een hele boom van PRIND's worden opgebouwd. De hierarchie van de boom kan worden gebruikt om de systeem-hierarchie aan te duiden, maar kan tevens een modulaire of een top-down structuur aangeven. Ieder PRIND legt de context vast voor de bollen die erin opgenomen zijn. Dit principe van uitwerken wordt getoond in de figuren 3 en 1. Eerst ken het stapelsysteem globaal worden bescbouwd (figuur 3). Hierin worden de interacties met de omgeving vastgelegd. Daarna kan bet systeem verder worden uitgewerkt (figuur 1).

Het genereren van PRIND's moet stoppen als het mogelijk is am aIle processen in sequentiele routines te beschrijven.

Het zal duidelijk zijn dat, omwille van de integriteit, er bij het uitwerken van een bol geen andere interacties het nieuwe PRIND mogen binnengaan of verlaten anders dan de interacties die de uit te werken bol blnnengaan of verlaten.

Als de bol 'stapelProces' aIleen via 'dozen' interactie beeft met de omgeving, dan mag zljn PRIND geen interacties aanduiden via zowel

'dozen' als 'bakken'.

2.2 DE DATA DICTIONARY

Tot nu toe is er nag niets gezegd over de documentatie van het systeem. De Data Dictionary (DD) is een gereedschap dat voor dit doel bedoeld is. Bij ieder PRIND hoort een DD met dezelfde naam.

Het DD valt in twee delen uiteen: 1. de proces data,

2. de interactie data.

(14)

Deze gegevens kunnen met behulp van een pseudo-code of programmeertaal worden vastgelegd.

De interactie-data geven de namen van de interacties en hun type. Voor de beschrijving van deze data kan eveneens een pseudo-code of programmeertaal worden gebruikt.

Het gebruik van een programmeertaal voor het beschrijven van de proces-en interactie-data bledt het voordeel dat deze gegevproces-ens beknopt proces-en ondubbelzinnig kunnen worden vastgelegd. Een tweede voordeel is dat de documentatie reeds grote delen van het beoogde simulatie- en/of besturingsprogramma bevat. Daardoor kan de programmeertijd aanzienlijk worden verkort.

Ter illustratie voIgt hierooder een beschrijving in pseudo-code van het besturingsProces in het stapelsysteem. In deze beschrijving is veronder-steld dat een stapelOrder aangeeft hoeveel dozen op een pallet moeten worden gestapeld. Tevens is er van uit gegaan dat het stapelProces tlweet" hoe een doos moet worden gestapeld en hoe een pallet moet worden gepakt. PROCESS besturing : BEGINPROC SEND nextPallet; LOOP RECEIVE palletReady; RECEIVE stapelOrder; FOR aantalDozen DO BEGIN SEND nextDoosj RECEIVE doosReady END; SEND orderReady; SEND nextPallet END ENDPROC; 2.3 SLOTOPMERKINGEN

Uit het voorbeeld blijkt duidelijk de scheiding tussen interne- en ex-terne processen. Het besturingsProces verloopt intern, de overige processen extern. In de hierboven gegeven procesbeschrijving kunnen de meeste S- en R-acties worden opgevat als respectievelijk v- en p-operaties op semaforen. AIleen voor de interacties stapelOrder en orderReady gaat dit niet op, omdat in deze gevallen het verstuurde object niet leeg is.

DAISY biedt de mogelijkheid van interactief gebruik op een computer. Er is een software pakket ontwikkeld, dat een data base, grafische faciliteiten en een editor biedt [Mulder, 1984]. Met behulp van de editor kunnen PRIND's op een kleurenbeeldscherm worden getekend. Hele PRIND-structuren, waaronder verschillende ontwerpvarianten, kunnen op

(15)

die manier worden gebouwd en opgeslagen. Deze computerondersteuning geeft de ontwerper de mogelijkheid om op gestructureerde wijze aan complexe systemen te werken.

In dit hoofdstuk is kort ingegaan op de concepten achter DAISY. Voor een uitgebreidere beschrijving wordt verwezen naar Overwater (1985a,b) en Overwater en Roods (1985).

(16)

PROCESSEN EN INTERACTIES

De procescomputer ontleent zijn naam aan het feit dat hij wordt gebruikt om processen te besturen.Processen kunnen zeer uiteenlopend van aard zijn. Gedacht kan worden aan bijvoorbeeld het vullen van een melkfles of het roteren van de pols van een robotarm. Proces wordt hier gebruikt in de zin van een reeks acties, die herhaald wordt uitgevoerd. De uitvoering is sequentieel. Dit houdt in dat binnen een cyelus aeties altijd in dezelfde volgorde worden uitgevoerd. Tevens kunnen de acties elkaar nooit in de tijd overlappen. WeI kan een aantal van de aeties voorwaardelijk zijn, zodat zij in sommige eycli weI en in andere niet worden uitgevoerd.

Praktische systemen zijn vrijwel altijd te beschouwen als opgesplitst in een aantal processen, die zich gelijktijdig (parallel) afspelen. Gezien vanuit de computer spelen deze processen zich extern af. Ze zullen daarom verder worden aangeduid als ext erne processen.

Met een proces is een toestand geassocieerd. Implieiet bevat deze informatie omtrent de voortgang van het proces. Daarnaast kan expliciet informatie aanwezig zijn ten behoeve van de uit te voeren acties.

In het algemeen zal een proces voor z1Jn voortgang mede afhankelijk zijn van andere processen. Er is sprake van interactie tussen de processen. Hierbij is een tweetal situaties te onderscheiden:

- Een proces moet in een bepaalde toestand zijn voordat een ander proces kan voortgaan. De interactie regelt de volgorde op een kritiek punt. Men spreekt van conditie synchronisatie.

- De voortgang van een proces hangt af van een beperkt besehikbaar middel. De interactie bepaalt dat niet meer processen kunnen voortgaan dan er van het middel beschikbaar is. De volgorde is in principe niet van belang. Men spreekt van wederzijdse uitsluiting.

Aangezien een proces niet zondermeer toegang heeft tot de toestand van een ander proces, is het nodig deze interactie tussen processen expliciet te maken. Conditie synchronisatie wordt doorgaans gerealiseerd door de overdracht van informatie van het ene proces naar het andere. Wederzijdse uitsluiting is te realiseren door inspectie van de beschik-ba re hoe vee lheid midde l€'o.

(17)

programma aanwezig zijn. In het geval dat men gebonden is aan eeo (cyclisch) programma zijn deze programma deleD sterk vervlochten. Binnen de cyclus dient immers met aHe mogeUjk optredende situaties rekening te worden gehouden. Het zal duidelijk zijn dat dit de overzichtelijkheid niet ten goede komt.

Dit kan worden verholpen door, in analogie met het "opdelen II van de

werkelijkheid in processen, ook het besturingsprogramma te splitsen in een aantal processen. Hierdoor kan afstand worden genomen van het strikt sequentiele karakter van programma's. Processen zijn weliswaar zelf sequentieel, maar meerdere processen kunnen zich gelijktijdig afspelen. In analogie met de externe processen zullen deze worden aangeduid als interne processen.

In beperkte mate voorziet het interrupt mechanisme in deze behoefte. Interrupt routines worden immers als het ware parallel aan het eigenlijke programma uitgevoerd. Aan het gebruik hiervan kleeft echter een aantal belangrijke nadelen, waardoor de bruikbaarheid wordt beperkt. Andere methoden am echt- of quasi-parallelisme te realiseren zijn nodig. Met de introductie van de interne processen worden de interacties uitgebreid met interacties tussen interne processen onderling en tussen interne- en externe processen.

Binnen dit concept van processen en interacties is een hoofdproblemen te onderscheiden:

- De keuze van (interne) processen.

tweetal

- De realisatie van een probleemloze interactie tussen de diverse processen.

Met betrekking tot het eerste punt is op het moment nog weinig gefundeerd te zeggen. Het keuzeprobleem valt nag grotendeels onder de kunst van het programmeren. Door het boek heen zal met voorbeelden worden getracht hiervan een indruk te geven.

Ten aanzien van de interactie is, met name vanuit de informatica, weI het nodige bekend. De volgende twee hoofdstukken zullen ingaan op respectievelijk de interactie tussen interne processen onderling en tussen interne- en externe processen.

Voor de declaratie van processen zal de volgende notatie worden gebruikt:

PROCESS <naam> ( <parameterlijst> ); BEGINPROC

<body> ENDPROC;

In tegenstelling tot de genoemde karakteristiek dat processen altijd cyclisch zijn, wordt hierbij verondersteld dat een procea is afgelopen bij het bereiken van ENDPROC. Een cyclisch proces heeft dan de vorm:

PROCESS <naam> ( <parameterlijst> ); BEGINPROC

LOOP <body>

(18)

END ENDPROC;

De aanroep van een proces gebeurt met:

start( <naam> «actuele parameters>

»;

Ret effect hiervan is dat het proces nu parallel wordt uitgevoerd met het aanroepende proces. In deze zin is ook het hoofdprogramma zelf een proces.

(19)

SYNCHRON I SAT IE

In dit hoofdstuk wordt ingegaan op de synchronisatie van (interne) processen onderling en van de synchronisatie van interne- en externe processen.

4.1 SYNCHRONISATIE TUSSEN INTERNE PROCESSEN

Het probleem van de synchronisatie tussen (interne) processen zal aan de hand van een eenvoudig voorbeeld worden gedemonstreerd. Veronderstel dat het wenselijk is om bij de variabele x de waarde 3 op te tellen en de uitkomst af te drukken. Een mogelijkheid is twee processen te starten, waarvan de ene 1 optelt bij x en de andere 2 optelt bij x. Wanneer de processen hiermee klaar zijn kan het programma de uitkomst afdrukken. Een dergelijk programma zou de volgende basisvorm kunnen hebben

PROGRAM xPlus3 ( ••• ); VAR x: integer; PROCESS xPlusl; BEGINPROC x:+ 1 ENDPROC; PROCESS xPlus2; BEGINPROC x:+ 2 ENDPROC; BEGIN x:= 10; start(xPlusl)j start(xPlus2); outInt(x) END.

Het 1ijkt in eerste instantie redelijk te veronderste11en dat dit programma inderdaad het gewenste effect heeft en 13 afdrukt. Bij nadere

(20)

beschouwing blijkt er echter een tweetal problemen op te treden, waar-door niet valt te voorspellen of de afgedrukte waarde 10, 11, 12 of 13 zal zijn.

Ret eerste probleem is dat bij het statement "outlnt(x)" wordt aangenomen dat de processen xplusl en xPlus2 al zijn afgelopen. Omdat deze processen parallel aan het hoofdprogramma worden uitgevoerd hoeft dit echter niet zo te zijn. De volgende volgordes zijn denkbaar:

- x:+ 1 -

,

x:+ 2-

,

out lnt (x). Resultaat: 13. - x:+ 2-

,

x:+ 1 ; outInt(x). Resultaat: 13. - x:+ 2; outlnt(x) ; x:+ 1. Resultaat: 12. - x:+ 1 ; outlnt(x) ; x:+ 2. Resultaat: 11. - outlnt (x); x:+ 1 .

,

x:+ 2. Resultaat: 10. - outlnt(x); x:+ 2'

x:+ 1. Resultaat: 10.

Ret is dus nodig dat de processen xPlusl en xPlus2 aan het hoofdprogramma laten weten dat ze klaar zijn. Dit is het probleem van conditie synchronisatie. De voortgang van het hoofdprogramma is gebonden aan de conditie dat xPlusl en xplus2 klaar zijn. Een mogelijke oplossing hiervan is de volgende:

PROGRAM xPlus3 ( ••• ); VAR x: integer;

klaarl, klaar2: boolean; PROCESS xPlusl; BEGINPROC x:+ 1; klaarl:= true ENDPROC; PROCESS xPlus2j BEGINPROC x:+ 2; klaar2:= true ENDPROC; BEGIN x:= 10;

klaarl:= falsej klaar2:= false; start (xPlusl);

start(xPlus2);

REPEAT UNTIL klaarl AND klaar2; outlnt(x)

END.

Ret probleem is hier helaas maar ten dele mee opgelost. De uitkomst 10 kan nu niet meer voorkomen. De uitkomsten 11, 12 en 13 behoren echter nog steeds tot de mogelijkheden. Dit komt doordat elk van de statements die iets bij x optellen niet een ondeelbaar geheel vormen. Ret statement x:+ 2 zou bijvoorbeeld kunnen worden uitgevoerd door eerst een accumulator te laden met de waarde van x, vervolgens daar 2 bij op te tellen en uiteindelijk het resultaat terug te zetten. Door het parallellisme kunnen niet aIleen de statements in verschillende volgorden worden uitgevoerd, maar oak verschillende delen van

(21)

statements. De volgende volgorde zal bijvoorbeeld het resultaat 11 produceren:

1. xPlus2: Laad accu2 met x { accu1 11, accu2 10, x == 10 }

2. xPlus2: Tel 2 op bij accu2 { accu1 == 11, accu2 12, x == 10 }

3. xPlusl: Laad accul met x { accul 10, accu2 == 12, x == 10 }

4. xPlus2: Zet ace u2 weg { aceul 10, aceu2 12, x ::: 12 }

5. xPlusl: Tel 1 op bij accul { accul 11, accu2 ::: 11, x == 12 }

6. xPlusl: Zet accul weg { accul 11, aecu2 11, x == 11 }

Hierbij is aangenomen dat elk proces beschikt over een eigen accumulator. Een gemeensehappelijke accumulator zal het probleem in het algemeen aIleen maar groter maken.

De essentie van het probleem is dat beide processen op hetzelfde moment dezelfde variabele proberen te veranderen. De mogelijkheid om dat te doen kan worden beschouwd als een beperkt beschikbaar middel, waardoor wederzijdse uitsluiting noodzakelijk is. De beschikbaarheid van x om te kunnen worden veranderd moet nu inspecteerbaar worden gemaakt. Helaas is dit probleem aanzienlijk ingewikkelder dan het realiseren van conditie synchronisatie. Het probleem kan in essentie worden weergegeven door het volgende proces: PROCESS skelet; BEGINPROC LOOP nietKritiekeSectie; ingangsProtocol; krit iekeSec tie; llitgangsProtocol; nietKritiekeSectie END

ENDPROC;

In dit proces bevindt zich een kritieke sec tie die pas kan worden uitgevoerd indien geen ander proces zich in zijn kritieke sec tie bevindt. Om dit te realiseren zijn enige statements nodig voordat aari de kritieke sectie kan worden begonnen, het ingangsprotocol. Nadat het proces zijn kritieke seetie heeft verlaten, zijn wederom enige statements nodig om aan te geven dat het proces zijn kritieke sec tie heeft verlaten. Dit geeft een ander proees de gelegenheid om zijn kritieke sectie te betreden. De oplossing van dit probleem is zeer lastig. Het eerst bekende algorithme waarbij sprake is van twee processen is opgesteld door de Nederlander Th. J. Dekker [Dijkstra, 1965a]. Door Peterson (1981) is een algorithme opgesteld dat iets eenvoudiger is. De beschrijving van het het i-de proces, i= 0, 1, luidt:

(22)

PROCESS mutEx(i: integer); VAR j: num; BEGINPROC j:= 1 - i; { Proces 0: i { Proces 1: i LOOP 0; j 1; j = 1 }

o }

nietKritiekeSectie;

flag[iJ:= false; tum:= i;

REPEAT UNTIL flag[j] OR (tum = j); krit iekeSec tie;

fla g [i ] :

=

true; nietKritiekeSectie END

ENDPROC;

De variabele flag[il, i= 0, I, heeft initieel de waarde true. De variabele tum wordt geinitialiseerd met 0 of 1.

Het voorbeeld kan met behulp van de oplossing van Peterson als voIgt worden beschreven:

PROGRAM xPlus3( ••• ); VAR x: integer;

klaarl, klaar2, flagI, flag2: boolean; tum: 1..2;

PROCESS xPlusI; BEGINPROC

flagl:= false; tum:= 1;

REPEAT UNTIL flag2 OR (tum = 2); x:+ 1; klaarl:= true;

flagI:= true ENDPROC;

PROCESS xPlus2; BEGINPROC

flag2:= false; tum:= 2;

REPEAT UNTIL flagi OR (tum = 1);

x:+ 2; klaar2:= true; flag2:= true

ENDPROC; BEGIN

x:= 10j

flagl:= true; flag2:= true; tum:= 1 { of 2}j klaarI:= false; klaar2:= falsej

start(pl); start(p2)j

REPEAT UNTIL klaar1 AND klaar2; outlnt(x)

END.

Het wezenlijke van het probleem van wederzijdse uitsluiting is dat het testen en het zetten van een gemeenschappelijke variabele niet als

(23)

ondeelbare actie verloopt. Een proces test een variabele en voordat dit proces deze variabele ook heeft veranderd is er een ander proces dat hier tussen sluipt en de waarde van de geteste variabele of test of zet. Aldus ontstaat een situatie waarbij wederzijdse uitsluiting niet meer is gegarandeerd of waarbij de processen elkaars voortgang belemmeren (deadlock).

4.2 SEMAPROREN

Dijkstra (1965a) is de eerste geweest die het probleem van het deelbaar testen en zetten heeft onderkend. Rij heeft het opgelost door de introductie van zogenaamde semaforen.

Een semafoor (s) is een datastructuur die onder andere een niet-negatieve integer (val) bevat. Op een semafoor zijn twee operaties gedefinieerd:

- de procedure pes) voert uit het statement val:- lander de voor-waarde dat val altijd grater of gelijk 0 blijft. Dit kan ertoe leiden dat een proces dat p aanroept moet wachten.

- de procedure v(s) voert uit de ondeelbare operatie val:+ 1.

Een informele beschrijving van de operatoren voIgt hierna. Ret voor-voegsel ATOMIC geeft aan dat de functie of procedure ondeelbaar wordt uitgevoerd.

PROCEDURE p(VAR s: sema);

ATOMIC FUNCTION testAndDec(VAR i: integer): boolean; UGrn

IF

i>

0

THEN BEGIN i:- 1; testAndDee:= true END ELSE testAndDec:= false

E~;

BEGIN REPEAT UNTIL testAndDec(s.val) END; ATOMIC PROCEDURE v(VAR s: serna);

BEGIN s.val:+ 1 END;

Een informele besehrijving van de initialisatie van een semafoor is de volgende:

PROCEDURE iniSema(VAR semaVariabele: sema; iniVal: integer); BEGIN

semaVariabele.val:= iniVal

E~;

Ret probleem van de wederzijdse uitsluiting kan nu eenvoudig worden opgelost door voordat de kritieke see tie wordt betreden eerst een p-operatie uit te voeren, en bij verlaten van de kritieke sectie een v-operatie. De val-waarde van zo'n semafoor is altijd 0 of 1. Men spreekt daarom ook weI over binaire semafoor.

Het probleem van de conditie synchronisatie kan worden opgelost door nadat aan de conditie Is voldaan een v-operatle uit te voeren, en door

(24)

-te wach-ten op de vervulling van de conditie door een p-operatie uit -te voeren. De val-waarde van zo'n semafoor kan aIle niet-negatieve waarden aannemen. Men spreekt daarom in dit geval ook weI over algemene- of tel-semafoor.

Het voorbeeld kan met behulp van semaforen als voIgt worden beschreven: PROGRAM xPlus3( ••• );

VAR x: integer;

mutEx, klaar: sema; PROCESS xPlusl; BEGINPROC p(mutEx); x:+ 1; v(klaar); v(mutEx) ENDPROC; PROCESS xPlus2; BEGINPROC p(mutEx); x:+ 2; v(klaar); v(mutEx) ENDPROC; BEGIN x:= 10; iniSema(mutEx, 1); iniSema(klaar, 0); iniSema(klaar, 0); start(xPlusl); start(xPlus2); p(klaar); p(klaar); outInt(x) END.

In het volgende hoofdstuk zal naast redenen van elegantie en eenvoud nog een reden (wellicht de belangrijkste) worden gegeven waarom een oplossing met behulp van semaforen is gewenst.

Een klassiek voorbeeld van de synchronisatie van processen die op meer dan een semafoor staan te wachten is het volgende (Dijkstra, 1971): vijf filosofen zitten aan een ronde tafel. Iedere filosoof heeft voor zich een bordo Tussen elke twee borden ligt een york. In totaal zijn er dus vijf borden en vijf vorken. Het leven van iedere filosoof bestaat uit denken en eten van spaghetti. Het denken bestaat uit rustig zitten, terwijl het eten bestaat uit het tot zich nemen van spaghetti vanaf het bord met behulp van de beide vorken links en rechts naast hem. Nadat de filosoof is uitgegeten legt hij beide vorken op tafel. Twee naast elkaar gezeten filosofen kunnen dus nooit tegelijk eten. Het volgende algorithme poogt een oplossing te geven.

(25)

PROGRAM Plato( ••• ); CONST n

=

5;

TYPE forkNum

= O •• n - 1;

VAR fork: ARRAY [forkNum] OF sema;

PROCESS philosopher(left, right: forkNum); BEG INP ROC

LOOP think; p(fork[left]); p(fork[right]); eat; v(fork[left]); v(forklright]) END ENDPROC; VAR i: num; BEGIN

FOR i:= 0 TO n - 1 DO iniSema(fork[i], 1);

FOR i:= 0 TO n - 1 DO start(philosopher«i

+

n - 1) MOD n, i»;

E~.

Indien aIle filosofen tegelijk hun linker york pakken, dan zal het duidelijk zijn dat de voortgang van aIle filosofen is gebiokkeerd. Dit probleem staat bekend als deadlock. De oplossing is dus niet acceptabel. De volgende oplossing is door Dijkstra (1971) gegeven. Hoewel dit programma geen blokkering bevat is het niet onmogelijk dat een filosoof niet aan de beurt komt en alsnog de, hier letterlijke, hongerdood sterft. Dit staat bekend als starvation.

PROGRAM Plato( ••• ); CONST n = 5;

TYPE num = O •• n - 1;

VAR mutex: serna;

state: ARRAY [num] OF (thinking, hungry, eating); selfSem: ARRAY [num] OF sema;

PROCEDURE test(k: num); BEGIN

IF (state[(k

+

n - 1) MOD nJ

<>

eating) AND (state[k]

=

hungry) AND

(state(k + 1) MOD n1

<>

eating) THEN BEGIN

END;

state(k]:= eating; v(selfSem[k]) END

(26)

-PROCESS philosopher(w: num); BEGINPROC

LOOP think;

p(mutex); state[w]:= hungry; test(w); v(mutex); p(selfSem[w]) ;

eat;

p(mutex); state[w]:= thinking;

test«w +n - 1) MOD n); test«w

+

1) MOD n); v(mutex) END ENDPROC; VAR i: num; BEGIN iniSema(mutex, 1); FOR i:= 0 TO n - 1 DO BEGIN

state[i]:= thinking; iniSema(selfSem[i], 0) END;

FOR i:= 0 TO n - 1 DO start(philosopher(i»; END.

Een wat eenvoudiger oplossing is de volgende: de oneven genummerde filosofen proberen eerst de linker en de even genummerde de rechter vork te pakken (dus eigenlijk dezelfde).

Het karakteristieke van het fflosofen probleem is dat meerdere processen via dezelfde semaforen toe gang willen hebben tot hun eigen kritieke sectie. Verwisseling van de p-volgorde is dan vergelijkbaar met de p-operaties van de filosofen. Het volgende "programma" illustreert dit nog eens.

PROGRAM deadlock( ••• ); VAR mutI, mut2: sema;

PROCESS pI; BEGINPROC p(mut!) ;

·

..

,

p(mut2);

...

,

v(mut2); • • • J v(mutl) ENDPROC; PROCESS p2; BEGINPROC p(mut2);

.

· ..

,

p(mutl) ;

.

.

.

,

v(mutI);

·

..

,

v(mut2) ENDPROC;

(27)

BEGIN

iniSema(mutl, 1); iniSema(mut2, 1); start(p1); start(p2);

END.

4.3 CONDITIONELE KRITIEKE SECTIES

Ofsehoon semaforen voor zowel conditie synehronisatie als wederzijdse uitsluiting kunnen worden gebruikt zijn p- en v-operaties tamelijk onveilige primitieven die gemakkelijk aanleiding kunnen geven tot fouten. Zo moet bijvoorbeeld iedere kritieke sec tie worden betreden met een p en worden verlaten met een v op dezelfde semafoor. Vergeten van een p of een v heeft rampzalige gevolgen. Zo geeft verwisseling van een p met een v of omgekeerd geen wederzijdse uitsluiting meer. Door Brineh Hansen (1972) en Hoare (1972) is voorgesteld om een aparte taal-eonstruetie in te voeren, met andere woorden om de syntaxis van de taal uit brelden, om zodoende de kans op programmeerfouten te vermijden. Dit meehanisme is zowel van toepassing op eonditie synchronisatie als op wederzijdse uitsluiting.

In dit boek is gekozen voor het implementeren van het taaleoneept van Brinch Hansen met behulp van een drietal procedures voor het besehrijven van de eonditionele kritieke seetie. Het voordeel van de introduetie van deze procedures dat de taal niet hoeft te worden uitgebreid. Het nadeel is dat deze primitieven dezelfde onveiligheid met zieh meebrengen als de semaforen.

De procedure iniCer(VAR c: ecr) initialiseert de cere De procedure enterCcr(VAR c: ccr) markeert het begin van de kritieke seetie. De procedure awaitCcr(VAR e: ecr; FUNCTION b: boolean) bepaalt de plaats waar de conditie b wordt getest. De procedure leaveCcr(VAR e: ecr) markeert het einde van de kritieke see tie. Deze notatie is ontleend aan Bron (1975).

PROGRAM Bron( ••• ); CONST n

=

?;

VAR v: ee r;

PROCESS pr(i: num);

FUNCTION cond: boolean; BEGIN BEG INP ROC

LOOP enterCer(v) ; kritiekeSectieDeell; awaitCcr(v, cond); kritiekeSectieDee12; leaveCcr(v) ; nietKritiekeSectie END ENDPROC; 20

-...

,

eond:= ••• END;

(28)

VAR k: num; BEGIN

iniCcr(v) ;

FOR k:= 0 TO n - 1 DO start(pr(k»; END.

Een mogelijke besehrijving van de eonditionele kritieke seeties in termen van semaforen is de volgende [Bron, 1975; Rossingh, Rooda, 1984].

TYPE ce r = RECORD

mutexLow, mutexHigh, wait: sema; waiting, ready: integer

END;

De semafoor mutexLow bepaalt de toegang tot de kritieke see tie via enterCer. De semafoor mutexHigh bepaalt de toegang tot de kritieke sec tie via awaitCcr. Deze twee semaforen garanderen dat sleehts een proces zieh in de kritieke sec tie kan bevinden. Processen die waehten in awaitCer hebben voorrang boven processen die waehten in enterCcr (deze keuze is arbitrair). De semafoor wait kan worden besehouwd als een rij van processen die waehten op een toestandsverandering in de kritieke seetie. Indien een proces de kritieke sec tie verlaat door aanroep van leaveCer of door aanroep van awaitCer, dan worden aIle processen die wachten via de semafoor wait doorgestart. Deze processen gaan waehten op de semafoor mutexHigh. De variabele waiting geeft aan het aantal processen dat in wait waeht. De variabele ready geeft aan het aantal processen dat op toegang tot de kritieke seetle via de semafoor mutexHigh waeht.

Een eer variabele wordt geinitialiseerd met de volgende procedure: PROCEDURE iniCcr(VAR e: eer);

BEGIN WITH e DO BEGIN END; iniSema(mutexLow , 1); iniSema(mutexHlgh, 0); iniSema(wait , 0); waiting:= OJ ready:=

a

END

Een kritieke seetie wordt betreden door mlddel van de volgende procedure aanroep:

PROCEDURE enterCcr (VAR e: cer); BEGIN p(e.mutexLow) END;

Binnen een kritieke seetle kan op het optreden van een bepaalde eonditie worden gewaeht door aanroep van de volgende procedure:

(29)

PROCEDURE awaitCer(VAR e: eer; FUNCTION b: boolean); BEGIN WITH e DO BEGIN END; WHILE waiting> 0

{Transporteer aIle waehtende processen in wait naar mutexHigh}

DO BEGIN

waiting:- 1; ready:+ 1; v(wait)

END;

WHILE NOT b DO BEGIN

END

waiting:+ 1;

IF ready > 0 {Er waehten processen op mutexHigh} THEN BEGIN ready:- 1; v(mutexHigh) END

ELSE v{mutexLow); p(wait); p(mutexHigh) END

De kritieke see tie wordt verlaten door middel van de volgende procedure aanroep:

PROCEDURE leaveCer(VAR e: eer); BEGIN

WITH e DO BEGIN

WHILE waiting> 0

{Transporteer aIle waehtende processen in wait naar mutexHigh}

DO BEGIN

waiting:- 1; ready:+ 1; v(wait) END;

IF ready > 0 {Er waehten processen op mutexHigh} THEN BEGIN ready:- 1; v(mutexHigh) END

ELSE v(mutexLow) END

END;

Indien de procedure awaitCcr niet wordt enterCer(e )-leaveCer(c) gelijkwaardig aan v(c.mutexLow). In zo'n geval verdient het de plaats van de eer te gebruiken.

gebruikt is het paar het paar p(c.mutexLow)-voorkeur de semafoor in

Ter illustratie van het gebruik van eonditionele kritieke see ties waar-bij zowel sprake is van wederzijdse uitsluiting als van eonditie syn-ehronisatie voIgt hieronder de uitwerking van het fiIosofen-probleem met behulp van conditionele kritieke seeties.

PROGRAM Plato( ••• ); CONST n = ?;

TYPE forkNum '" O •• n - 1;

(30)

-VAR forkFree: ARRAY [forkNum] OF boolean;

c: cc r;

PROCESS philosopher (left, right: forkNum); VAR v: num;

FUNCTION cond: boolean; BEGIN

cond:= forkFree[left] AND forkFree[right] END; BEGINPROC LOOP think; enterCc r (c); awaitCcr(c, cond);

forkFree[left]:= false; forkFree[right]:= false; leaveCcr(c) ;

eat;

enterCcr(c) ;

forkFree[left]:= true; forkFree[right]:= true; lea veCcr (c )

END ENDPROC; VAR k: num; BEGIN

FOR k:= 0 TO n - 1 DO forkFree[k]:= true; in 1 Cc r (c, , Cc r ' ) ;

FOR k:= 0 TO n - 1 DO start(philosopher«k+n-1) MOD n, k»; END.

4.4 SYNCHRONISATIE TUSSEN INTERNE- EN EXTERNE PROCESSEN

Interne- en externe processen kunnen communiceren via speciale gemeen-schappelijke "variabelen": de toonbankregisters van de interfaces. Schrijven naar zo'n register maakt de data toegankelijk voor het rand-apparaat (extern proces). Analoog kan door lezen van zo'n reglster worden gecontroleerd of het randapparaat een bepaalde condltle slgnaleert. Het lljkt voor de hand te llggen dat conditie synchronisatie tussen interne- en externe processen kan worden verkregen met behulp van een "REPEAT - UNTIL - <conditie>" statement. In het volgende hoofdstuk zal worden aangegeven dat deze oplossing niet echt brulkbaar Is. Het blijkt dat ook hier het gebruik van semaforen een oplossing biedt.

(31)

IMPLEMENTATIE VAN PROCESSEN EN SYNCHRONISATIES

In de vorige hoofdstukken is er als denkmodel vanuit gegaan dat aIle processen parallel worden uitgevoerd. Helaas is dit in praktische gevallen niet zoo Over het algemeen is er slechts sprake van een enkele fysieke processor. Dit betekent dat processen slechts quasi-parallel kunnen worden uitgevoerd. In dit hoofdstuk wordt een methode beschreven om zo goed mogelijk parallel te kunnen blijven denken, terwijl er toch slechts sprake is van een processor.

5.1 PROCESSEN

Het mechanisme van concurrente processen is als zodanig niet in Modulair Pascal uit te drukken. Om toch met processen te kunnen werken bevat de gereedschapskist een module dat hiervoor de nodige (gedeeltelijk in machine code geschreven) routines bevat. Deze uitbreiding is voldoende om samenwerkende processen te beschrijven.

De routines vergen van de gebruiker soms een tamelijk onhanteerbare notatie. Daarom wordt de syntaxis van Modulair Pascal voor dit doel uitgebreid. Er is een zogenaamde preprocessor beschikbaar die de toegevoegde syntaxis converteert naar Modulair Pascal zander uitbreidingen. Deze preprocessor kan worden beschouwd als een extra pass van de vertaler die wordt uitgevoerd voor de overige vier passes. Een informele beschrijving van de syntaxis van processen is als voIgt:

PROCESS procesNaam «formele parameters»; <locale declaraties>

BEGINPROC

{ Body van het proces } ENDPROC;

Het is noodzakelijk dat de '~eywordstJ PROCESS, BEGINPROC en ENDPROC als eerste op een regel staan.

De aanroep van een proces levert, net als een functie, een resultaat. Overigens gedraagt een proces zich vrijwel hetzelfde als een procedure. Het functieresultaat wordt al afgeleverd voordat met de uitvoering van

(32)

-het proces wordt begonnen. Het heeft dan ook niets te maken met de uitvoering van het proces. In plaats daarvan is het een pointer naar de zogenaamde instantiatie van het proces. Deze onstaat als neveneffect bij de aanroep. De pointer is van het TYPE proc. Na de aanroep van een proces worden zowel de aanroeper als het aangeroepen proces concurrent uitgevoerd.

Een elegante manier om een proces te waarbij het functieresultaat verder maken van de procedure start(p: proc).

instantieren en uit te voeren niet nodig is, is door gebruik te De aanroep is als voIgt:

start«procesnaam) «instantiatie naam), <prioriteit>, <dataStackSize>, <retumStackSize>. <ac tuele parameters»);

Van een proces kunnen meerdere instantiaties naast elkaar bestaan. Deze onstaan eenvoudigweg door meerdere aanroepen van het proces, eventueel met verschillende waarden van actuele parameters.

Afgezien van het feit dat processen concurrent worden uitgevoerd is het grootste verschil met procedures dat de uitvoering kan worden onder-broken en weer hervat. Meerdere instantiaties van een proces zijn dan ook volkomen concurrent. Ook bij procedures kunnen meerdere instantiaties naast elkaar bestaan (recursie). Deze zijn echter strikt hierarchisch. De laatste aanroep zal altijd het eerst zijn voltooid. Een proces kan zijn eigen uitvoering onderbreken door aanroep van de procedure passivate. De omgeving waarbinnen dit proces is gedefinieerd zorgt ervoor dat eventueel een ander proces wordt doorgestart. Ook stopt een proces wanneer het ENDPROC bereikt. Daama bestaat het proces niet meer. Een aanroep hiema van de procedure activate voor het betreffende proces zal dan ook lei den tot een foutmelding.

Hervatting van een proces vanaf de plaats waar het werd onderbroken geschiedt door middel van de procedure activate(p: proc).

In vrij veel gevallen zal blijken dat het plezierig is om processen te hebben die nooit aflopen. In tegenstelling tot de situatie bij procedures, waar dit tot de bekende oneindige Ius leidt, is dit bij processen geen enkel bezwaar. De gelijktijdigheid van uitvoering zorgt ervoor dat toch aIle processen aan de beurt komen. Een nette notatie voor een niet aflopend proces wordt verkregen met het LOOP statement:

[ [

LOOP

statements

END

Door de preprocessor wordt een proces omgezet naar de volgende procedure en de volgende functie.

(33)

PROCEDURE xxProcesNaam (PROCEDURE ini; formele parameters): VAR locale variabelen;

BEGIN ini;

{ Body van het proces } waitForAllChildren END;

FUNCTION procesNaam (formele parameters): proc; PROCEDURE work(PROCEDURE ini);

BEGIN

xxProcesNaam(ini, actuele parameters) END;

BEGIN

procesNaam:= newProcess(work)

E~;

Deze op het eerste gezicht lastige construe tie is nodig om formele parameters aan een proces mee te kunnen geven zonder dat verschillende uitvoeringen van de functie newProcess nodig zijn.

Het effect van de aanroep van de procedure waitForAllChildren is dat de procedure work niet wordt verla ten voordat eventuele kind-processen die binnen het vader-proces zijn gestart zijn beeindigd, hoewel de body van het vader-proces weI is beeindigd. Op deze wijze blijven variabelen die in het vader-proces zijn gedeclareerd voor de kind-processeD beschik-baar. Het volgende voorbeeld illustreert dit nog eeDs.

PROGRAM daddyWithChildren( ••• ); PROCESS daddy;

VAR daddyVars:

?;

PROCESS childl; BEGINPROC

LOOP Gebruik daddyVars E~

ENDPROC;

PROCESS child2; BEGINPROC

LOOP Gebruik daddyVars E~ E~PROC;

BEGINPROC

iniDaddyVars;

start(childl); start(child2)

{Hier is de body van het vader-proces beeindigd, terwijl daddyVars nog nodig zijn}

E~PROC;

BEGIN

start(daddy); END.

Indien een proces geen kind-processen heeft opgestart, hoeft de procedure waitForAllChildren niet te worden aangeroepen.

(34)

-]]

5.2 SYNCHRONISATIE TUSSEN INTERNE PROCESSEN

De synchronisatie tussen interne processen wordt gerealiseerd met behulp van semaforen of conditionele kritieke see ties.

In het vorige hoofdstuk is een informele beschrijving van een semafoor gegeven. Deze besehrijving 1s niet bruikbaar in een enkele processor machine. Immers de processor kan niet gelijktijdig de waehtlus van meerdere processen uitvoeren. Met andere woorden busy-waiting kan slechts in een proces tegelijk plaats vinden. Het is dus noodzakelijk dat een proces wordt onderbroken indien een p-operatie niet succesvol kan worden uitgevoerd en dat de executie aan een ander proces wordt gegeven. Dit mechanisme kan worden worden beschreven door de procedures passivate en activate. De procedure passivate stopt de uitvoering van het proces en zorgt ervoor met behulp van het onderliggende voor de gebruiker onzichtbare systeem dat een ander proces wordt doorgestart. De procedure activate draagt een proces voor uitvoering voor. De werkelijke uitvoering wordt weer bepaald door het onderliggende systeem. Indien geen enkel proces voor uitvoering is voorgedragen dan staat de processor in het statement LOOP - END van het onderliggende systeem te wachten. Een mogelijke implementatie van een semafoor op een single-processor machine is de volgende. TYPE queue poslnt sema ? •

.

,

O •• maxlnt; RECORD val poslnt; lijst: queue END;

De niet-oegatieve integer val geeft het aantal keren aan dat een p-operatie kan worden uitgevoerd zonder dat een proces hoeft te wachten. De queue lijst dient voor de identificatie van aIle processen die wachten.

Voor het type queue zijn de volgende procedures en functies beschikbaar. PROCEDURE iniQueue(VAR q: queue); ••• ;

FUNCTION isQueueEmpty(CONST q: queue): boolean; ••• , PROCEDURE procesToQueue(VAR q: queue; p: proc); ••• , FUNCTION procesFromQueue (VAR q: queue): proc; ••• ; De variabele

currentProcess.

die het huldige lopende

De procedure iniSema kan worden beschreven door:

(35)

PROCEDURE iniSema(VAR s: sema; iniVal: posInt)j BEGIN

WITH s DO BEGIN

val:= iniVal; iniQueue(lijst) END

END;

De p-operatie kan worden beschreven door: PROCEDURE p(VAR s: serna);

BEGIN WITH s DO BEGIN END; disable { ••• ondeelbaar}; IF val> 0

THEN BEGIN val:- 1; enable { ••• deelbaar} END ELSE BEGIN

END

procesToQueue(lijst, currentProces);

passivate {Enable is in passivate opgenomen}

END

De v-operatie kan worden beschreven door: PROCEDURE v(VAR s: sema);

BEGIN WITH s DO BEGIN END; disable { ••• ondeelbaar}; IF isQueueEmpty(lijst) THEN val:+ 1 ELSE activate(procesFromQueue(lijst»; enable { ••• deelbaar} END

De normale programmacyclus (von Neumann cyclus) kan niet worden onder-broken door interrupts indlen de procedure disable is aangeroepen. Deze ondeelbaarheid kan worden opgeheven door aanroep van de procedure enable.

5.3 SYNCHRONISATIE TUSSEN INTERNE- EN EXTERNE PROCESSEN

De synchronisatie tussen interne- en externe processen wordt op een enkel processor machine op een aantal wijzen gerealiseerd.

Het sc h ri jven van door het zetten apparaat behoort.

gegevens naar een randapparaat' vindt eenvoudig plaats van de juiste bits in het register dat bij het rand-nit kan met de procedures putBit, putByte en putWord.

(36)

-Het lezen van gegevens van een randapparaat vindt plaats analoog aan het schrijven. Hiervoor zijn de functies getBit, getByte en getWord beschik-baar.

Het synchroniseren van de interne- en externe processen kan niet met behulp van een "REPEAT UNTIL"- statement worden opgelost. Immers, de processor kan niet op meerdere plaatsen tegelijk wachten. Een oplossing is om periodiek het betreffende bit of de betreffende bits te inspecteren van het ingangs-register. Een andere oplossing is door het gebruik van interrupts. Welke oplossing wordt gekozen hangt af van verschillende factoren, zoals de beschikbare tijd tussen het optreden van een verandering en het afhandelen van de bi jbehorende ac tie.

Eerst zal aandacht worden geschonken aan het periodiek inspecteren, ook weI pollen genoemd, van de ingangswaarden. De volgende procedure geeft hiervan een voorbeeid.

PROCEDURE waitForByte(addr, val: integer); BEGIN

WHILE getByte(addr)

<>

val DO wait( ••• )

END;

De procedure wait vertraagt het proces gedurende een bepaalde tijd. Het nadeel van deze methode is dat een proces ook moet worden geactiveerd en gepassiveerd indien niet aan de voorwaarde getByte(addr) = val is voldaan. Met name indien sprake is van meerdere processsen leidt dit tot overbodig rekenwerk.

Een betere oplossing is om aIle processen die niet aan de voorwaarde voldoen in een wachtrij te plaatsen en door middel van inspectie van de betreffende bits te onderzoeken of het zinvol is om het proces te activeren. In de praktijk blijkt veelal dat men wenst te wachten op het opkomen of afvallen van een enkel bit. Het volgende programma module geeft hiervoor een oplossing. Met de procedure waitFor wordt eventueel gewacht of aan een conditie is voldaan. Met behulp van de procedure signalWaits wordt een test uitgevoerd op aIle processen die staan te wachten. De procedure signalWaits kan bijvoorbeeld worden aangeroepen in een interrupt handler die reageert op de klok.

PROGRAM waitFor( ••• ); TYPE list = ?;

PROCEDURE iniList(VAR 1: list); ••• ,

PROCEDURE processToList(VAR 1: list; p: proc); ••• , FUNCTION processFromList(VAR 1: list): proc; ••• , FUNCTION firstOfList(l: list): proc; ••• ;

(37)

}

Het type proc bevat de volgende beschrijving TYPE proc AprocRec;

proc Rec = RECORD

con tac tNr: ioBit; stateVal: boolean; END;

FUNCTION nextProc e ss (p: proc): proc; ••• ; VAR waitList: list;

PROCEDURE #waitFor(contactBit: ioBit; state: boolean); VAR p: proc; BEGIN IF getBit(contactBit)

<>

state THEN BEGIN END; p:= currentProces; WITH pA DO BEGIN END

contactNr:= contactBit; stateVal:= state; disable;

processToList(waitList, p);

passivate {Enable is in passivate opgenomen} END

PROCEDURE #signaIWaits; VAR this, next: proc; BEGIN

disable;

this:= firstOfList(waitList); WHILE this

<>

nil

DO WITH this A DO BEGIN next:= nextProcess(this); IF getBit(contactNr)= stateVal THEN activate(processFromList(waitList»; this:= next END; enable END; BEGIN iniList(waitList) END.

Naast het gebruik van polling procedures bestaat de mogelijkheid om interrupts toe te passen. In het navolgende zal worden bekeken hoe een interrupt handler, eigenlijk zelf een soort proces, met andere processen

(38)

-kan eommuniceren. Het volgende programma is daarvan een voorbeeld. Hierin wordt een proces doorgestart nadat een interrupt is opgetreden.

PROGRAM eondSyneIntrpt( ••• ); VAR eondSync: sema;

PROCEDURE IntrHandler; BEGIN v(condSync) END; PROCESS aProcess; BEGINPROC

LOOP

p(e ond Sync); END ENDPROC; BEGIN connectHandler(intrHandler, ••• ); start(aProcess); END.

In sommige gevallen gebruikt men een handler om een variabele bij te we rk en , zoals bijvoorbeeld de tijd. De volgende programma's laten de daarbij optredende complicaties zien. Het volgende programma lijkt een oplossing te bieden om de tijd bij te werken in een interrupt handler en de tijd te lezen in een proces.

PROGRAM gebruikTijd( ••• ); TYPE time

=

RECORD

min, sec: integer END;

VAR currentTime: time; PROCEDURE handleTime; BEGIN

WITH currentTime DO BEGIN

IF sec = 59

THEN BEGIN sec:= 0; min:+ 1 END ELSE sec:+ 1 END END; PROCEDURE iniTimer; BEGIN connnectHandler(handleTime, ••• ); END;

(39)

PROCESS aProcess; VAR saveTime: time; BEG INP ROC

LOOP saveTime:= currentTime; END ENDPROC; BEGIN currentTime:= time(O,O); iniTimer; start (aProcess); END.

Nu is het denkbaar dat de volgorde van uitvoering is: - sec:= OJ

- saveTime:= currentTime; - min:+ 1;

De "norma Ie" von Neumann cyclus wordt onderbroken door een interrupt en het gevolg zal zijn dat de variabele saveTime niet de huidige tijd bevat. Dit probleem ken worden ondervangen door de introductie van een semafoor die zorgt voor wederzijdse uitsluiting met betrekking tot de variabele currentTime. Het volgende programma lijkt een oplossing te bieden:

PROGRAM gebruikTijd( ••• ); TYPE time = RECORD

min, sec: integer END;

VAR currentTime: time; mutEx sema j PROCEDURE handleTime; BEGIN WITH currentTime DO BEGIN p(mutEx) ; IF sec = 59

THEN BEGIN sec:= 0; min:+ 1 END ELSE sec:+ 1; v(mutEx) END END; PROCEDURE iniTimer;

...

,

PROCESS aProcess;

VAR saveTime: currentTime; BEGINPROC

LOOP

(40)

-p(mutEx) ; saveTime:= currentTime; v(mutEx) ;

...

END ENDPROC; BEGIN currentTime:= time(O, 0); iniSema(mutEx, 1); iniTimer; start (aProcess); END.

Nu is het denkbaar dat de volgorde van uitvoering is: - a1 p(mutEx);

- a2 : saveTime:= currentTime; - il : p(mutEx);

Hier wordt de "normale" von Neumann cyclus wederom onderbroken door een interrupt. De handler wordt nu echter geblokkeerd en een situatie van deadlock is opgetreden.

Een mogelijke oplossing zou kunnen zijn om het proces aProcess tijdelijk een hogere prioriteit te geven. zodat de handler het proces niet kan onderbreken. Dit betekent dat de handler pas wordt uitgevoerd nadat een proces de kritieke sec tie heeft verlaten. Oft kan leiden tot het "over-schrijven" van interrupts. Ook dit is niet de bedoeling.

Een oplossing ligt in het vermi jden van blokkerende handel1ngen zoals het uitvoeren van een p- (of enter-) operatie in een interrupt handler. Het volgende programma geeft een eenvoudige en effectieve oplossing ten koste van een extra proces. Bij deze oplossing gaat geen informatie verloren indien het proces handleTimerProcess tijdelijk wordt opgehouden: de semafoor heeft een bufferende werking.

PROGRAM gebruikTijd; TYPE time = RECORD

min, sec: integer END;

VAR currentTime time; mutEx, syncTimer: sema; PROCEDURE handleTimer; BEGIN v(syncTimer) END; PROCEDURE iniTimer; "'; PROCESS handleTimerProcess; BEGINPROC LOOP P (sync Timer) ; WITH currentTime

(41)

DO BEGIN

p(mutEx) ; IF sec = 59

THEN BEGIN sec:= OJ min:+ 1 END ELSE sec:+ 1; v(mutEx) END END ENDPROC; PROCESS aProcess; VAR saveTime: time; BEGINPROC LOOP p(mutEx) ; saveTime:= currentTimej v(mutEx) ; END ENDPROC; BEGIN currentTime:= time(O, 0);

iniSema(mutEx, 1); iniSema(syncTimer, 0); iniTimerj start(handleTimerProcess); start(aProcess);

END.

In sommige gevallen wil men nadat een interrupt is opgetreden tevens invoergegevens in bijvoorbeeld een buffer plaatsen. Het volgende programma lijkt een oplossing te bieden voor het onder interrupt lezen van karakters die in een buffer worden geplaatst. De functie takeChar leest een karakter uit de buffer.

PROGRAM txtBuf( ••• );

CONST acia = 16#f7fc; stat= acia; data= acia+ 1;

bufSize = 128;

TYPE bufIdx = O •• bufSize - 1;

VAR charReceived, free, full, mayRemove: buffer

tnp, out

PROCEDURE ttyIntHandler; BEGIN v(charReceived) END; PROCESS handleTtyProcess; BEGINPROC LOOP p(charReceived) ; p(free) ; bufferlinp]:= chr(getByte(data»; v(full); sema;

ARRAY [bufIdx] OF char; bufIdx;

Referenties

GERELATEERDE DOCUMENTEN

de minister niet met deze ambtenaar kan werken of omdat men meent, dat de · betreffende ambtenaar niet voldoende is meege- groeid ·met de groter geworden taak

BEDRIJFSKAPITAAL GELDLENING NA TEKENEN AKTE VAN SCHULDBEKENTENIS EN OPVOEREN IN SYSTEEM. &gt; inbreng

 Een vast aanspreekpunt dat meer met ouder in verbinding staat – alle gedupeerden die het proces vervolgen krijgen na de uitslag van de eerste toets een vast aanspreekpunt die

In deze paragraaf zal het stage-gate model voor de farmaceutische industrie in het algemeen beoordeeld worden en eventueel aangepast worden voor het product A en andere nieuwe

Deze punten zijn deels van elkaar afhankelijk en zorgen er alleen voor dat beperkingen optreden voor de planning en productie. Wanneer orders geleverd worden, wordt het getelde

basisjaar voor specifiek de algemene operationele kosten in verband met waargenomen incidentele kostenontwikkelingen. • Middelen van de algemene operationele kosten is hier een

Serialization: Zeegers wordt niet opnieuw geïntroduceerd, het artikel bevat geen nieuwe

Een zesde reden waarom dit proces bijzonder is, is omdat iemand wordt vervolgd voor het aanzetten tot haat die zelf beweert te waarschuwen tegen een haatdragende ideologie. Of hij