UNIX-ohjelmointiympäristön erityispiirteitä

Ensimmänen versio 2.10.2009

Kai Lassfolk

Johdanto

Tämä ohje on tarkoitettu musiikkitieteen Musiikkiohjelmoiti I -kurssin esimerkkiohjelmien tueksi UNIX-ohjelmointiympäristön erityispiirteiden esittelyyn. Ohje on tarkoitettu UNIX:in ja UNIX-yhteensopivien ympäristöjen (Linux, Mac OS X, Cygwin) esittelyyn.

Unixin perinteinen käyttöliittymä on komentotulkki (engl. Command Line Interpreter), jota käytetään tekstipohjaisilla, näppäimistöltä syötetyillä komennoilla. Myös ruudulle tulevat tulosteet ovat pääosin tekstimuotoisia. Hiirtä tarvitaan periaatteessa vain komentotulkkiohjelman eli pääte-emulaatioohjelman (Terminal emulator) käynnistämiseen. Pääte-emulaatio ohjelma jäljittelee 1970- ja 1980-luvuilla käytetyn, näppäimistöllä ja kuvaruudulla varustetun näyttöpäätteen toimintaa.

Pääte-emulaatioohjelma on esimerkiksi Linuxissa ja Mac OS X:ssä Terminal-niminen. Macissa se löytyy Applications-kansion (suom. Ohjelmat) alikansiosta nimeltä Utilities (Lisäohjelmat). Jos pääteohjelmaa käyttää usein, se kannattaa viedä ohjelmalaiturille (Dock). Eri Linux jakeluissa Terminal (suom. Pääte tms.) löytyy selaamalla sovellusvalikoita.

Komentotulkki ja peruskomennot

Unixissa tiedostojen ja hakemistojen luominen, muokkaus, nimeäminen ja organisointi tapahtuu komentojen avulla. (Hakemisto on Unixin "kansiota" vastaava termi, ts. tiedostojen eli dokumenttien säilytyspaikka.) Pääteohjelma käynnistää automaattisesti ns. komentotulkin, joka tulkitsee käyttäjän syöttämät komennot, käynnistää niiden perusteella ohjelmia (l. komentoja) ja välittää näille käyttäjän syöttämiä parametreja. Käynnistyessään komentotulkki tulostaa ruudulle muutaman merkin mittaisen, ns. kehotteen (engl. prompt) merkiksi siitä, että se on valmis ottamaan vastaan käyttäjän komentoja. Tyypillisesti komento syötetään komentotulkille yhtenä tekstirivinä, jonka lopussa painetaan rivinsiirtonäppäintä. Tämän jälkeen komentotulkki tulkitsee tämän ns. komentorivin ja käynnistää tarvittavan ohjelman. Ohjelman suorituksen päätettyä komentotulkki tulostaa uuden kehotteen merkiksi suorituksen päättymisestä.

Itse komennot ovat muutaman merkin mittaisia. Tyypillisesti yleisimmin käytetyt komennot ovat lyhyitä, 2-5 merkin mittaisia kirjainlyhenteitä ja harvemmin käytetyt pidempiä, joskus selväkielisiäkin sanoja.

Tärkeimmät yleiset komennot ovat

Esimerkiksi ls-komentoa käytetään yksinkertaisimmillaan vain kirjoittamalla pääteelle:
	ls
ja painamalla rivinsiirtoa. Tällöin ruudulle tulostuu lista tiedostojen hakemistojen nimistä. Lisää tietoa hakemiston sisällöstä saa lisäämällä komentoon ns. option -l, ts.
	ls -l
Option aloitusmerkki on väliviiva (-). Optiot voivat olla joko yhden merkin mittaisia tai useamman merkin mittaisia, joskus kokoneisia sanoja tai yhdyssanoja. Perinteisesti Unixissa käytettiin yksimerkkisiä optioita, mutta monimerkkiset optiot ovat yleistyneet varsinkin Linuxissa. Joissakin ohjelmissa voi vaihtoehtoisesti käyttää yksi- tai monimerkkisiä optioita. Joskus monimerkkisten optioiden aloitusmerkkinä on +. Yksimerkkisiä optioita voi joskus myös yhdistää, varsinkin vanhimmissa Unix-komennoissa. Esimerkiksi komento ls -lR tulostaa "rekursiivisesti" hakemiston ja kaikkien sen alihakemistojen sisällön.

