2.2.2.1 Navnemodellen
Det er nyttigt at have en model for, hvordan navne er forbundet med specifikke objekter. En systemdesigner opretter en navngivningsplan, som består af tre elementer. Det første element er et navnerum, som består af et alfabet af symboler sammen med syntaksregler, der angiver, hvilke navne der er acceptable. Det andet element er en navnemappingsalgoritme, som tilknytter nogle (ikke nødvendigvis alle) navne i navnerummet til nogle (igen ikke nødvendigvis alle) værdier i et univers af værdier, som er det tredje og sidste element i navnemappingsordningen. En værdi kan være et objekt, eller det kan være et andet navn fra enten det oprindelige navnerum eller fra et andet navnerum. En mapping fra navn til værdi er et eksempel på en binding, og når en sådan mapping findes, siges navnet at være bundet til værdien. Figur 2.10 illustrerer det.
I de fleste systemer er der typisk flere forskellige navngivningsordninger i drift samtidig. Et system kan f.eks. anvende ét navngivningsskema til e-mail-postkasse-navne, et andet navngivningsskema til internetværter, et tredje til filer og et fjerde til virtuelle hukommelsesadresser. Når en programfortolker støder på et navn, skal den vide, hvilket navngivningsskema den skal påberåbe sig. Det miljø, der omgiver brugen af navnet, giver normalt nok oplysninger til at identificere navngivningssystemet. I et applikationsprogram ved forfatteren af programmet f.eks., at programmet skal forvente, at filnavne kun fortolkes af filsystemet, og at internetværtsnavne kun fortolkes af en eller anden netværkstjeneste.
Den fortolker, der støder på navnet, kører navnemappingsalgoritmen for det relevante navnemappingsskema. Navnemappingsalgoritmen løser navnet op, hvilket betyder, at den finder og returnerer den tilknyttede værdi (af denne grund kaldes navnemappingsalgoritmen også for en resolver). Navnetilknytningsalgoritmen styres normalt af en ekstra parameter, en såkaldt kontekst. For et givet navngivningsskema kan der være mange forskellige kontekster, og et enkelt navn i navnerummet kan mappe til forskellige værdier, når resolver’en anvender forskellige kontekster. Når en person f.eks. i almindelig tale henviser til navnene “du”, “her” eller “Alice”, afhænger betydningen af hvert af disse navne af den kontekst, hvori personen udtaler dem. På den anden side har nogle navngivningssystemer kun én kontekst. Sådanne navngivningsordninger giver det, der kaldes universelle navnerum, og de har den gode egenskab, at et navn altid har den samme betydning inden for den pågældende navngivningsordning, uanset hvem der bruger det. I USA udgør f.eks. socialsikringsnumre, som identificerer offentlige pensions- og skattekonti, et universelt navnerum. Når der er mere end én kontekst, kan fortolkeren fortælle resolveren, hvilken kontekst den skal bruge, eller resolveren kan bruge en standardkontekst.
Vi kan sammenfatte navnemodellen ved at definere følgende konceptuelle operation på navne:
værdi ← resolve (navn, kontekst)
Når en fortolker støder på et navn i et objekt, finder den først ud af, hvilket navneskema der er tale om, og dermed hvilken version af resolve den skal påberåbe sig. Derefter identificerer den en passende kontekst, løser navnet i denne kontekst og erstatter navnet med den løste værdi, mens den fortsætter fortolkningen. Variablen context fortæller resolve, hvilken kontekst der skal bruges. Denne variabel indeholder et navn, der er kendt som en kontekstreference.
I en processor er registernumre navne. I en simpel processor er både sættet af registernavne og de registre, som disse navne er bundet til, fastlagt på designtidspunktet. I de fleste andre systemer, der anvender navne (herunder registernavneordningen i nogle højtydende processorer), er det muligt at oprette nye bindinger og slette gamle bindinger, at opregne navnerummet for at få en liste over eksisterende bindinger og at sammenligne to navne. Til disse formål definerer vi fire yderligere konceptuelle operationer:
status ← bind (name, value, context)
status ← unbind (name, context)
list ← enumerate (context)
result ← compare (name1, name2)
Den første operation ændrer kontekst ved at tilføje en ny binding; statusresultatet rapporterer, om ændringen lykkedes eller ej (den kan mislykkes, hvis det foreslåede navn er i strid med syntaksreglerne for navnerummet). Efter et vellykket kald til bind returnerer resolve den nye værdi for name.* Den anden operation, unbind, fjerner en eksisterende binding fra konteksten, hvor status igen rapporterer succes eller fiasko (måske fordi der ikke var nogen sådan eksisterende binding). Efter et vellykket kald til unbinding returnerer resolve ikke længere denne værdi for name. Operationerne bind og unbind gør det muligt at bruge navne til at skabe forbindelser mellem objekter og ændre disse forbindelser senere. En designer af et objekt kan ved at bruge et navn til at henvise til et komponentobjekt vælge det objekt, som navnet er bundet til, enten på det tidspunkt eller på et senere tidspunkt ved at påkalde bind, og fjerne en binding, der ikke længere er hensigtsmæssig, ved at påkalde unbind, alt sammen uden at ændre det objekt, der bruger navnet. Denne evne til at udskyde og ændre bindinger er et effektivt værktøj, der anvendes i designet af næsten alle systemer. Nogle navngivningsimplementeringer tilbyder en enumerate-operation, som returnerer en liste over alle de navne, der kan opløses i kontekst. Nogle implementeringer af enumerate kan også returnere en liste over alle værdier, der i øjeblikket er bundet i konteksten. Endelig rapporterer compare-operationen (sandt eller falsk), om name1 er det samme som name2 eller ej. Betydningen af “samme” er et interessant spørgsmål, som behandles i afsnit 2.2.5, og det kan kræve, at der leveres yderligere kontekstargumenter.
Differente navngivningsordninger har forskellige regler om entydigheden af navn-til-værdi-tilknytninger. Nogle navngivningssystemer har en regel om, at et navn skal mappe til præcis én værdi i en given kontekst, og at en værdi kun må have ét navn, mens et navn i andre navngivningssystemer kan mappe til flere værdier, eller en værdi kan have flere navne, selv i samme kontekst. En anden form for entydighedsregel er reglen om et navnerum med entydige identifikatorer, som giver et sæt navne, der aldrig vil blive genbrugt i navnerummets levetid, og som, når de først er bundet, altid vil forblive bundet til den samme værdi. Et sådant navn siges at have en stabil binding. Hvis et navnerum med entydige identifikatorer også har den regel, at en værdi kun kan have ét navn, bliver de entydige navne nyttige til at holde styr på objekter over en længere periode, til at sammenligne referencer for at se, om de henviser til det samme objekt, og til koordinering af flere kopier i systemer, hvor objekter replikeres af hensyn til ydeevne eller pålidelighed. F.eks. udgør kundekontonummeret i de fleste faktureringssystemer et unikt identifikationsnavneområde. Kontonummeret vil altid henvise til den samme kundekonto, så længe denne konto eksisterer, på trods af ændringer i kundens adresse, telefonnummer eller endog personlige navn. Hvis en kundes konto slettes, vil denne kundes kontonummer ikke blive genbrugt til en anden kundes konto. Navngivne felter inden for kontoen, som f.eks. den skyldige saldo, kan ændre sig fra tid til anden, men bindingen mellem kundens kontonummer og selve kontoen er stabil.
Navntilknytningsalgoritmen plus en enkelt kontekst tilknytter ikke nødvendigvis alle navne i navnerummet til værdier. Et muligt resultat af udførelsen af resolve kan således være et resultat, der ikke er fundet, hvilket resolve kan meddele opkalderen enten som en reserveret værdi eller som en undtagelse. På den anden side kan et muligt resultat være en liste over værdier, hvis navneskemaet tillader, at et navn kan henføres til flere værdier. I så fald kan operationen unbinding kræve et ekstra argument, der angiver, hvilken værdi der skal ophæves. Endelig giver nogle navngivningsordninger mulighed for omvendt opslag, hvilket betyder, at en kalder kan levere en værdi som et argument til navnemappingsalgoritmen og finde ud af, hvilket navn eller hvilke navne der er bundet til denne værdi.
Figur 2.10 illustrerer navnemodellen, der viser et navnerum, det tilsvarende univers af værdier, en navnemappingsalgoritme og en kontekst, der styrer navnemappingsalgoritmen.
I praksis støder man på tre hyppigt anvendte navnemappingsalgoritmer:
Tabelopslag
■
Rekursivt opslag
■
Multipelopslag
Den mest almindelige implementering af en kontekst er en tabel med {navn, værdi}-par. Når implementeringen af en kontekst er en tabel, er navnemappingsalgoritmen blot et opslag af navnet i denne tabel. Selve tabellen kan være kompleks og involvere hashing eller B-trees, men den grundlæggende idé er stadig den samme. At binde et nyt navn til en værdi består i at tilføje dette {navn, værdi}-par til tabellen. Figur 2.11 illustrerer denne almindelige implementering af navngivningsmodellen. Der er én sådan tabel for hver kontekst, og forskellige kontekster kan indeholde forskellige bindinger for det samme navn.
Eksempler fra den virkelige verden på både den generelle navnemodel og implementeringen af table-lookup er der masser af:
En telefonbog er en table-lookup-kontekst, der binder navne på personer og organisationer til telefonnumre. Som i eksemplet med datakommunikationsnetværket er telefonnumre i sig selv navne, som telefonselskabet opløser til fysiske linjenumre ved hjælp af en navnemappingsalgoritme, der omfatter områdenumre, centraler og fysisk omstillingsudstyr. Telefonbøgerne for Boston og San Francisco er to kontekster af det samme navngivningsskema; et bestemt navn kan optræde i begge telefonbøger, men hvis det er tilfældet, er det sandsynligvis bundet til forskellige telefonnumre.
Små hele tal navngiver registrene i en processor. Værdien er selve registeret, og mapping fra navn til værdi sker ved ledningsføring.
Hukommelsesceller navngives på samme måde med de tal, der kaldes adresser, og mapping fra navn til værdi sker igen ved ledningsføring. Kapitel 5 beskriver en mekanisme til omdøbning af adresser, kendt som virtuel hukommelse, som binder blokke af virtuelle adresser til blokke af sammenhængende hukommelsesceller. Når et system implementerer flere virtuelle hukommelser, er hver virtuel hukommelse en særskilt kontekst; en given adresse kan henvise til en forskellig hukommelsescelle i hver virtuel hukommelse. Hukommelsesceller kan også deles mellem virtuelle hukommelser, i hvilket tilfælde den samme hukommelsescelle kan have samme (eller forskellige) adresser i forskellige virtuelle hukommelser, som bestemt af bindingerne.
Et typisk computerfilsystem anvender flere lag af navne og kontekster: disksektorer, diskpartitioner, filer og mapper er alle navngivne objekter. Kataloger er eksempler på tabelopslagskontekster. Et bestemt filnavn kan optræde i flere forskellige kataloger, der er bundet til enten de samme eller forskellige filer. I afsnit 2.5 præsenteres et casestudie af navngivning i Unix-filsystemet.
Computere tilsluttes datakommunikationsnetværk på steder, der kaldes netværkstilslutningspunkter. Netværkstilslutningspunkter navngives normalt med to forskellige navngivningsordninger. Den første, der anvendes inden for netværket, omfatter et navnerum, der består af tal i et felt med fast længde. Disse navne er bundet, nogle gange permanent og andre gange kun kortvarigt, til fysiske ind- og udgangspunkter i netværket. En anden navngivningsordning, der anvendes af netværkets klienter, knytter et mere brugervenligt universelt navnerum af tegnstrenge til navne i det første navnerum. Afsnit 4.4 er et casestudie af Domain Name System, som giver brugervenlig navngivning af tilknytningspunkter til internettet.
En programmør identificerer procedurevariabler ved hjælp af navne, og hver aktivering af proceduren giver en særskilt kontekst, hvori de fleste af disse navne opløses. Nogle navne, der identificeres som “statiske” eller “globale navne”, kan i stedet opløses i en kontekst, der deles mellem aktiveringer eller mellem forskellige procedurer. Når en procedure kompileres, kan nogle af de oprindelige brugervenlige navne på variabler erstattes af hele talidentifikatorer, som er mere bekvemme for en maskine at manipulere, men navngivningsmodellen gælder stadig.
En Uniform Resource Locator (URL) på World Wide Web afbildes til en bestemt webside ved hjælp af en relativt kompliceret algoritme, der opdeler URL’en i flere bestanddele og opløser delene ved hjælp af forskellige navngivningsskemaer; resultatet identificerer i sidste ende en bestemt webside. Afsnit 3.2 er et casestudie af denne navngivningsordning.
Et kundefaktureringssystem opretholder typisk mindst to slags navne for hver kundekonto. Kontonummeret navngiver kontoen i et unikt identifikationsnavneområde, men der findes også et særskilt navneområde med personnavne, som også kan bruges til at identificere kontoen. Begge disse navne er typisk knyttet til kontooptegnelser i et databasesystem, således at konti kan hentes enten efter kontonummer eller efter personnavn.
Disse eksempler fremhæver også en skelnen mellem “navngivning” og binding. Nogle, men ikke alle kontekster “navngiver” ting i den forstand, at de mapper et navn til et objekt, der almindeligvis opfattes som havende dette navn. Telefonbogen “navngiver” således ikke hverken personer eller telefonlinjer. Et andet sted findes der kontekster, der binder navne til personer, og som binder telefonnumre til bestemte fysiske telefoner. Telefonbogen binder navne på personer til navne på telefoner.