*Tämä artikkeli liittyy tietotekniikkaan. Moniajo voi viitata myös rautatieliikenteessä käytettyyn monivetoon.*
Linux Mint, Xfce, Firefox, laskuohjelma, kalenteri, Vim, GIMP ja VLC media player yhtäaikaisesti käynnissä.
**Moniajo** (engl. *multitasking*) on tietokoneen käyttöjärjestelmän ominaisuus, joka mahdollistaa usean ohjelman ajamisen samanaikaisesti.

Jos tietokoneessa on vain yksi suoritin, moniajo toteutetaan jakamalla suorittimelle tehtäviä nopeasti vaihdellen (näennäisesti rinnakkain), kun taas monisuoritintietokoneessa tehtävät jaetaan usean suorittimen kesken ja voidaan suorittaa aidosti rinnakkaisesti (moniprosessointi).
Tehtävät voivat olla eri prosesseissa tai eri säikeissä: prosessi on suoritettava ohjelma ja säiettä kutsutaan toisinaan *kevyeksi prosessiksi*, joka ei vaadi osoitevaruuden vaihtoa.

Nykyaikaisempia moniajon toimintamalleja ovat *ennakoiva moniajo*, *irrottava moniajo* ja *keskeyttävä moniajo* (engl. *pre-emptive*), jossa käyttöjärjestelmän osa tai prosessi nimeltä vuorontaja ("*skeduleri*", engl. *scheduler*) irrottaa ajossa olevan prosessin suorittimesta, valitsee uuden suoritettavan prosessin valmiustilassa olevien joukosta, antaa suorittimen sen hallintaan ja määrittelee sen saaman aikaviipaleen (engl. *time slice*). Näin vältetään yhteistyömoniajossa oleva ongelma, että yksi huonosti käyttäytyvä ohjelma voi varastaa koneen koko laskentatehon. Vuoronvaihto (engl. *Context switch*) tarkoittaa suorituksessa olevan ohjelman tilan säilömistä toisen ohjelman suorituksen ajaksi: tämä tarkoittaa suorittimen rekisterien arvojen säilömistä muistipinoon.

Suoritukseen annettava aikaviipale voi perustua useisiin eri tekijöihin kuten prosessin prioriteettiin sekä järjestelmän kokonaiskuormitukseen. Odottavalle säikeelle tai ohjelmalle voidaan antaa enemmän suoritusaikaa jotta se vapautuu tilanteestaan mahdollisimman nopeasti ja koska se voi luovuttaa (engl. *yield*) ajoaikansa mikäli odottaminen jatkuu.

Moniajo usein hyödyntää laitteiston keskeytyksiä vuoronvaihtoon, jolloin käyttöjärjestelmälle annetaan vuoro tarvittaessa tai ajoitetusti.

Vähemmän eksaktissa kielenkäytössä käytetään moniajo-termiä myös kuvaamaan sellaista käyttöliittymää, jossa käyttäjä voi vaihtaa "lennossa" usean sovelluksen välillä. Erityisesti termiä käytetään silloin, kun tällaista mahdollisuutta ei ole, ja todetaan virheellisesti, että moniajo puuttuu.

Historia
--------

Moniajon historia alkaa 1960-luvulta, jolloin osituskäyttöjärjestelmät kehitettiin yksittäisten, kalliiden suurtietokoneiden jakamiseksi.

Varhaiset moniajojärjestelmät käyttivät yhteistyömoniajoa, jonka jälkeen kehitettiin keskeyttävä moniajo. Yhteistyömoniajo riippui ohjelmien vapaaehtoisesta vuoron luovuttamisesta. Keskeyttävässä moniajossa laitteistokeskeytys herättää osan ohjelmakoodia, joka pakottaa vuoron vaihtamiseen.

Osituskäyttöön kehitettyjä järjestelmiä olivat muun muassa Compatible Time-Sharing System ja Dartmouth Time Sharing System, joita seurasivat käyttöjärjestelmät kuten Multics ja OS/360MFT.

Käyttöjärjestelmien vaatimukset vaihtelevat: sulautetuissa järjestelmissä ajetaan lähes aina reaaliaikaista käyttöjärjestelmää, jolla on tarkasti määritellyt kiinteät rajoitteet. Reaaliaikaisen käyttöjärjestelmän on vastattava määritellyissä rajoissa tai sen katsotaan epäonnistuneen toisin kuin osituskäyttöjärjestelmä, jossa nopea vasteaika on toivottavaa mutta ei pakollista, tai eräajokäyttöjärjestelmä jossa aikarajoja ei ole lainkaan.

NUMA-muistiarkkitehtuurissa tietokone voidaan käsittää koostuvan eri etäisyyksillä olevista moniprosessointia tukevista "soluista", jotka on kytketty toisiinsa: eri soluissa olevien suorittimien ja muistin välillä on tietty määrä kaistaa ja etäisyys, joka määrittää muistin käytön nopeuden.

Moniytimillisten suorittimien yleistyttyä moniprosessointia hyödyntävä vuoronnus on kiinnittänyt huomiota välimuistin paikallisuuden ja yhtenäisyyden käsittelyyn.