Optioiden lisäksi komennoille voi syöttää muita parametreja, joita kutsutaan Unix-terminologiassa argumenteiksi. Argumenttina voi olla esimerkiksi käsiteltävän tiedoston tai hakemiston nimi. Esimerkiksi komento

	mkdir koe
luo uuden hakemiston nimeltä koe. "koe" on siis komennon mkdir argumentti. Puolestaan komento
	cd koe
siirtää käyttäjän hakemistoon koe. Tarkemmin määriteltynä komento vaihtaa käyttäjän ns. nykyhakemiston eli työskentelyhakemiston (engl. current directory ja working directory).

Kun pääteohjelma käynnistyy, työskentelyhakemistona on yleensä käyttäjän kotihakemisto (home directory tai vain "home"). Tänne käyttäjä voi luoda omia alihakemistoja, ja luoda niihin tiedostoja. Kotihakemisto sijaitsee Unixin hierakkisessa hakemistopuussa, jolla on yhteinen juuri (root).

Tyypillinen, lyhyt työskentelysessio alkaa pääteohjelman käynnistämisellä, jatkuu uuden hakemiston luomisella (mkdir), siirtymisellä sinne (cd), tiedostojen luomisella ja muokkauksella joillakin käyttötarkoitukseen soveltuvilla komennnoilla, ylimääräisten tiedostojen hävittämisellä (komento rm), ja päättyy pääteohjelman sulkemisella.

Komentojen käytöstä saa lisätietoa niiden dokumentaatiosta, jonka perinteinden muoto on Unixissa ns. man-sivu (man page, so. manual page). Sen voi tulostaa kuvaruudulle komennolla man, jonka argumentiksi kirjoitetaan halutun komennon nimi, esimerkiksi

	man ls
Man-sivulla on selostettu komennon kutsusyntaksi (ts. missä järjestyksessä ja muodossa optiot ja argumentit kirjoitetaan), sekä optioiden ja argumenttien käyttö. Itse man-komennon man-sivu tulostuu komennolla
	man man
Kaikista, erityisesti uudemmista tai erikoisesmmista komennoista ei ole kirjoitettu man-sivua. Niissä dokumentaatioteksti on usein tulostettavissa ns. help-option avulla, tyypillisesti joko "-h" tai "-help". Esimerkiksi komento
	xyz -h
tulostaisi kuvitteellisen komennon xyz help-tekstin. Unix-komennot tulostavat myös yleensä lyhyen, ns. usage-viestin, jos niille annetaan vääränlaisia optioita tai argumentteja. Usage-viesti on tyypillisesti vain rivin tai kahden mittainen ilmoitus oikeasta kutsutavasta.

Tässä on lista keskeisistä Unix-komennoista, joihin voi perehtyä man-sivujen avulla:

Nykyaikaisissa, ikkunoiduissa käyttöliittymissä pääteohjelmia voi avata samanaikaisesti useita, jolloin yhdessä ikkunassa voi esimerkiksi suorittaa komentoja ja toisessa lukea samanaikasesti komentojen man-sivuja. Useaa paaäteohjelmaa käytettäessä pitää muistaa, että ohjelmat ovat itsenäisiä. Esimerkiksi nykyhakemiston vaihto yhdessä ikkunassa ei vaikukuta muihin avoinna oleviin pääteohjelmiin. Useimmiten tämä on etu, koska käyttäjä voi samanaikaisesti työskennellä monessa hakemistossa.

Jokerimerkit

Unixissa on jokerimerkkejä voi hyödyntää varsin monipuolisesti sekä komentotulkissa että monien komentojen parametreissa. Yleisemmin Unixin jokerimerkkijärjestelmää kutsutaan säännöllisiksi lausekkeiksi (regular exporessions). Näistä yleisin on asteriski (*), joka korvaa yhden tai useamman merkin. Esimerkiksi komento
	rm a*
poistaa hakemistosta kaikki tiedostot, joiden nimi alkaa a-kirjaimella. Jokerimerkki ? korvaa puolestaan yhden mielivaltaisen merkin. Esimerkiksi komento
	rm versio?
hävittää hakemistosta tiedostot joiden nimi alkaa tekstillä "versio" ja jota seuraa mikä tahansa yksi merkki. Kuitenkin esimerkiksi tiedosto "versio10" jäisi hävittämättä, koska siinä on lopussa vielä ylimääräinen merkki. Tähän täsmäisi lauseke "versio??" tai "versio*".

