Klassisk Mac OS-hukommelsesstyring - Classic Mac OS memory management

"Om denne computer" Mac OS 9.1- vindue, der viser hukommelsesforbruget for hver åben applikation og selve systemsoftwaren.

Historisk set brugte det klassiske Mac OS en form for hukommelsesadministration, der er faldet ud af favør i moderne systemer. Kritik af denne fremgangsmåde var et af de centrale områder, der behandles ved ændringen til Mac OS X .

Det originale problem for ingeniørerne af Macintosh var, hvordan man optimalt bruger 128 KB RAM, som maskinen var udstyret med, på Motorola 68000- baseret computerhardware, der ikke understøttede virtuel hukommelse . Da maskinen på det tidspunkt kun kunne køre et applikationsprogram ad gangen, og der ikke var noget fast sekundært lager , implementerede ingeniørerne et simpelt skema, der fungerede godt med de særlige begrænsninger. Dette designvalg skaleres ikke godt med maskinens udvikling, hvilket skaber forskellige vanskeligheder for både programmører og brugere.

Fragmentering

De oprindelige ingeniørers primære bekymring ser ud til at have været fragmentering - det vil sige den gentagne allokering og deallokation af hukommelse gennem markører, der fører til mange små isolerede hukommelsesområder, som ikke kan bruges, fordi de er for små, selvom den samlede ledige hukommelse muligvis være tilstrækkelig til at tilfredsstille en bestemt anmodning om hukommelse. For at løse dette brugte Apple- ingeniører konceptet med et flytbart håndtag , en henvisning til hukommelse, der gjorde det muligt at flytte de faktiske henviste data uden at ugyldiggøre håndtaget. Apples ordning var enkel - et håndtag var simpelthen en markør i en (ikke-flytbar) tabel med yderligere markører, som igen pegede på dataene. Hvis en hukommelsesanmodning krævede komprimering af hukommelse, blev dette gjort, og tabellen, kaldet masterpointerblokken, blev opdateret. Maskinen selv implementerede to tilgængelige hukommelsesområder til denne ordning - systembunken (bruges til operativsystemet) og applikationsbunken. Så længe kun en applikation ad gangen blev kørt, fungerede systemet godt. Da hele applikationsbunken blev opløst, da applikationen afsluttedes, blev fragmentering minimeret.

Hukommelsesstyringssystemet havde svagheder; systembunken var ikke beskyttet mod fejlagtige applikationer, som det ville have været muligt, hvis systemarkitekturen havde understøttet hukommelsesbeskyttelse , og dette var ofte årsagen til systemproblemer og nedbrud. Derudover åbnede den håndtagsbaserede tilgang også en kilde til programmeringsfejl, hvor henvisninger til data inden for sådanne flytbare blokke ikke kunne garanteres at forblive gyldige på tværs af opkald, der kan få hukommelse til at bevæge sig. Dette var et reelt problem for næsten alle system- API'er, der eksisterede. På grund af gennemsigtigheden af ​​systemejede datastrukturer på det tidspunkt kunne API'erne ikke gøre meget for at løse dette. Således skyldtes programmøren ikke at oprette sådanne markører eller i det mindste styre dem meget omhyggeligt ved at henvise alle håndtag efter hvert sådant API-opkald. Da mange programmører generelt ikke var fortrolige med denne tilgang, led tidlige Mac-programmer ofte af fejl, der opstod som følge heraf.

Palm OS og 16-bit Windows bruger en lignende ordning til hukommelsesadministration, men Palm- og Windows-versionerne gør programmeringsfejl vanskeligere. For eksempel i Mac OS, for at konvertere et håndtag til en markør, henviser et program bare til håndtaget direkte, men hvis håndtaget ikke er låst, kan markøren hurtigt blive ugyldig. Opkald til at låse og låse op for håndtag er ikke afbalancerede; ti opkald til HLock fortrydes af et enkelt opkald til HUnlock . I Palm OS og Windows er håndtag af en uigennemsigtig type og der skal henvises til MemHandleLock i Palm OS eller Global/LocalLock Windows. Når en Palm- eller Windows-applikation er færdig med et håndtag, ringer den til MemHandleUnlock eller Global/LocalUnlock . Palm OS og Windows holder låseantal for blokke; efter tre opkald til MemHandleLock , bliver en blok først låst op efter tre opkald til MemHandleUnlock .

At løse problemet med indlejrede låse og låse op kan være ligetil (skønt kedeligt) ved at anvende forskellige metoder, men disse trænger ind på læsbarheden af ​​den tilknyttede kodeblok og kræver opmærksomhed og disciplin fra koderen.

Hukommelseslækage og uaktuelle henvisninger

Bevidsthed og disciplin er også nødvendigt for at undgå hukommelses "lækager" (manglende deallokering inden for rammerne af tildelingen) og for at undgå henvisninger til uaktuelle håndtag efter frigivelse (hvilket normalt resulterede i et hårdt nedbrud - irriterende på et system med en enkelt opgave, potentielt katastrofal, hvis andre programmer kører).