Muita vaikuttavia parametreja ovat energian tarve sekä lämpörajoitukset.

Irrottava/ennakoiva/keskeyttävä moniajo
---------------------------------------

Useimmat *oikeaa* moniajoa tukevat järjestelmät käyttävät *irrottavaa*, *ennakoivaa* tai *keskeyttävää* (engl. *pre-emptive*) moniajoa. Keskeyttävässä moniajossa laitteistokeskeytys herättää osan ohjelmakoodia, joka pakottaa vuoron vaihtamiseen.

Tämän tyyppistä monia käyttävät Unix-tyyppiset käyttöjärjestelmät, mukaan lukien BSD-versiot ja Linux. 
Linux tukee lisäksi ytimen itsensä keskeyttämistä. FreeBSD:ssä on rajattu ytimen keskeyttäminen mutta suunnitelmissa on tehdä siitä täysin keskeytettävä.

Mikrotietokoneissa tämän tyyppistä moniajoa ovat käyttäneet muun muassa AmigaOS Amiga-tietokoneissa (julkaistu 1985).

Myös TRIPOS on käyttänyt irrottavaa moniajoa. IBM siirtyi OS/2:n Warp-versiossa tukemaan ennakoivaa moniajoa.

Yhteistyömoniajo
----------------

*Yhteistyömoniajo* (engl. *Cooperative multitasking, Non-preemptive multitasking*) missä ohjelmat vapaaehtoisesti jakoivat suoritinaikaa toisille ohjelmille oli käytössä mm. RISC OS-käyttöjärjestelmässä ja Windows 95 -käyttöjärjestelmää edeltävät Windows-käyttöjärjestelmät.

OS X -käyttöjärjestelmää edeltävissä Mac OS -järjestelmissä oli myös yhteistyömoniajo. Microsoft siirtyi ennakoivaan moniajoon Windows NT:ssä ja Apple OS X:ssä (BSD-ydin).

OS/2 oli osittain ennakoivaa moniajoa tukeva (Warp-versiot), mutta osin rajattu yhteistyömoniajoon varhaisissa versioissa.

Moniohjelmointi
---------------

Varhaisissa tietokonejärjestelmissä oli niin kutsuttua moniohjelmointikäsittelyä (engl. *multiprogramming*), jossa toiselle ohjelmalle annetaan suoritusaikaa ennen ensimmäisen valmistumista.

Näissä tietokone suorittaa yhtä ohjelmaa kunnes ohjelma pysähtyy odottamaan esimerkiksi laite-IO:ta ja vaihtaa silloin suoritettavaa ohjelmaa.

Joissakin yhteyksissä moniohjelmoinnilla tarkoitetaan myös moniajoa ja eroa moderniin vastineeseen ei tehdä.

Reaaliaikainen
--------------

*Pääartikkeli: Reaaliaikainen käyttöjärjestelmä*
Reaaliaikainen käyttöjärjestelmä perustuu takeeseen vasteajan noudattamisesta. Tämän tyyppinen moniajo voi erota teknisesti merkittävästikin, jotta aikarajattu toiminta (engl. *deadline*) ei ylity missään tilanteessa.

Reaaliaikaisia käyttöjärjestelmiä ovat muun muassa QNX ja VxWorks.

Reaaliaikaiset järjestelmät voidaan jakaa kahteen: pehmeään (toivottu vasteaika) ja kovaan (vaadittu vasteaika). Pehmeässä aikarajan ohittaminen voi olla merkittävä menetys mutta kovassa järjestelmässä epäonnistuminen on katastrofaalinen. Kovan reaaliaikajärjestelmän vasteajat ovat tyypillisesti millisekunteja ja järjestelmän on vastattava ympäristön tapahtumiin. Kovan reaaliaikajärjestelmän vuoronnusta voidaan käyttää myös pehmeään reaaliaikajärjestelmään.

Kovan reaaliaikajärjestelmän vuoronnus voidaan jakaa dynaamiseen ja staattiseen: staattiseen ajoitukseen on tunnettava ennalta parametrit kuten suoritusajat ja aikarajat, mutta suorituksen aikainen kuormitus on pieni.

Kaksi tyypillistä tapaa toteuttaa vuoronnus reaaliaikajärjestelmässä ovat tapahtumapohjainen (engl. *event-driven*) ja aikajakava (engl. *time-sharing*):

* tapahtumapohjaisessa tehtäville jaetaan prioriteetit, joista korkeamman tason prioriteetilla olevat suoritetaan ensin
* aikajakavassa (myös nimellä Round-Robin -vuoronnus) suoritusvuoro kiertää listan mukaan, joka sallii jokaiselle tietyn ennalta määritellyn aikajakson (engl. *time slice*)

Reaaliaikaisessa järjestelmässä vuoronnus voi perustua *kiinteän prioriteetin* (*fixed-priority*) tai *varhaisin aikaraja ensin* (*earliest-deadline first*) malliin. Moniprosessointia tukevat järjestelmät voivat jakaa mallit *globaaleihin*, jossa tehtävät voivat käyttää kaikkia resursseja, sekä *osioituihin*, joissa tehtävät asetetaan kiinteästi tietyille suorittimille.