C-ohjelmien kääntäminen

C-kielisten ohjelmien kääntäminen suorituskelpoisiksi tapahtuu C-kääntäjällä, joka komento on cc. Sen argumentiksi annetaan lähdekielisen C-ohjelman tiedoston nimi, esimerkiksi:
	cc koe.c
jossa koe.c on jonkin C-ohjelman lähdekooditiedosto. Ennen kääntämistä C-ohjelma on joko kirjoitettava tai kopioitava jostakin. C-ohjelmien kirjoittaminen tapahtuu tyypillisesti jollakin tekstieditorilla, ohjelmalla, jolla voi kirjoittaa muotoilemattomia tekstitiedostoja. Tällaisia ovat Unixissa esim. Emacs, vi ja pico. Näistä vasta-alkajille helpoin on pico. Se käynnistyy komennolla pico, ja sille voi antaa argumentiksi kirjoitettavan ohjelman tiedostonnimen. Esimerkiksi:
	pico koe.c
Pico tulostaa ruudun alalaitaan listan tärkeimmistä komennoista. Niissä ^-merkki tarkoittaa Control-näppäintä (merkitty näppäimistöön yleensä tekstillä ctrl). Control on muutenkin Unixissa tärkeä näppäin, jolla ohjataan pääteohjelman ja komentojen toimintaa.

C-ohjelmien syöttö- ja tulostusfunktiot

C-kielessä aliohjelmia kutsutaan funktioiksi (engl. function). Keskeiset tiedon syöttöön ja tulostukseen (sekä tiedostojen käsittelyyn) liittyvät fuktiot voidaan ryhmitellä kahteen pääkategoriaan:
  1. Korkean tason ns. standardisyöttö- ja tulostusfunktiot
  2. Matalan tason ns. systeemikutsut
Näistä korkean tason funktiot ovat monipuolisempia, helppokäyttöisempiä ja siirrettäviä (muihinkin kuin Unix-yhteensopiviin käyttöjärjestelmiin). Systeemikutsut ovat puolestaan (oikein käytettynä) tehokkaampia ja läheisemmin sidoksissa käyttöjärjestelmään. Tyypillisesti korkean tason funktiot on rakennettu systeemikutsujen "päälle". Lisätietoa funktioiden käytöstä saa man komennon avulla, esim "man printf". Man-sivut on jaoteltu lukuihin (chapter), joista luku 1 on varattu komennoille, luku 2 systeemikutsuille ja luku 3 korkean tason funktioille. Joskus järjestelmässä voi olla samanniminen komento ja systeemikutsu (tai funktio). Tällöin oikean man-sivun saa tulostettua antamalla man-komennolle ensimmäiseksi argumentiksi luvun numeron ja toiseksi komennon tai funktion nimen. Esimerkiksi
	man 2 write
tulostaa systeemikutsu write:n man-sivun, ei write-komennon (jos järjestelmässä on tälläinen komento). Jos luvun numeroa ei anna, man etsii man-sivua ensin luvusta 1, sitten luvusta 2 jne. ja tulostaa ensimmäisen löytyneen sivun.

Optioiden ja argumenttien välittäminen komentotulkista C-ohjelmaan

Optioiden ja argumenttien välittäminen komentotulkista C-ohjelmaan tapahtuu C-kielen main-funktion kautta. Main saa parametrinaan kaksiulotteisen merkkijonotaulukon ja taulukon koon kertovan kokonaisluvun. Nämä nimetään yleensä seuraavasti:
    int main(int argc, char *argv[])
    {
        ...
    }
Siinä argc on komentoriviparametrien määrä (mukaan luettuna itse komennon nimi) ja argv on taulukko, jonka alkioina ovat komentoriviparametrit erillisinä merkkijonoina siinä järjestyksessä kuin ne ovat komentorivillä. Esimerkiksi komennon
	cp vanha uusi
parametrit ovat:
    argc = 3
    argv[0] = "cp"   (ts. komennon nimi)
    argv[1] = "vanha"
    argv[2] = "uusi"
Jos komennolle halutaan välittää parametreina numeerisia arvoja, nämä on muunnettava merkkijonomuodosta numeeriseen muotoon, esimerkiksi kokonais- tai liukuluvuiksi. Tähän käytetään tyypillisesti sscanf-funktiota (ks. man sscanf).