212 Sulautettu ohjelmointi 13. Esimerkki: Symbianympäristö Tässä luvussa annamme esimerkin eräästä todellisesta sulautettujen järjestelmien toteuttamisessa käytetystä ympäristöstä, Symbian-käyttöjärjestelmästä. Tässä yhteydessä ei kuitenkaan esitellä Symbianympäristöä kokonaisuudessaan (sitä varten on omat teoksensa), vaan keskitytään nimenomaan niihin piirteisiin, jotka sen suunnittelussa paljastavat taustalla olleet sulautettujen järjestelmien yleiset ominaisuudet ja niihin liittyvät ongelmat, kun pyritään käyttämään C++-kieltä tarkoituksenmukaisesti. Erityisesti varsinainen Symbian-sovelluskehitys sivuutetaan, sillä siihen liittyvät ominaisuudet ovat samantapaisia kuin moniin muihinkin graafisiin sovelluskehitysympäristöihin 28. Sen sijaan taustalla oleva sovelluskehys esitellään lyhyesti, samoin kuin muut Symbianiin sisällytetyt sovelluskehitysmahdollisuudet. 13.1 Yleiskuvaus Symbian OS alunperin EPOC perustuu C++-kieleen ja oliosuunnittelun perusajatuksiin. Suunnitteluun ovat vaikuttaneet mobiililaitteiden kriittiset ominaisuudet ja kehittäjien kokemukset aiempien mobiililaitteiden ja niiden käyttöjärjestelmien suunnittelusta. Koska käyttöjärjestelmän suunnittelu on edennyt rinnan C++-kielen kehityksen kanssa, osaan nyky-c++:n ominaisuuksista ehdittiin Symbianissa kehittää oma, rinnakkainen ratkaisunsa ennen kieleen standardoitua vastaavaa mekanismia. Symbian OS on moniajokäyttöjärjestelmä, jossa käyttöjärjestelmän ydin vaihtaa suoritettavia säikeitä irrottavasti. Käyttöjärjestelmän eri versiot tukevat reaaliaikaisuutta vaihtelevasti, ja reaali- 28. On tosin myönnettävä että joissakin kohdin Symbianissa mennään äärimmäisyyksiin moneen muuhun ympäristöön verrattuna.
Esimerkki: Symbian-ympäristö 213 aikaominaisuuksia on lisätty järjestelmään tarpeen mukaan. Aivan ensimmäisissä käyttöjärjestelmän versioissa tukea reaaliajalle ei ollut lainkaan. Symbian on ehkä sikäli monesta muusta sulautettuun ympäristöön tarkoitetusta käyttöjärjestelmästä eroava toteutus, että monet sen piirteet ovat koettaneet tuoda lisäjoustavuutta järjestelmään. Tästä syystä voidaan jopa ajatella, että Symbian-ympäristö on jonkinlainen välimuoto kokonaan sulautettuihin järjestelmiin suunnattujen käyttöjärjestelmien ja perinteisten tietokoneisiin tarkoitettujen käyttöjärjestelmien välillä. 13.2 Käyttöjärjestelmän ydin Toteutustasolla Symbian-käyttöjärjestelmä perustuu mikroytimeen, joka huolehtii pääsääntöisesti vain suoritettavan säikeen vaihtamisesta ja muistinsuojauksesta. Lähes kaikki monimutkaisempi toiminta on poistettu käyttöjärjestelmän ytimestä ja toteutettu omana prosessinaan. Näitä prosesseja joista osa tosin on toisiinsa sulautunut ja toteutettu säikein, jotka voivat suoraan jakaa muistia kutsutaan Symbianympäristössä palvelimiksi. Koska esimerkiksi muistinhallinta, laiteajurit ja vuorontaminen ovat kuitenkin ytimen vastuulla, eivät omissa prosesseissaan, kyseessä ei kuitenkaan ole puhdas mikroydinjärjestelmä, olkoonkin, että ytimen sisällä monia toimintoja hoitaa ydinpalvelin (kernel server). Ytimen ja sovellusten rakenne Symbian-ympäristössä on esitetty kuvassa 13.1. Liityntä ytimen ja varsinaisten ohjelmistojen välillä tapahtuu kirjaston euser.lib kautta. Symbian-ytimeen liittyy sellainen erikoisuus, että laiteajurit on tyypillisesti toteutettu kerrostamalla. Korkeamman tason laiteajuri, nimeltään looginen laiteajuri, tarjoaa käyttöjärjestelmän ytimelle ja sovelusohjelmille laitteen palveluita abstraktilla tasolla, kun taas matalamman tason laiteajuri, fyysinen laiteajuri, peittää erilaisten laitteistojen toteutusyksityiskohdat. Toinen mielenkiintoinen ytimeen liittyvä yksityiskohta on, että uusissa käyttöjärjestelmissä mikroytimen sisällä on toinen, vieläkin pienempi ydin, nimeltään nanoydin, jonka varaan muun mikroytimen toiminta rakentuu. Nanoytimen toimintaan liittyy paljon rajoituksia, kuten esimerkiksi se, että dynaaminen muistin varaaminen ja vapauttaminen eivät ole mahdollisia. Toisaalta sen avulla voidaan toteuttaa aikakriittisempiä operaatioita kuin mitä muuten olisi mahdollista. Tämä onkin
214 Sulautettu ohjelmointi Sovellukset Ytimen omat palvelut Liityntä ytimeen (euser.lib) Ydin (ekern.exe) Laiteajurirajapinta Symbianpalvelimet Ydinpalvelin Taustasäie Laiteajuri Oheislaite Kuva 13.1 Symbian-ympäristö ja käyttöjärjestelmän ydin ollut tärkeä mekanismi käyttöjärjestelmän reaaliaikaominaisuuksia toteutettaessa. Aiemmin mainittu kirjasto euser.lib sisältää alustakohtaisia määrityksiä, kuten säikeet, semaforit ja joukon muita yleisesti tarvittuja ohjelmointiprimitiivejä. Kirjaston ominaisuuksia ei kuitenkaan voida käyttää käyttöjärjestelmän matalan tason ominaisuuksia ohjelmoitaessa, vaan kirjasto tarjoaa usein tarvittavia luokkia, operaatioita sekä mahdollisuuden tehdä järjestelmäkutsuja ytimen ja ydinpalvelimen tarjoamiin palveluihin ainoastaan ytimen vuorontamille prosesseille. 13.3 Resurssien hallinta Resurssien hallinta on sulautetuissa järjestelmissä toistuva ongelma. Symbian-ympäristössä hallinta on ratkaistu tavalla, joka on mikroydinjärjestelmille tyypillinen: käyttämällä palvelimia, jotka puolestaan hallinnoivat resursseja. 13.3.1 Palvelimet resurssien kätkijöinä Symbian-ympäristössä palvelimet toteuttavat kaikenlaisen resursseihin liittyvän toiminnallisuuden. Palvelimet on toteutettu säikeinä, ja ne odottavat sanomia joko asiakasohjelmilta tai toisilta säikeiltä. Sanoman
Esimerkki: Symbian-ympäristö 215 saatuaan palvelimet toimivat sanomaan koodatun ohjeen mukaan. Toisin sanoen palvelimen ymmärtämät sanomat muodostavat sen rajapinnan. Koska sovellusohjelmointi puhdasta sanomarajapintaa käyttäen voisi osoittautua hankalaksi, tarjoavat oikeastaan kaikki palvelimet proseduraalisen, metodikutsuihin perustuvan rajapinnan, joka käärii sanomanvälityksen. Tästä syystä palvelimien kanssa kommunikoidaan metodikutsuja käyttäen, ei suoraan asiakasohjelmille näkyvällä viestinvälityksellä. Sisäisesti on kuitenkin pääsääntöisesti kyse viestinvälityksestä, vaikka myös muistialueen siirto prosessilta toiselle on mahdollista. Tätä käytetään lähinnä silloin, kun tarvitaan suurten tietorakenteiden siirtämistä prosessilta toiselle. Toinen Symbian-resursseihin liittyvä selkeä piirre on, että niihin pitää erikseen ottaa yhteyttä, jolloin palvelimen ja asiakkaan väliin muodostuu istunto. Yhteyden otto on yleensä muotoa palvelin.connect(), ja sitä käytetään lähes aina joskus tosin hivenen naamioidussa muodossa. Tämän jälkeen on mahdollista käyttää palvelimen muita palveluita istunnon aikana. Vastaavasti istunto pitää myös sulkea. Siihen on omat rutiininsa. Koska jokainen resurssi on eristetty muusta järjestelmästä, on resursseihin liittyvistä ongelmista näennäisen helppo toipua. Riittää, että palvelin käynnistetään uudelleen, jolloin kaikki sen istunnot katkeavat, mutta asiakkaat voivat jatkaa toimintaansa edelleen. Niille asiakkaille, jotka ovat odottamassa palvelimen suoritettavia operaatioita, pitää lisäksi ilmoittaa, että palvelimella oli ongelmia, ja että se on jälleen käytettävissä vasta uudelleenkäynnistyksen jälkeen. Tähän riittää yleensä yksinkertainen aikavalvontamekanismi, jolloin asiakas riittävän kauan odotettuaan voi todeta, ettei palvelimelta tule vastausta lainkaan. Vastaavasti yksittäisen asiakkaan ongelmat eivät yleensä näy palvelimelle, sillä samanlainen aikavalvonta voidaan rakentaa symmetrisesti myös palvelimeen. Vaikka järjestelmän osittaminen ytimeen ja palvelimiin vaikuttaa toimintojen ositusmielessä hyvältä ratkaisulta, liittyy tähän myöskin joitakin käytännön ongelmia. Ehkä suurin ongelmista on, että kommunikointi palvelinten kanssa vaatii pääsääntöisesti viestinvälitystä asiakasohjelman ja palvelimen välillä. Tämä puolestaan voi vaikuttaa suorituskykyyn tilanteissa, joissa kommunikaatio on runsasta. Käytännössä tämä on johtanut optimointeihin sen suhteen, mitä palvelimia kannattaa ajaa samassa prosessissa, sillä tällöin ne voivat jakaa tietorakenteensa ja käyttää niitä ristiin. Esimerkkinä tällaisista palvelimista
216 Sulautettu ohjelmointi voidaan mainita tietoliikenneyhteyksien muodostuksessa tarvittavat palvelimet. Toinen ongelma on, että ohjelmoijalle ei välttämättä ole aina selvää, mitä metodikutsun taakse kätketty viestinvälitys tarkkaan ottaen toteuttaa. Tästä syystä tarjolla saattaa olla useita samantapaisia operaatioita, mutta niihin liittyy erilaisia sivuvaikutuksia ja semanttisia yksityiskohtia. Esimerkiksi tiedostoja käsiteltäessä voidaan helposti ajatella operaatiota, joka palaa vasta sitten, kun tiedosto on kirjoitettu flashmuistiin, ja toista operaatiota, joka ainoastaan kopioi tiedot tiedostopalvelimen muistialueelle, ja pyytää tiedostopalvelinta huolehtimaan varsinaisesta levyoperaatiosta. 13.3.2 Joitakin palvelimia Kuten aiemmin todettiin, lähes kaikki Symbian-ympäristön tarjoamat resurssit on kapseloitu palvelimiin. Seuraavassa on esimerkin vuoksi esitelty joitakin palvelimia ja niiden tehtäviä. Esitellyt palvelimet eivät missään tapauksessa ole täydellinen lista Symbian-palvelimista, vaan tavoitteena on antaa joitakin käytännön esimerkkejä siitä, millaisten resurssien kätkeminen on mahdollista palvelinten avulla. Tiedostoihin liittyvät palvelut Tiedostojärjestelmän palvelut tarjoava File Server on yksi Symbianympäristössä eniten käytettyjä palvelimia. Se tarjoaa pääsyn erilaisiin tiedostojärjestelmiin, joita ovat esimerkiksi ROM-, RAM- ja flashmuisti, mahdollinen muistikortti ja tarvittaessa myös muualla olevat, etäyhteyden kautta käytettävät tiedostojärjestelmät. Sovelluksia rakennettaessa File Serverin käyttö näkyy luokan RFs käyttönä. Tähän luokkaan on koottu rutiinit, jotka mahdollistavat varsinaisen tiedostopalvelimen kanssa kommunikoinnin viestinvälitystä käyttäen. Varsinaiset tiedostot puolestaan käsitellään luokan RFile kautta. Luokka luo ali-istunnon aiemmin avatun RFs-istunnon sisään. Ikkunointi Ikkunointi on Symbian-ympäristössä annettu tehtäväksi palvelimelle nimeltä Window Server, ja sillä on kaksi päätehtävää: näytön hallinnointi ja tapahtumankäsittely. Tästä syystä Window Serverin kanssa
Esimerkki: Symbian-ympäristö 217 ovat tekemisissä oikeastaan lähes kaikki Symbian-ympäristön alijärjestelmät, ehkä tietoliikennerutiineja lukuunottamatta. Näytön hallinnoinnin osalta palvelimen tehtävät ovat odotetut. Ikkunoinnin toteutuksen ideana on eräänlainen hierarkia, jossa ikkunointipalvelin omistaa aina ylimmän tason juuri-ikkunan itse. Tämän ikkunan alapuolelle on mahdollista rakentaa sovelluskohtaista ikkunointia joko ikkunaryhminä tai yksittäisinä ikkunoina. Myös ikkunaryhmät ja ikkunat voivat olla keskenään hierarkkisia. Toinen tärkeä palvelimen toimintokokonaisuus on tapahtumankäsittely. Tapahtumia käsitelläkseen Window Server rekisteröityy käyttöjärjestelmän ytimelle, joka puolestaan delegoi kaiken tapahtumienkäsittelyn palvelimelle. Tapahtumia käsitellessään palvelin myös jalostaa sisääntulevaa tapahtumatietoa, ja lähettää tapahtumainformaatiota sovelluksille ja tarvittaessa myös muille palvelimille. Varsinaiset tapahtumat ovat pitkälti samantapaisia kuin mitä muissa vastaavissa ympäristöissä. Mukana tosin on myös jonkin verran erikoisia operaatioita, kuten vaikkapa yksinkertaiset animaatiot, joiden käyttö tuo sovelluksiin lisää näyttävyyttä. Tietoliikenneyhteydet Tietoliikenneyhteyksien käyttöä varten Symbian-ympäristö tarjoaa useita palvelimia. Niistä sovellusohjelmoijan kannalta ehkä tärkeimmät on esitelty seuraavassa. Socket Server. Sovellusohjelmoija käyttää ohjelmia kirjoittaessaan palvelinta nimeltä Socket Server. Palvelin tarjoaa rajapinnan jota käyttäen tietoliikenneyhteyksiä voidaan avata, sulkea ja hallinnoida. Serial Communications Server. Palvelin hallinnoi varsinaista tietoliikenneyhteyttä, jota käyttäen tietoja voidaan välittää laitteesta verkkoon sekä vastaanottaa verkosta laitteeseen. Asiakasohjelmille palvelin tarjoaa sarjaporttia muistuttavan rajapinnan. Erilaisia kommunikointiprotokollia varten on mahdollista toteuttaa dynaamisesti ladattavia kommunikointimoduuleita (CSY). ETEL Server. Palvelin ottaa haltuunsa radiorajapinnan tarjomat palvelut matkapuhelinverkon suuntaan. Käytännössä kyseessä on jonkun verran abstrahoitu rajapinta matkapuhelinmodeemin toiminnallisuuksiin. Samaan tapaan kuin edellisenkin palvelimen tapauksessa, erilaisia toteutuksia varten voidaan dynaamisesti ladata erilaisia laajennoksia (TSY).
218 Sulautettu ohjelmointi Messaging Server. Palvelin huolehtii laitteen lähettämästä ja vastaanottamasta viestiliikenteestä. Sen toiminta kattaa SMS:t, MMS:t, näiden erilaiset muunnokset sekä sähköpostin. 13.4 Aktiiviset oliot Koska resursseja hallinnoivat palvelimet on kaikki toteutettu omina säikeinään, muodostuu Symbian-ympäristön toteutuksen kannalta olennaiseksi kysymykseksi eri säikeiden välinen kommunikointi. Vaikka jotkut palvelimet onkin toteutettu saman prosessin sisäisinä säikeinä, jotka voivat jakaa muistiavaruutensa, näin ei kuitenkaan toimita läheskään aina, vaan kommunikointi tapahtuu aidosti viestinvälityksen kautta. Tämä puolestaan tarkoittaa sitä, että viestinvälitykseen liittyvä sanomien käsittely pitää saada mahdollisimman virtaviivaiseksi. Symbian-ympäristössä käytetty toteutus perustuu tekniikkaan, jota kutsutaan aktiivisiksi olioiksi (active object). Hivenen monimutkaiselta ja mahtipontiselta kuulostavasta nimestään huolimatta aktiiviset oliot ovat varsin yksinkertainen käsite. Toteutustasolla kyse on siitä, että kaikkia tapahtumia odottaa yksi säie, ja kun jotakin tapahtuu, herätetty säie kutsuu sopivaa tapahtumankäsittelijää. Toisin sanoen aktiiviset oliot voidaan ajatella tavaksi toteuttaa tapahtumapohjainen ohjelmointiympäristö vähäisin resurssein ja ilman ylimääräisiä säikeitä. Aktiivisten olioiden lisäksi Symbian-ympäristö tarjoaa myös mahdollisuuden käyttää säikeitä hyödyntämällä luokkaa RThread, mutta tämän käyttöä pyritään välttämään suorituskyky- ja muistinkulutussyistä. Toteutuksessa käytetty säie kuluttaa noin 4 kilotavua ytimen ja 12 kilotavua sovelluksen muistia, kun taas aktiivinen olio kuluttaa ainoastaan muutaman tavun. Lisäksi suorituskyvyssä on merkittävä ero johtuen siitä, että aktiivisia olioita käytettäessä ei tarvitse vaihtaa suoritettavaa säiettä. Tämän on todettu johtavan kertaluokkaa nopeampaan toteutukseen useissa käytännön sovelluksissa. Aktiiviset oliot toimivat siten, että yksi säie palvelee aktiivisen vuorontajan (active scheduler) avulla yhtä tai useampaa keskenään rinnakkaista aktiivista oliota. Hivenen harhaanjohtavasta nimestä huolimatta ei toteutuksessa ole kyse varsinaisesta moniajosta eikä olioiden aktiivisuudesta, vaan eri sanomien käsittelyn sarjallistamisesta siten, että operaatiot suoritetaan niitä vastaavien pyyntöjen prioriteetti- ja saapumisjärjestyksessä. Kokonaisuutena voidaan ajatella, että kollektiivisesti kaikkien operaatioiden läpimenoaika nopeutuu tällä järjeste-
Esimerkki: Symbian-ympäristö 219 lyllä, sillä aikaa ei kulu suoritettavan operaation vaihtamiseen, mikäli uusi sanoma saapuu, kun edellisen käsittely on vielä käynnissä. Toisaalta korkeaprioriteettiset operaatiot kärsivät, sillä niiden vasteaika voi huonontua johtuen jo suorituksessa alempiprioriteettisten operaatioiden aiheuttamasta odotuksesta. Koska kaikki tapahtumankäsittelyyn liittyvät operaatiot suoritetaan aina loppuun saakka ennen seuraavan tapahtuman käsittelyä, on selvää, että kovin pitkät tapahtumankäsittelijät eivät ole mahdollisia. Jos sellaisia tarvitaan, pitää ne yleensä jakaa pienempiin kokonaisuuksiin, jotka sitten kytketään sarjaan käyttämällä esimerkiksi ajastimia apua. Käytännössä tämä johtaa usein tarpeettoman monimutkaiseen ratkaisuun, mutta muitakaan vaihtoehtoja ei usein ole. Lisäksi joitakin käsitteellisiä ongelmia liittyy siihen, miten suoritusaikaisiin virheisiin suhtaudutaan tapahtumankäsittelyn aikana. Symbian-ympäristö tarjoaa mahdollisuuden tarjota virheenkäsittelyrutiini, mutta käytännön syistä joskus voi olla vaikeaa toteuttaa kaikista mahdollisista ongelmista järkevästi toipuvaa rutiinia. Lisäksi se, miten pitkälle varsinaista toimintoa on ehditty suorittaa, voi ainakin periaatteessa aiheuttaa ongelmia. 13.5 Dynaamisen muistin hallinta Symbianympäristössä Koska yksi Symbian-ympäristön suunnittelutavoitteista oli ottaa huomioon sulautetun järjestelmän erityispiirteitä, on tämä tavoite läsnä vahvasti myös dynaamisen muistin hallintaan liittyvissä toiminnoissa. Seuraavassa esittelemme dynaamisen muistinhallinnan perusmekanismit, joihin Symbian-ohjelmoinnissa tukeudutaan. 13.5.1 Tyyppijärjestelmä ja nimeämiskäytännöt Kuten jo palvelimien yhteydessä kävi ilmeiseksi, monet Symbianympäristössä käytetyt tyypit ja niiden nimet poikkeavat melkoisesti monesta muusta ympäristöstä tutuista. Osaltaan syynä on Symbianympäristön erikoisuudet, kuten palvelimet ja resurssien käyttö niiden kautta, mutta osaltaan syynä on myös pyrkimys luoda omanlaisensa tyyppijärjestelmä ja nimeämiskäytäntö, joka liittyy kiinteästi siihen, miten dynaamisesti varattuja resursseja erityisesti muistia hallitaan. Tästä syystä perinteisiä C- tai C++ -tietotyyppejä ei Symbianympäristössä käytetä oikeastaan lainkaan.
220 Sulautettu ohjelmointi Tyyppijärjestelmä ei pääosin eroa muista vastaavista, mutta monelle tyypille on annettu uudet nimet. Lisäksi mukana on joitain kokonaan uusia tietotyyppejä, joiden avulla on joissain tilanteissa mahdollista toteuttaa tiettyjä rutiineja joko turvallisemmin tai nopeammin kuin mitä olisi mahdollista käyttäen vain C:n ja C++:n rutiineja 29. Esimerkkinä tällaisesta rutiinista voisi mainita kuvaimet (descriptor), jotka ovat Symbian-ympäristön merkkijonoja. Toisin kuin C:n ja C++:n perinteiset merkkijonot, kuvaimet tietävät minkä kokoisia ne ovat, ja osaavat myös toimia johdonmukaisesti, jos merkkijonoa indeksoidaan liian pitkälle. (C++:n vector-mallilla toteutettu merkkijono (string) tietää myös pituutensa ja vahtii indeksejä, jos indeksointi tehdään jäsenfunktiolla at hakasulkeiden sijaan.) Symbian-ympäristön nimeämiskäytännöt ovat kattavia, ja koskevat luokkia, metodeja sekä yksittäisten muuttujien nimiä. Seuraavassa on esitetty lyhyt lista tärkeimmistä käytännöistä. Luokat ja tyypit Luokkien nimet alkavat C-kirjaimella. Ytimen luokkien nimet alkavat D-kirjaimella. Mixin-luokkien nimet alkavat M-kirjaimella. Tyyppien nimet alkavat T-kirjaimella. Luettelotyyppien nimet alkavat E-kirjaimella. Resursseihin liittyvien luokkien ja tyyppien nimet alkavat R-kirjaimella. Metodit Metodien nimet alkavat isolla kirjaimella. Ne metodit, jotka saattavat heittää poikkeuksen, loppuvat kirjaimeen L (tai LC). Saanti- ja asetusmetodien nimet ovat samat kuin muuttujan nimi, kun kyseessä on yksinkertanen metodi. Saanti- ja asetusmetodien nimet ovat muotoa GetSomeVariable ja SetSomeVariable, kun kyseessä on monimutkainen metodi. 29. Monessa kohtaa on kuitenkin käynyt niin, että C:n ja C++:n uudempiin versioihin on lisätty samantapaisia ominaisuuksia.
Esimerkki: Symbian-ympäristö 221 Muuttujat Instanssimuuttujien nimet alkavat i-kirjaimella. Argumenttimuuttujien nimet alkavat a-kirjaimella. Vakioiden nimet alkavat K-kirjaimella. Automaattisten muuttujien, siis niiden, jotka ovat metodille paikallisia ja olemassa vain metodin suorituksen ajan, nimet alkavat pienellä kirjaimella, mutta ei kuitenkaan mieluusti edellä varatuilla kirjaimilla väärinkäsitysten välttämiseksi. 13.5.2 Poikkeukset Vaikka C++ tarjoaa poikkeukset osana standarditoteutusta, Symbianympäristössä on perinteisesti käytetty omaa poikkeustoteutusta, joka on liitoksissa muistinhallintaan (katso seuraava kohta). Symbianin poikkeuskäsittelyn varsinainen rakenne on samankaltainen kuin standardin määrittelemäkin, mutta syntaksi on hivenen erilainen: TRAPD(error, RunExceptionThrowingCode(arguments); // try-osa if (error!= KErrNone) { // Catch-osa if (error == KErrNotSupported) {...} } Varsinaisen poikkeuksen heittäminen tapahtuu kutsumalla operaatiota User::Leave poikkeustilannetta kuvaavalla parametriarvolla, User::Leave(KErrUnknown); // Throw-osa Jos tarkastellaan tilannetta kulissien takana, suurin ero standardinmukaiseen poikkeukseen verrattuna on, että Symbian-ympäristössä poikkeus ei aiheuta olioiden rakentamista, vaan parametrina välitettävä kokonaisluku identifioi poikkeuksen. 13.5.3 Muistinvaraukset ja poikkeukset Ehkä erikoisin dynaamisen muistinhallintaan liittyvä käytäntö, joka Symbian-ympäristössä on otettu käyttöön, on erillisen tietorakenteen varaaminen dynaamisesti varattujen muistialueiden hallinnoimiseksi. Muussa tapauksessa voisi käydä niin, että poikkeuksen sattuessa viitettä varattuun muistialueeseen ei enää olisi olemassa, eikä mikään osa ohjelma voisi vapauttaa tätä muistialuetta.
222 Sulautettu ohjelmointi Edellä kuvattu tietorakenne on nimeltään CleanupStack. Ajatuksena on, että aina kun ohjelmoija varaa dynaamista muistia, osoitin varattuun muistialueeseen lisätään tähän tietorakenteeseen, CData data = new (ELeave 30 ) CData(); CleanupStack::PushL(data); Kun tietorakenteeseen viittaava viite on sijoitettu pinoon, voidaan poikkeuksen sattuessa vapauttaa ne dynaamiseen muistiin viittaavat varaukset, joihin ei enää ole pääsyä ohjelmasta itsestään poikkeuksen jälkeen. Toisin sanoen CleanupStack on siis eräänlainen roskaantumista ehkäisevä varokeino, jonka toimintaa ohjelmoijan on kuitenkin autettava. Lisäksi on tärkeää, että ainoastaan dynaamisesti varatut resurssit, joihin liittyvä ainoa viite on jonkin metodin sisällä olevan muuttujan arvona, lisätään CleanupStack-tietorakenteeseen, sillä ainoastaan näihin muuttujiin liittyy riski niiden arvon katoamisesta. Sen sijaan esimerkiksi olioiden jäsenmuuttujat, joiden kautta dynaamista muistia voidaan myös varata, eivät saa osalleen vastaavanlaista kohtelua. Mikäli näin kävisi, voisi muisti tulla jossain tilanteessa vapautettua kaksi kertaa, mikä tulkitaan yleensä vakavaksi virheeksi. CleanupStack-tietorakenteeseen lisätyt viitteet ja niiden takana olevat tietorakenteet eivät poistu pinosta automaattisesti muuten kuin poikkeuksen yhteydessä. Tästä syystä, kun tietorakennetta ei enää tarvita, viite siihen pitää muistaa poistaa myös CleanupStack-tietorakenteesta: delete data; CleanupStack::Pop(); On myös mahdollista työntää pinoon viittauksia istuntoihin, jota on avattu palvelimille. Tällöin käytetään muotoa CleanupStack::ClosePushL joka määrittelee rutiinin Close poikkeuksen yhteydessä suoritettavaksi metodiksi. CleanupStack-tietorakenteen käyttöön liittyy myös useita lyhennysmerkintöjä, joiden avulla rakenteen voi hävittää ja tuhota samalla kertaa. Samaten se, mistä luokasta tietorakenteeseen sijoitettu tietorakenne on peritty, vaikuttaa varauksen vapauttamiseen; joissain ti- 30. ELeave:n merkitys on kutsua kuormitettua rakentajaa, joka heittää poikkeuksen, jos muistia ei saada varattua. Tällöin ei tarvitse erikseen tarkistaa muistinvarauksen onnistumista joka kerta.
Esimerkki: Symbian-ympäristö 223 lanteissa riittää, että ainoastaan muisti vapautetaan, kun taas joskus pitää myös olion purkaja suorittaa. 13.5.4 Kaksivaiherakentaminen Edellä esitelty tietorakenne ei vielä riitä kaikkiin muistinvaraustilanteisiin. Jos käy niin ikävästi, että poikkeus syntyy, kun suoritetaan rakentajaa ja joitakin resursseja on jo varattu, ei Symbianin poikkeuskäsittelijä pysty vapauttamaan niitä, vaan ne jäävät roskaamaan muistia. Tilanteen korjaamiseksi Symbian-ympäristössä kehotetaan käyttämään kahta rakentajaa, joista ensimmäinen rakentaa tietorakenteen niiltä osin kuin poikkeuksia ei voi tulla muistinvarausta lukuunottamatta, ja jälkimmäinen sitten huolehtii niistä operaatioista, jotka mahdollisesti johtavat poikkeukseen. Ennen jälkimmäisen rakentajan kutsua voidaan kuitenkin viite varattuun alueeseen sijoittaa CleanupStacktietorakenteeseen. Rakentajista ensimmäinen on normaali C++-rakentaja, ja jälkimmäinen yleensä nimeltään ConstructL, joka siis nimensä mukaisesti voi heittää poikkeuksen: CData data = new (ELeave) CData(); CleanupStack::PushL(data); data.constructl(); Koska joissain tilanteissa joudutaan rakentamaan useita perintähierarkiatasoja, on joskus tapana käyttää myös muotoa BaseConstructL. On kuitenkin selvää, että varsinkin syvän perintähierarkian yhteydessä kaksivaiherakentaminen voi johtaa vaikeuksiin. 13.6 Laajennukset Perinteisesti Symbian-sovellukset on rakennettu käyttäen C++-kieltä, jonka käyttöä varten Symbian tarjoaa luokkahierarkian. Lisäksi on saatavilla useita sovelluskehitystä tukevia laajennoksia. Näistä tärkeimmät käsitellään seuraavassa. Tarkoituksena on osoittaa, että laajennusten avulla erilaisten sovellusten toteuttaminen yksinkertaistuu. Lisäksi samalla saavutetaan myös nopeampi kehitys.
224 Sulautettu ohjelmointi 13.6.1 Symbian C++-sovelluskehitys Symbian C++-sovelluskehitys perustuu sovelluskehykseen, jota erikoistamalla on mahdollista toteuttaa graafiseen käyttöliittymään perustuvia sovelluksia. Sovelluskehys käytännössä pakottaa toteuttamaan sovellukset MVC-malliin (Model, View, Controller) perustuen. Yleensä malliosuuden (model) siis sovelluksen tietorakenteet ja niihin liittyvät operaatiot käsittävät osat voi yleensä toteuttaa melko samaan tapaan kuin mitä yleensäkin C++:lla, jos ei oteta huomioon edellä esitettyjä nimi- ja tyyppikäytäntöjä ja muita yksityiskohtia. Joskus jopa suora siirto kääntämällä onnistuu, sillä kääntäjä ei ota huomioon Symbian-ympäristön erikoisuuksia muuten kuin rajapintariippuvuuksien kautta. Sen sijaan näkymä (view) ja ohjain (controller) on toteutettava Symbianin omien käyttöliittymäkirjastojen avulla, jolloin on lähes pakko seurata Symbian-ympäristön käytäntöjä ja osattava käyttää kirjaston luokkahierarkiaa. Esimerkkinä mainittakoon vaikkapa graafisen käyttöliittymän kautta annetut syötteet tulkitseva ikuinen silmukka, joka on toteutettu aktiivisten olioiden avulla ja jonka toiminta perustuu kantaluokan tietyn metodin kuormittamiseen omassa, sovelluskohtaisessa luokassa. Lisäksi myös E32Main-funktion käyttö on mahdollista, jolloin sovellusta voidaan suorittaa ikään kuin komentoriviltä käynnistettynä. Tämä tapa toteuttaa sovelluksia sopii lähinnä kokeiluihin ja pieniin testiohjelmiin, vaikka pohjimmiltaan mikään ei estä monimutkaistenkaan sovellusten kehittämistä. 13.6.2 Java Symbian-ympäristöön on saatavissa useita eri toteutuksia mobiiliympäristöön sovitetusta Javasta, joka puolestaan on ehkä maailman yleisin sulautettu ohjelmointiympäristö satojen miljoonien levinneisyydellä. Symbian-ympäristön eri toteutusten ominaisuudet vaihtelevat, ja jotkut niistä (erityisesti kommunikaattoreihin tarkoitetut toteutukset) ovat hyvin lähellä työasemien Java-ympäristöjä, kun taas puhelimiin tarkoitettu Java on yleensä jonkin verran yksinkertaistettu. Puhelinmallisiin laitteisiin on tyypillisesti sisällytetty MIDP Java, jossa joitain kielen ominaisuuksia on jätetty pois muistin säästämiseksi, suorituskyvyn optimoimiseksi ja tietoturvaominaisuuksien yksinkertaistamiseksi. Ominaisuuksia, joista on jossakin vaiheessa luovuttu, ovat esimerkiksi seuraavat:
Esimerkki: Symbian-ympäristö 225 liukulukulaskenta, heikot viittaukset (weak references) reflektio säieryhmät (thread groups). Lisäksi käyttöliittymää on yksinkertaistettu matkapuhelimen näyttöä paremmin tukevaan muotoon. Ohjelmoija voi hyödyntää grafiikkaa käyttäen joko matalan tason rajapintoja, joiden avulla on mahdollista rakentaa samanlainen näkymä ohjelmistoon kaikissa laitteissa, tai sitten graafisten komponenttien käyttöä tukevia rajapintoja, jotka tyypillisesti on mukautettu laitteen oman graafisen ilmiasun mukaisesti. Perusominaisuuksien lisäksi laitteet voivat tarjota lisärajapintoja, joiden avulla yhä monimutkaisempien ominaisuuksien käyttö on mahdollista. Erilaisten lisärajapintojen tukeminen tai tukematta jättäminen (ja niissä olevien toteutusten ongelmien tunteminen) on tärkeää erityisesti silloin, kun tähdätään mahdollisimman suorituskykyisiin ja laajalti käytettäviin sovelluksiin. 13.6.3 Python Python on yleisesti käytetty tulkattava skriptikieli, jota käytetään usein yhdistämään eri sovelluksia. Pythonilla on kuitenkin mahdollista toteuttaa myös kokonaisia sovelluksia, ja saatavilla olevat Python-toteutukset ovat suorituskyvyltään varsin hyviä, joten myös suorituskyvyn kannalta Pythonin käyttö mobiiliympäristössä on jossakin mielessä perusteltua. Symbian-ympäristöön on saatavilla myös versio Python-ohjelmointikielestä, jonka avulla omia ohjelmia on mahdollista rakentaa skriptaamalla. Saatavilla oleva Python-toteutus sisältää standardirajapintojen lisäksi myös mahdollisuuden hyödyntää mobiililaitteille spesifisiä rajapintoja. Tällaisia ovat esimerkiksi kamera, laitteen sisään talletetut yhteystiedot ja kalenterimerkinnät, Bluetooth-yhteydet, audioominaisuudet sekä yksinkertaiset puhelintoiminnot, kuten soittaminen ja viestinlähetys. Rajapinnat on tyypillisesti suunniteltu siten, että ohjelmoijan näkökulma on otettu huomioon. Tästä syystä operaatiot eivät välttämättä ole aivan yhtä yleisiä kuin mitä Symbian-ympäristön natiivioperaatiot, mutta toisaalta niiden käyttö on yksinkertaisempaa ja suoraviivaisempaa. Symbian-ympäristön lisäksi Python on saatavilla myös moneen muuhun sulautettuun ympäristöön, jossa skriptaaminen on hyödyllistä.
226 Sulautettu ohjelmointi Esimerkkinä mainittakoon vaikkapa Nokian Linux-pohjainen Maemoympäristö. 13.6.4 Web Runtime Web Runtime -ympäristö (WRT) on lähinnä web-ohjelmien tapaan toimivien sovellusten toteuttamista varten rakennettu sovellusympäristö. Toteutusmielessä ympäristö sopii hyvin web widget - tyyppisten sovellusten toteuttamiseen, ja sen avulla on melko yksinkertaista rakentaa pikkuohjelmia, jotka lataavat sisältöä WWW:tä hyväksikäyttäen. Aivan kuten perinteisessä selainympäristössäkin, sovellukset rakennetaan WRT-ympäristössä käyttäen XHTML:ää, CSS:ää sekä JavaScriptia, joten myös huonot puolet ovat samat kuin selainsovelluksia käytettäessä. Myös Ajax-tyyppisten (Asynchronous JavaScript and XML) ominaisuuksien käyttö on mahdollista, joten asynkroniset päivitykset verkosta ladattaessa ovat mahdollisia. Lisäksi toisin kuin selainympäristöt yleensä, Symbianin Web Runtime -ympäristö tarjoaa jonkin verran rajapintoja laitteen sisäisiin resursseihin. Tämä tarjoaa sovelluskehittäjälle mielenkiintoisia mahdollisuuksia mashup 31 -tyyppisten sovellusten suunnitteluun ja toteutukseen. 13.6.5 OPL OPL (alkujaan Organizer Programmer Language) on alun perin jo EP- OC:iin liitetty Basicia muistuttava ohjelmointikieli, jolla oli tarkoitus ohjelmoida Psionin valmistamia mobiililaitteita. OPL-kielen avulla on mahdollista luoda sekä konsolisovelluksia että graafista käyttöliittymää hyödyntäviä ohjelmistoja sangen suoraviivaisesti. OPL on ilmeisesti periaatteessa edelleen osa Symbianympäristöä, olkoonkin että OPL-sovelluksien määrää on vaikea arvioida. Projektin kotisivu on viimeksi päivitetty 17.6.2006, joten voitaneen todeta että OPL ei ole kovinkaan laajassa käytössä oleva laajennos. 31. Mashup-sovellukset ovat verkossa yleinen tapa koostaa uudenlaisia sovelluksia ja palveluita yhdistämällä tietoa useamman palvelimen tarjoamasta valikoimasta. Esimerkkimashup-sovelluksina mainittakoon vaikkapa karttapohjainen uutispalvelu ja wikipedia-sivut, jotka on kytketty valokuviin kuvissa käytettyjen tagien perusteella.
Esimerkki: Symbian-ympäristö 227 13.7 Lopuksi Loppuyhteenvetona voi perustellusti todeta, että Symbianissa käytetty mikroydinarkkitehtuuri on osoittautunut niin hyväksi kompromissiksi muunneltavuuden, muistinkulutuksen ja suorituskyvyn kannalta, että sen varaan on kyetty rakentamaan kokonainen mobiililaitteiden tuoteperhe. Toki parantamisen varaa on, ja jopa siitä, onko tyypillisesti paljon viestinvälitystä vaativa mikroydin oikea valinta sulautettuun järjestelmään lainkaan, voidaan kiistellä. Ohjelmoijan kannalta mielenkiintoinen seikka on, että Cleanup- Stack-tietorakenteen käyttö sekä Symbian-ympäristön nimeämiskäytännöt ohjaavat ottamaan dynaamisen muistin hallinnan huomioon Symbian-sovelluksia suunnitellessa aivan suunnittelun alkuvaiheista lähtien. Tätä voidaan pitää yleisenä hyvänä käytäntönä sulautetuissa järjestelmissä ja niiden ohjelmistoissa, varsinkin silloin, kun nojataan vahvasti oliosuunnitteluun, ja toteutus rakennetaan C++-kieltä käyttäen. Huonona puolena Symbian-ympäristön käytännöissä voidaan pitää sitä, että yleensä pienten asioiden kokeilu kaikkien sääntöjen puitteissa on usein työlästä ja aikaa vievää. Itse asiassa se, että ohjelmoija joutuu alusta asti keskittymään dynaamisen muistin hallintaan tarkoittaa usein myöskin sitä, että lopullinen kokonaisuus pitää ainakin alustavasti hahmotella ennen kuin varsinaisia kokeiluita päästään edes aloittamaan. Erilaiset laajennokset puolestaan mahdollistavat Symbianympäristön käytön käyttämällä jotakin yksinkertaisempaa ja suoraviivaisempaa tekniikkaa kuin C++-ohjelmointia. 13.8 Yhteenveto Symbian-ympäristö perustuu mikroytimeen ja resursseja hallinnoiviin palvelinkomponentteihin. Monet sulautetun ohjelmoinnin kannalta tärkeät erityispiirteet huomioitu osana ohjelmointityyliä. Tyyppijärjestelmä pakottaa huomioimaan mihin muuttujat allokoidaan muistissa. Oma poikkeuskäsittely, johon yhdistetty oma muistinhallinta, vaatii dynaamisen muistinkulutuksen suunnittelua sekä pinon että keon osalta.
228 Sulautettu ohjelmointi Mahdollisuus toteuttaa sekä irrottava että irrottamaton skedulointi käyttäen joko säikeitä tai aktiivisia olioita. Taustan ymmärtäminen yksinkertaistaa rajoitteiden huomiointia suunnittelutyössä, vaikka osa rajoitteista ei enää nykyisin olekaan samalla tavalla tärkeää matkapuhelimia toteutettaessa. Ympäristön monimutkaisuuden vuoksi useita sovelluskehittäjän työtä yksinkertaistavia laajennoksia saatavilla.