Reaaliaikaisessa järjestelmässä luotetut sovellukset voivat kytkeä laitteistokeskeytykset pois päältä suojatun alueen käsittelyn ajaksi.

Reaaliaikaisiin käyttöjärjestelmiin on kehitetty useita protokollia prioteettien inversio-ongelman välttämiseksi. Näitä ovat muun muassa *Priority Inheritance Protocol* (PIP), *Priority Ceiling Protocol* (PCP) ja *Stack Resource Policy* (SRP).

Katso myös
----------

* Unix
* Multics

Lähteet
-------

1. 1 2  Arpaci-Dusseau, Remzi H. & Arpaci-Dusseau, Andrea C.: The Abstraction: The Process (PDF) *pages.cs.wisc.edu*. Viitattu 1.3.2020. (englanniksi)
2. 1 2  Arpaci-Dusseau, Remzi H. & Arpaci-Dusseau, Andrea C.: Multiprocessor Scheduling (Advanced) (PDF) *pages.cs.wisc.edu*. Viitattu 1.3.2020. (englanniksi)
3. ↑  Arpaci-Dusseau, Remzi H. & Arpaci-Dusseau, Andrea C.: Scheduling: Introduction (PDF) *pages.cs.wisc.edu*. Viitattu 1.3.2020. (englanniksi)
4. ↑  Nikita Ishkov: A complete guide to Linux process scheduling (PDF) *trepo.tuni.fi*.  2015. Viitattu 1.3.2020. (englanniksi)
5. 1 2 3 4 5  Multitasking Definition *linfo.org*. Viitattu 25.10.2019. (englanniksi)
6. 1 2  *Operating System Concepts*, s. 43. Ninth Edition. Wiley, 2013. ISBN 978-1-118-12938-8.
7. ↑  What is NUMA? *kernel.org*. Viitattu 1.3.2020. (englanniksi)
8. ↑  Nicolas Pitre: Teaching the scheduler about power management *lwn.net*.  18.6.2014. Viitattu 1.3.2020. (englanniksi)
9. ↑  Marta Rybczyńska: Telling the scheduler about thermal pressure *lwn.net*.  16.5.2019. Viitattu 1.3.2020. (englanniksi)
10. ↑  Moniajo *Tut.fi Etäopetus (Web Archive 2011)*.  Arkistoitu 11.11.2011. Viitattu 12.2.2022.
11. ↑  Fagerlund, Kai: Vektorigrafiikan konvertteri (Tutkintotyö Tampereen ammattikorkeakoulussa) *theseus.fi*. Viitattu 2.3.2017.
12. 1 2 3  OS/2 Warp versio 3 IBM. Viitattu 2.3.2017.
13. ↑  What is UNIX The Digital Research Initiative. Viitattu 26.10.2019. (englanniksi)
14. ↑  Robert Love: Lowering Latency in Linux: Introducing a Preemptible Kernel  1.5.2002. Linux Journal. Viitattu 25.10.2019. (englanniksi)
15. ↑  8.3. General Architecture and Design *freebsd.org*. Viitattu 25.10.2019. (englanniksi)
16. ↑  The Micro-AmigaOne and Amiga OS4 Developer Prerelease (Update 1) Ars Technica. Viitattu 28.2.2017.
17. 1 2  Wenz, John: The Cult of Amiga Is Bringing an Obsolete Computer Into the 21st Century Popular Mechanics. Viitattu 4.10.2017.
18. ↑  Thomas B. Steel: Multiprogramming: promise, performance and prospect *dl.acm.org*.  1968. doi:10.1145/1476589.1476607.  Viitattu 26.10.2019. (englanniksi)
19. ↑  Multiprogramming *it.uu.se*. Viitattu 26.10.2019. (englanniksi)
20. ↑  2.3. Processes and Multiprogramming *w3.cs.jmu.edu*.  Arkistoitu 26.10.2019. Viitattu 26.10.2019. (englanniksi)
21. ↑  Benedikt Huber: Real-Time & Embedded Operating Systems (PDF) *ti.tuwien.ac.at*.  2010. Viitattu 25.2.2020. (englanniksi)
22. 1 2 3 4 5  Kanaka Juvva: Real-Time Systems *users.ece.cmu.edu*.  1998. Viitattu 25.2.2020. (englanniksi)
23. ↑  RTOS *udel.edu*. Viitattu 25.10.2019. (englanniksi)
24. ↑  Bjorn B. Brandenburg: Scheduling and Locking in Multiprocessor Real-Time Operating Systems (PDF) *cs.unc.edu*.  2011. Viitattu 26.10.2019. (englanniksi)
25. ↑  Khushu, Sanjeev & Simmons, Johnathan: Scheduling and Synchronization in Embedded Real-Time Operating Systems (PDF) *cseweb.ucsd.edu*. Viitattu 20.2.2017.
26. 1 2  Hierarchical Scheduling of Complex Embedded Real-Time Systems (PDF) *es.mdh.se*. Viitattu 25.2.2020. (englanniksi)