Demystified with a jargon-free exploration.
Usein kuulemme, opimme ja jopa käytämme termejä tai lauseita, joita emme täysin ymmärrä. Minusta tämä on melko yleistä ohjelmistokehitysyhteisössä, olipa kyseessä sitten RESTful Web APIs, ketterät menetelmät, koneoppiminen tai jokin muu termi. Tämä ei välttämättä ole huono asia, mutta on tärkeää ymmärtää, milloin todella tuntee jotain ja milloin vain tietää sen nimen.
Mulle Systems Programming on yksi tällainen termi. Haluaisin yrittää selittää yksinkertaisella kielellä, mitä se tarkoittaa.
Ennen kuin voimme ymmärtää, mitä systeemiohjelmointi tarkoittaa, meidän on ensin ymmärrettävä, mikä on systeemi. Ohjelmistot jaetaan yleensä kahteen leiriin, järjestelmäohjelmistoihin ja sovellusohjelmistoihin.
Järjestelmäohjelmistot ovat tietokoneohjelmistoja, jotka on suunniteltu tarjoamaan alustan muille ohjelmistoille. Järjestelmäohjelmisto sisältää myös laiteajurit, jotka käyttävät tietokoneen peruslaitteita ja oheislaitteita.
– techopedia.comJärjestelmäohjelmisto tarkoittaa tiedostoja ja ohjelmia, joista tietokoneen käyttöjärjestelmä koostuu. Järjestelmätiedostoihin kuuluvat toimintokirjastot, järjestelmäpalvelut, tulostimien ja muiden laitteistojen ajurit, järjestelmäasetukset ja muut määritystiedostot. Järjestelmäohjelmistoon kuuluvia ohjelmia ovat muun muassa assemblerit, kääntäjät, tiedostonhallintatyökalut, järjestelmäapuohjelmat ja debuggerit.
– techterms.com
Wikipedian määritelmä on hyvin epämääräinen sen suhteen, mitä pidetään järjestelmäohjelmistona, kunhan se tarjoaa palveluja muille sovelluksille. Kaksi muuta määritelmää keskittyvät kuitenkin puhtaasti käyttöjärjestelmään – ajureihin, ytimiin, kirjastoihin ja toimintoihin (ajatellaan kernel/libc-otsikkotiedostoja ja jaettuja objekteja). Tämä merkitsee läheistä suhdetta laitteistoon. Jos tarkastelemme toista Wikipedian artikkelia järjestelmäohjelmoinnista, näemme:
Järjestelmäohjelmointi edellyttää suurta tietämystä laitteistosta.
Artikkeli jatkaa vihjaamalla, että keskeinen osa järjestelmäohjelmointia on se, että asioiden on oltava hyvin nopeita. Tämä on järkevää, miksi tarvitsisimme paljon tietoa laitteistosta. On myös järkevää, että nopeus (suorituskyky) olisi keskeinen osa järjestelmäohjelmointia, jos se on alusta muille ohjelmistoille.
Jos sovelluksen keskeisin osa (järjestelmäohjelmiston ”alusta”) on hidas, koko sovellus on hidas. Monille sovelluksille, erityisesti mittakaavassa, tämä olisi ratkaiseva tekijä.
Järjestelmäohjelmisto pähkinänkuoressa
Yllä olevien lainausten ja muiden resurssien perusteella olen päätynyt seuraaviin kriteereihin järjestelmäohjelmiston määrittelemiseksi:
- Sisältää alustan, jonka varaan muut ohjelmistot voidaan rakentaa.
- Suorasti tai läheisesti rajapinnassa tietokonelaitteiston kanssa tarvittavan suorituskyvyn saamiseksi ja abstraktioiden paljastamiseksi (osana alustaa).
Mitä on ja mitä ei ole järjestelmäohjelmisto
Esimerkkejä siitä, mikä on järjestelmäohjelmisto:
- OS-ytimet
- Ajurit
- Paljaan metallin hypervisorit (esim.g. Hyper-V ja VM Ware ESXi)
- Kääntäjät (jotka tuottavat natiiveja binäärejä) ja debuggerit
Esimerkkejä siitä, mikä ei ole järjestelmäohjelmisto:
- GUI Chat-sovellus (Slack, Discord jne.)
- Web-pohjainen JavaScript-sovellus
- Web Service API
Huomaa, että vaikka Web Service API:t tarjoavat palvelua toisille ohjelmistoille, ne eivät (tyypillisesti) ole vuorovaikutuksessa laitteiston kanssa paljastaakseen abstraktioita laitteiston yli. On kuitenkin olemassa sovelluksia, jotka kuuluvat keskimmäiselle harmaalle alueelle. Mieleen tulevat suurteholaskentasovellukset ja sulautetut ohjelmistot.
Teholaskentasovellukset (HPC-sovellukset), kuten reaaliaikainen kaupankäynti pörsseissä, eivät tyypillisesti paljasta alustaa, mutta niissä on tavallista kirjoittaa koodia, joka on suoraan yhteydessä laitteistoon. Esimerkkinä voidaan mainita ytimen tarjoaman verkkopinon ohittaminen ja oman verkkopinon toteuttaminen, joka puhuu suoraan verkkokortin (korttien) kanssa. Näin voidaan nähdä, että HPC-ohjelmistoilla on monia yhtäläisyyksiä järjestelmäohjelmistojen kanssa, sillä ne toimivat suoraan vuorovaikutuksessa laitteiston kanssa, jotta saadaan aikaan tarvittava suorituskykyhyöty.
Embedded-ohjelmistokehityksessä on myös monia yhtäläisyyksiä järjestelmäohjelmistojen kanssa, sillä koodia kirjoitetaan niin, että se toimii suoraan rajapinnassa laitteiston kanssa. Kaikki tarjotut abstraktiot ovat kuitenkin tyypillisesti saman ohjelmiston käyttämiä, eikä niitä voida pitää alustana.
On tärkeää huomioida sovellukset, joilla on yhtäläisyyksiä järjestelmäohjelmiston määritelmämme kanssa, koska näet todennäköisesti, että näitä sovelluksia/työtehtäviä kuvataan näillä termeillä (järjestelmäohjelmistot, järjestelmäinsinöörit jne.)
Systeemien ohjelmointi (+ kielet)
Systeemien määrittelyn jälkeen voimme määritellä systeemien ohjelmoinnin systeemien ohjelmistojen luomiseksi systeemien ohjelmointikieliä käyttäen. Riittävän yksinkertaista, eikö?
Nyt yksi asia jäi huomaamatta, kielet. Ihmiset puhuvat usein systeemiohjelmointikielistä tyyliin ”X on hieno, se on nopea, käännetty ja systeemiohjelmointikieli”. Mutta ovatko kaikki samoilla linjoilla siitä, mitä järjestelmäohjelmointikieli on?
Systeemien määritelmiemme perusteella määrittelisin järjestelmäohjelmointikielen kriteereiksi:
- Kompiloitu natiiviksi binäärikieleksi
- Voidaan rakentaa ilman riippuvuuksia muista ohjelmistoista (mukaan lukien ydin)
- Suorituskykyominaisuuksiltaan samankaltainen kuin muut järjestelmäohjelmointikielet
Disclaimeri: Tämä on minun määritelmäni. Koska ei ole olemassa määrättyjä kriteerejä, johdan määritelmän siitä, mikä minusta on järkevää, kun otetaan huomioon asiayhteys, jossa olen määritellyt järjestelmäohjelmiston.
Kompiloi natiiviksi binäärikieleksi
Jos kieli ei voi kääntää suoritettavaksi ohjelmaksi, joka on suoraan prosessorin tulkittavissa, niin se on määritelmän mukaan alustalla suoritettava kieli (esim. JVM, Ruby VM, Python VM, jne). Tähän voi olla perusteluja, mutta yksinkertaisuuden vuoksi pidän tätä sopivana kriteerinä.
Ei riippuvuuksia
Väite on samanlainen kuin kääntäminen natiiviin binääritiedostoon. Jos kieli vaatii aina jonkin muun ohjelmiston läsnäoloa suorittaakseen sen, se toimii alustalla. Esimerkki tästä on Go ja sen mukana tuleva standardikirjasto. Se vaatii käyttöjärjestelmän tukea suorittaakseen perustoimintoja, kuten muistin varaamista, säikeiden luomista (goroutiineja varten), sen sisäänrakennettua verkkokyselyä ja muita toimintoja varten. Vaikka nämä ydintoiminnot on mahdollista toteuttaa uudelleen, se luo esteen niiden käytölle tässä yhteydessä, ja on helppo kuvitella, miksi kaikkia kieliä, edes niitä, jotka käännetään staattisiksi binääreiksi, ei ole tarkoitettu järjestelmäohjelmointikieliksi.
Samankaltaiset suorituskykyominaisuudet
Tämä on hiukan väistämätöntä. Sen tarkoituksena on kuitenkin sanoa, että järjestelmäohjelmointikieliksi tyypillisesti luokiteltujen kielten järjestelmässä ei pitäisi olla suuria (suuruusluokkien) eroja suorituskykyominaisuuksissa. Ominaisuuksilla tarkoitan nimenomaan suoritusnopeutta ja muistitehokkuutta.
Vertailun kultainen standardi on C ja/tai C++, kuten usein esitetään vertailevissa vertailuanalyyseissä, joissa suoritusnopeutta mitataan sillä, kuinka monta suuruusluokkaa hitaampia kielet ovat kuin C/C++.
Nimimerkkejä
Kielet, jotka tulevat heti mieleen edellä olevan määritelmän perusteella, ovat C ja C++. Mutta on myös uudempia kieliä, kuten Rust ja Nim, jotka myös täyttävät tämän markkinaraon. Itse asiassa on jo olemassa kokonaan Rustilla kirjoitettu käyttöjärjestelmä (RedoxOS) ja Nimillä kirjoitettu ydin (nimkernel).
Puhutaan Go:sta
Viittasin aiemmin siihen, että Go ei ehkä kuulu ”järjestelmäohjelmointikielten” perheeseen. Kuitenkin, aivan kuten kaikki sovellukset eivät sovi hienosti sovellusohjelmiin ja järjestelmäohjelmiin, eivät myöskään kielet.
Tiheästi Go:ta kutsutaan järjestelmäohjelmointikieleksi, ja jopa golang.org:ssa siteerataan:
Go on yleiskäyttöinen kieli, joka on suunniteltu järjestelmäohjelmointia silmällä pitäen.
Tämäkään ei kuitenkaan ole suoranainen väite siitä, että Go:ta kutsutaan järjestelmäohjelmointikieleksi, vaan yksinkertaisesti siitä, että se on suunniteltu sitä silmällä pitäen. Minusta se istuu pikemminkin keskellä.
Vaikka Go kääntää natiivit binääritiedostot, sisältää hyödyllisiä matalan tason käsitteitä (raa’at/epävarmat osoittimet, natiivit tyypit, kuten bytes ja int32, ja rivikokoonpanotuki), ja se on suhteellisen suorituskykyinen; sillä on silti joitakin haasteita voitettavana. Go:n mukana toimitetaan ajoaika ja roskienkerääjä.
Ajoaika tarkoittaa, että ajoajan käynnistäminen/ylittäminen on tarpeen, jotta sitä voidaan käyttää ympäristöissä, joissa ei ole ytimiä. Tämä menee enemmän kielen sisäiseen toteutukseen, joka voi muuttua tulevissa versioissa. Muutokset vaativat ylimääräistä bootstrapping-työtä kielen kehittyessä.
Garbage collector (GC) tarkoittaa joko sitä, että Go:ta rajoitetaan siinä, missä sovellusalueilla sitä voidaan käyttää, tai että GC on poistettava käytöstä ja korvattava manuaalisella muistinhallinnalla. Siinä tapauksessa, että GC:tä ei voida korvata, reaaliaikaisella toimialueella (joka määritellään operaatioilla, joiden on valmistuttava tietyissä aikarajoissa ja/tai suorituskyky mitataan nanosekunneissa) ei voida ottaa riskiä GC:n epädeterministisistä taukoajoista.
Distributed Systems Software
Kun yhä useammin puhutaan hajautetuista järjestelmistä ja Kubernetesin kaltaisista sovelluksista on tulossa hyvin suosittuja, saamme kuulla runsaasti uutta sanastoa, jota (jos rehellisiä ollaan) suurin osa meistä ei ymmärrä täysin.
Tässä vaiheessa olen nähnyt termejä järjestelmäohjelmointi ja järjestelmäinsinöörit käytettävän yhteyksissä, joissa oikeasti tarkoitettiin hajautettujen järjestelmien ohjelmointia ja hajautettujen järjestelmien insinöörejä.
Tässä postauksessa olemme määritelleet järjestelmäohjelmistot, järjestelmäkielet ja järjestelmäohjelmoinnin. Kun puhumme kuitenkin hajautetuista järjestelmistä, järjestelmän merkitys muuttuu. Ja vaikka en aio sukeltaa tässä erityisiin eroihin (lähinnä siksi, että minun on vielä itse ymmärrettävä ne paremmin), on tärkeää, että teemme nämä mentaaliset erot ja käytämme tarkempaa puhetta silloin, kun se on mahdollista, jotta vältymme sekaannukselta niille, jotka vielä opettelevat tätä aluetta.