Omskifter

Situationen forværredes med fremkomsten af Switcher , som var en måde for en Mac med 512 KB eller mere hukommelse til at køre flere applikationer på én gang. Dette var et nødvendigt skridt fremad for brugere, der fandt en app-ad-gang-tilgang meget begrænsende. Da Apple nu var forpligtet til sin hukommelsesstyringsmodel samt kompatibilitet med eksisterende applikationer, blev det tvunget til at vedtage en ordning, hvor hver applikation fik sin egen bunke fra det tilgængelige RAM. Mængden af ​​faktisk RAM tildelt til hver bunke blev indstillet af en værdi kodet i metadataene for hver applikation, indstillet af programmøren. Nogle gange var denne værdi ikke nok til bestemte former for arbejde, så værdiindstillingen måtte udsættes for brugeren for at give dem mulighed for at tilpasse dyngestørrelsen, så den passer til deres egne behov. Selvom det var populært blandt " power-brugere ", var denne eksponering af en teknisk implementeringsdetalje i modstrid med Mac-brugerfilosofien. Bortset fra at udsætte brugerne for esoteriske tekniske forhold, var det ineffektivt, da der ville blive anvendt en applikation til at få fat i alt det tildelte RAM, selvom det efterlod det meste af det efterfølgende ubrugt. En anden applikation kan være sultet i hukommelse, men vil ikke kunne udnytte den gratis hukommelse, der "ejes" af en anden applikation.

Selvom en applikation ikke med fordel kunne bruge en søsters applikations dyng, kunne den bestemt ødelægge den, typisk ved utilsigtet at skrive til en nonsensadresse. En applikation, der ved et uheld behandler et fragment af tekst eller billede eller en ikke-tildelt placering som en markør, kunne let overskrive koden eller dataene for andre applikationer eller endda OS og efterlade "lurker", selv efter at programmet blev afsluttet. Sådanne problemer kan være ekstremt vanskelige at analysere og rette.

Switcher udviklede sig til MultiFinder i System 4.2, som blev Process Manager i System 7 , og på det tidspunkt var ordningen længe forankret. Apple gjorde nogle forsøg på at omgå de åbenlyse begrænsninger - midlertidig hukommelse var en, hvor et program kunne "låne" gratis RAM, der lå uden for sin bunke i korte perioder, men dette var upopulært hos programmører, så det stort set ikke lykkedes at løse problemerne. Apples System 7 Tune-up-tilføjelsesprogram tilføjede en "mindste" hukommelsesstørrelse og en "foretrukken" størrelse - hvis den foretrukne mængde hukommelse ikke var tilgængelig, kunne programmet starte i det minimale rum muligvis med nedsat funktionalitet. Dette blev indarbejdet i standard OS startende med System 7.1, men behandlede stadig ikke rodproblemet.

Virtuelle hukommelsesordninger , som gjorde mere hukommelse tilgængelig ved at søge ubrugte dele af hukommelsen til disken, blev gjort tilgængelige af tredjepartsværktøjer som Connectix Virtual og derefter af Apple i System 7 . Dette øgede Macintosh-hukommelseskapaciteten til en ydeevneomkostning, men tilføjede ikke beskyttet hukommelse eller forhindrede hukommelsesadministratorens bunkekomprimering, der ville ugyldiggøre nogle markører.

32-bit ren

Oprindeligt havde Macintosh 128 kB RAM med en grænse på 512 kB. Dette blev øget til 4 MB efter introduktionen af Macintosh Plus . Disse Macintosh-computere brugte 68000 CPU, en 32-bit processor, men havde kun 24 fysiske adresselinjer. De 24 linjer tillod processoren at adressere op til 16 MB hukommelse (2 24 bytes), hvilket blev betragtet som en tilstrækkelig mængde på det tidspunkt. RAM-grænsen i Macintosh-designet var 4 MB RAM og 4 MB ROM på grund af hukommelseskortets struktur. Dette blev løst ved at ændre hukommelseskortet med Macintosh II og Macintosh Portable , hvilket muliggør op til 8 MB RAM.

Fordi hukommelse var en knap ressource, besluttede forfatterne af Mac OS at drage fordel af den ubrugte byte i hver adresse. Den originale Memory Manager (indtil frem til System 7) placerede flag i de høje 8 bits i hver 32-bit markør og håndtag . Hver adresse indeholdt flag såsom "låst", "renselig" eller "ressource", som blev gemt i masterpegetabellen. Når de blev brugt som en faktisk adresse, blev disse flag maskeret af og ignoreret af CPU'en.

Mens en god brug af meget begrænset RAM-plads, forårsagede dette design problemer, da Apple introducerede Macintosh II, som brugte 32-bit Motorola 68020 CPU. 68020 havde 32 fysiske adresselinjer, der kunne adressere op til 4 GB (2 32 bytes) hukommelse. Flagene, som Memory Manager lagrede i den høje byte i hver markør og håndtag, var betydningsfulde nu og kunne føre til adressering af fejl.

I teorien var arkitekterne af Macintosh-systemsoftwaren fri til at ændre "flag i den høje byte" -plan for at undgå dette problem, og det gjorde de. For eksempel blev Macintosh IIci og senere maskiner HLock() og andre API'er omskrevet for at implementere håndtagslåsning på en anden måde end at markere de høje bit af håndtag. Men mange Macintosh-applikationsprogrammerere og en stor del af Macintosh-systemsoftwarekoden selv fik adgang til flagene direkte i stedet for at bruge API'erne, som f.eks. HLock() , Der var leveret til at manipulere dem. Ved at gøre dette gjorde de deres applikationer uforenelige med ægte 32-bit adressering, og dette blev kendt som ikke "32-bit rent".

For at stoppe kontinuerlige systemnedbrud forårsaget af dette problem, ville System 6 og tidligere kørsel på en 68020 eller en 68030 tvinge maskinen til 24-bit tilstand og ville kun genkende og adressere de første 8 megabyte RAM, en åbenbar fejl i maskiner, hvis hardware var kablet til at acceptere op til 128 MB RAM - og hvis produktlitteratur annoncerede for denne kapacitet. Med System 7 blev Mac-systemsoftwaren endelig gjort 32-bit ren, men der var stadig problemet med beskidte ROM'er. Problemet var, at beslutningen om at bruge 24-bit eller 32-bit adressering skulle træffes meget tidligt i opstartsprocessen, da ROM-rutinerne initialiserede Memory Manager for at oprette et grundlæggende Mac-miljø, hvor NuBus-ROM'er og diskdrivere er indlæst. og henrettet. Ældre ROM'er havde ingen 32-bit Memory Manager-understøttelse, og det var derfor ikke muligt at starte i 32-bit-tilstand. Overraskende nok blev den første løsning på denne fejl udgivet af softwarefirmaet Connectix , hvis produkt MODE32 fra 1991 genstartede Memory Manager og gentog tidlige dele af Mac-opstartsprocessen, hvilket gjorde det muligt for systemet at starte i 32-bit-tilstand og muliggøre brugen af ​​alle RAM i maskinen. Apple licenserede softwaren fra Connectix senere i 1991 og distribuerede den gratis. Den Macintosh IIci og senere Motorola baserede Macintosh-computere havde 32-bit rene rom'er.

Det gik et stykke tid, før applikationer blev opdateret for at fjerne alle 24-bit afhængigheder, og System 7 gav en måde at skifte tilbage til 24-bit tilstand, hvis der blev fundet applikationsinkompatibiliteter. På tidspunktet for overgangen til PowerPC og System 7.1.2 var 32-bit renhed obligatorisk for oprettelse af indfødte applikationer, og endnu senere kunne Motorola 68040- baserede Mac'er ikke understøtte 24-bit-tilstand.

Objektorientering

Fremgangen af objektorienterede sprog til programmering af Mac - først Object Pascal , derefter senere C ++ - forårsagede også problemer for den vedtagne hukommelsesmodel. Først synes det naturligt, at objekter implementeres via håndtag for at få fordelen ved at blive flyttet. Disse sprog, som de oprindeligt blev designet, brugte markører til objekter, hvilket ville føre til fragmenteringsproblemer. En løsning, implementeret af THINK (senere Symantec ) compilers , var at bruge håndtag internt til objekter, men bruge en pegesyntaks til at få adgang til dem. Dette syntes i første omgang en god idé, men der opstod snart dybe problemer, da programmører ikke kunne fortælle, om de havde at gøre med en flytbar eller fast blok, og derfor ikke havde nogen måde at vide, om de skulle påtage sig opgaven med at låse objekter eller ej. Naturligvis førte dette til et stort antal fejl og problemer med disse tidlige objektimplementeringer. Senere compilere forsøgte ikke at gøre dette, men brugte rigtige pegepinde og implementerede ofte deres egne hukommelsesallokeringsordninger til at omgå Mac OS-hukommelsesmodellen.

Mens Mac OS-hukommelsesmodellen med alle dens iboende problemer forblev på denne måde til Mac OS 9 på grund af alvorlige begrænsninger for applikationskompatibilitet, betød den stigende tilgængelighed af billig RAM, at de fleste brugere stort set kunne opgradere deres vej ud af en hjørne. Hukommelsen blev ikke brugt effektivt, men det var rigeligt nok til, at problemet aldrig blev kritisk. Dette er ironisk, da formålet med det originale design var at maksimere brugen af ​​meget begrænsede mængder hukommelse. Mac OS X fjernede endelig hele ordningen ved at implementere en moderne sparsom virtuel hukommelsesordning . En delmængde af de ældre hukommelsesmodel-API'er eksisterer stadig for kompatibilitet som en del af Carbon , men kort til den moderne hukommelsesmanager (en trådsikker malloc implementering) nedenunder. Apple anbefaler, at Mac OS X- kode bruges malloc og free "næsten udelukkende".

Referencer

eksterne links