# Toepassingen hosten

## Analyse

Aan een besturingssysteem op zichzelf is niet zoveel aan. Wat een OS geweldig maakt, zijn de toepassingen die er onder kunnen worden uitgevoerd. Helaas biedt de Pocket Distributie thans niet veel meer ruimte voor iets anders dan systeemprogramma's. Toch zou het aardig zijn het systeem net voldoende uit te breiden dat er een aantal gave toepassingen op zouden kunnen worden gehost. Uiteraard kan er geen sprake zijn van een volledig opgetuigde X-Window GUI, maar de uitvoering van een klein op de console gebaseerd programma ligt binnen handbereik.

In plaats van als voorbeeld een typisch "hello world" programma te geven, zal het hosten van toepassingen worden gedemonstreerd met een op de console gebaseerde audiospeler genaamd mp3blaster. Het bouwen van mp3blaster biedt een technischer uitdaging dan "hello world" en het voltooide product is een stuk leuker. Er mag echter niet uit worden afgeleid dat een console geöriënteerde jukebox de enige toepassing voor Pocket Linux is. Integendeel, na het voltooien van deze fase zou de lezer de kennis en tools hebben om vrijwel elk console geöriënteerd programma dat hij of zij wenst te bouwen.

Dus wat is er voor nodig om een GNU/Linux systeem in zakformaat om te zetten in een mp3-speler? Een paar dingen worden hieronder opgesomd.

- Voeg ondersteuning toe voor audio-hardware.

- Creëer ruimte voor het mp3blaster programma.

- Voorzie in een handige manier om audiobestanden te benaderen.

## Ontwerp

### Ondersteuning voor audio-hardware

Er is een snelle toename van audiohardware op de markt en elke geluidskaart heeft zijn eigen specifieke configuratie. Voor details over het instellen van een bepaalde geluidskaart kunnen we ons wenden tot de Sound-HOWTO beschikbaar vanaf het Linux Documentatie Project op http://www.tldp.org. In bredere zin kunnen we een geluidskaart echter net als elk ander stukje nieuwe hardware behandelen. Om hardware aan het GNU/Linux systeem toe te voegen, zullen we de kernel moeten configureren dat het 't herkent en `/dev` bestanden op de rootdisk moeten configureren om het te kunnen benaderen.

#### Kernelondersteuning voor audio

Voor ondersteuning van geluidskaarten, zal een nieuwe kernel moeten worden gecompileerd. Het is van groot belang dat de ondersteuning voor audio-hardware als vast onderdeel van de kernel wordt geconfigureerd, omdat de Pocket Distributie niet is ingesteld op de afhandeling van kernelmodules.

#### Rootdisk-ondersteuning voor audio

Het doorzoeken van `devices.txt` op het trefwoord "sound" geeft een opsomming van flink wat audio-devices, maar gewoonlijk zijn alleen `/dev/dsp` en `/dev/mixer` nodig om geluid uit een PC te krijgen. Deze twee bestanden besturen respectievelijk de digitale audio-uitvoer en mixer-controls.

### Ruimte voor het programma vrijmaken

Waarschijnlijk de makkelijkste manier om meer ruimte voor het mp3blaster programma te creëeren is door een extra opslagdevice te mounten. Voor mountpoints hebben we verscheidene keuzes. Tot dusverre zijn `/usr`,`/home` en `/opt` allen lege directory's en elk daarvan kunnen worden gebruikt om een diskette, CD-ROM of een extra gecomprimeerd ramdiskimage te mounten. De `/usr` directory is een logische keuze voor een lokatie om een toepassing in te plaatsen, maar hoe zit het met de mediakeuze? Mp3blaster en de daarbijbehorende benodigde library's zijn te groot voor een 1.44M diskette en het branden van een CD-ROM lijkt nogal wat werk voor een klein programma. Dus gegeven deze beperkingen, zou de beste keuze zijn om het programma op een gecomprimeerde diskette te plaatsen.

#### Mounten van extra gecomprimeerde diskettes

Het mounten van CD's en ongecomprimeerde diskettes is makkelijk, maar hoe zit het met het laden van gecomprimeerde images van diskette naar ramdisk? Het zal handmatig moeten worden gedaan, omdat automatisch mounten van gecomprimeerde diskettes alleen werkt voor de rootdiskette. En het gebruik van `mount /dev/fd0` zal niet werken omdat er geen bestandssysteem op de diskette is, er is alleen de inhoud van een gzip bestand. Het werkelijke bestandssysteem bevindt zich in het gzip bestand. Dus hoe kunnen we het bestandssysteem mounten dat is verborgen in het gzip bestand? Deze puzzel kan worden opgelost door de stappen te bestuderen die werden gebruikt om de bekende gecomprimeerde rootdisk diskette aan te maken.

1. Een ramdisk wordt aangemaakt, gemount en gevuld met bestanden.

2. Het ramdisk-device wordt met umount ontkoppeld.

3. De inhoud van de ramdisk wordt met behulp van `dd` naar een image-bestand weggeschreven.

4. Het image-bestand wrodt gecomprimeerd met `gzip`.

5. Het gecomprimeerde image-bestand wrodt naar diskette weggeschreven met `dd`.

Als dat de weg is die het gecomprimeerde image aflegt van ramdisk naar de gecomprimeerde diskette, dan zou het afleggen van de weg van een gecomprimeerde diskette naar ramdisk zo simpel zijn als het omgekeerd doorlopen van de stappen.

1. Het gecomprimeerde image-bestand wordt gelezen van diskette met `dd`.

2. Het image-bestand wordt gedecomprimeerd met `gunzip`.

3. De inhoud van het image-bestand wordt in ramdisk gedumpt met behulp van `dd`.

4. Het ramdisk-device wordt gemount.

5. De bestanden zijn beschikbaar.

We kunnen het tussenliggende image-bestand eruit knippen door gebruik te maken van een pipe om `dd` en `gunzip` als volgt te combineren: `dd if=/dev/fd0 | gunzip -cq > /dev/ram1`. Nu gaat de gecomprimeerde diskette rechtstreeks naar de ramdisk, het onderwijl decomprimerend.

#### Rootdisk-ondersteuning voor extra ramdisks

We hebben reeds ondersteuning voor ramdisks in de kernel, omdat we gebruik maken van een gecomprimeerde rootdisk, maar we zullen meer ramdisks in `/dev` nodig hebben. De kernel ondersteunt acht ramdisks van `/dev/ram0` tot en met `/dev/ram7` waarbij `ram0` wordt gebruikt voor de rootdisk. Het bestand `devices.txt` opgenomen in de documentatie van de Linux broncode zal behulpzaam zijn voor het evenaren van devices met hun major en minor nummers.

### Benaderen van audio-bestanden

Het voorbeeld mp3 bestand dat we in ons voorbeeld zullen gebruiken is klein genoeg dat het op een ongecomprimeerde diskette past zodat het niet nodig is een CD te branden. Serieuze muziekliefhebbers willen echter wellicht de mogelijkheid hebben om een aangepaste CD-ROM vol met melodieën te mounten en die optie vereist ondersteuning voor extra hardware.

#### CD-ROM hardware-ondersteuning

De meeste moderne CD-ROM stations zullen gebruik maken van IDE-devices, zoals `/dev/hdc` of `/dev/hdd`. Ter ondersteuning van deze CD-ROM stations zullen we ondersteuning voor IDE in de kernel moeten configureren en de van toepassing zijnde devicebestanden op de rootdisk aanmaken.

#### Ondersteuning voor het CD-ROM bestandssysteem

Op CD-ROM's worden andere bestandssystemen geplaatst dan op harddisks en diskettes. De meeste CD brandertoepassingen gebruiken een bestandssysteem met de naam ISO-9660 en hebben de mogelijkheid tot ondersteuning van joliet en rockridge extensies. We zullen ondersteuning voor deze bestandssystemen in de kernel op moeten nemen om CD-ROM's te kunnen mounten.

### Andere benodigde bestanden

We zullen alle benodigde library's en andere ondersteunende bestanden beschikbaar hebben als onderdeel van het gecomprimeerde `/usr` image zodat mp3blaster correct kan worden uitgevoerd. De bekende `ldd` opdracht kan worden gebruikt om vast te stellen welke library's mp3blaster nodig heeft. Extra library's kunnen worden geplaatst in `/usr/lib`. Ook al verschijnen op het ontwikkelaarssysteem een aantal library's in `/lib`, dan nog kunnen ze op het Pocket Linux systeem in `/usr/lib` worden geplaatst. De linker is slim genoeg dat het bij het laden van library's op beide plaatsen kijkt.

Omdat mp3blaster de curses (of ncurses) schermbesturingslibrary gebruikt, hebben we nog één extra bestand nodig. De curses library moet weten wat de karakteristieken van de terminal zijn die het bestuurt en het haalt die informatie uit de terminfo database. De terminfo database bestaat uit alle bestanden onder de directory `/usr/share/terminfo` en is nogal groot in vergelijking met onze beschikbare diskruimte. Maar gezien Pocket Linux alleen de PC console ondersteunt, hoeven we ons alleen bezig te houden met één type terminal en hebben daarom slechts één bestand nodig. Het stukje van de terminfo database dat we nodig hebben is het bestand `/usr/share/terminfo/l/linux`, omdat we gebruik maken van een "Linux" terminal. Zie voor meer informatie over curses, John Strang's boek getiteld "Programming with Curses" beschikbaar bij O'Reilly publishing op http://www.oreilly.com.

### Samenvatting van taken

Tussen geluidskaarten, ramdisks, CD-ROM's en terminfo is aardig wat bij te houden. Dus laten we een moment nemen om de taken die nodig zijn te organiseren en samenvatten om de pocket jukebox te realiseren.

- Maak een nieuwe kerneldisk aan waarin ondersteuning is opgenomen voor audio-hardware, IDE-devices en CD-ROM bestandssystemen.

- Maak de van toepassing zijnde `/dev` bestanden aan op de rootdisk voor de ondersteuning van audio-hardware, extra ramdisks en IDE CD-ROM's.

- Maak een opstartscript om een gecomprimeerd image van diskette in ramdisk te laden en mount de ramdisk op `/usr`.

- Maak een gecomprimeerde diskette waarop het mp3blaster programma wordt geplaatst met de bijbehorende library's en terminfo bestanden.

## Constructie

### Maak een bootdisk aan

#### Compileer een nieuwe kernel

    bash# cd /usr/src/linux
    bash# make menuconfig

Configureer ondersteuning voor het volgende:

- 386 processor

- Floppy disk

- RAM disk

- Virtual console

- Audio hardware

- CD-ROM hardware

- ISO-9660 en Joliet bestandssystemen

    bash# make dep
    bash# make clean
    bash# make bzImage

#### Kopieer de kernel naar diskette

Plaats de bootdisk in station fd0

    bash# cp /usr/src/linux/arch/i386/boot/bzImage /mnt/boot/vmlinuz
    bash# mount /dev/fd0 /mnt

#### Installeer de LILO bootloader

    bash# lilo -r /mnt

#### Ontkoppel de bootdisk

    bash# cd /
    bash# umount /mnt
    bash# sync

### Maak een rootdisk aan

#### Maak extra devicebestanden aan

##### IDE CD-ROM

    bash# mknod -m640 ~/fase/dev/hdc b 22 0
    bash# mknod -m640 ~/fase/dev/hdd b 22 64

Maak optioneel IDE-devices aan.

##### Ramdisk

    bash# mknod -m 640 ~/fase/dev/ram1 b 1 1
    bash# mknod -m 640 ~/fase/dev/ram2 b 1 2
    bash# mknod -m 640 ~/fase/dev/ram3 b 1 3
    bash# mknod -m 640 ~/fase/dev/ram4 b 1 4
    bash# mknod -m 640 ~/fase/dev/ram5 b 1 5
    bash# mknod -m 640 ~/fase/dev/ram6 b 1 6
    bash# mknod -m 640 ~/fase/dev/ram7 b 1 7

##### Audio

    bash# mknod -m664 ~/fase/dev/dsp c 14 3
    bash# mknod -m664 ~/fase/dev/mixer c 14 0

#### Schrijf een opstartscript om een gecomprimeerde diskette te mounten

Gebruik een teksteditor voor het aanmaken van het volgende script en sla het op als `~/fase/etc/init.d/usr_image`

    #!/bin/sh
    #
    # usr_image - laad gecomprimeerde images van diskette in ramdisk en
    #       mount op /usr.
    #
    echo -n "Is there a compressed diskette to load for /usr [y/N]? "
    read REPLY
    if [ "$REPLY" = "y" ] || [ "$REPLY" = "Y" ]; then
      echo -n "Please insert the /usr floppy into fd0 and press <ENTER>."
      read REPLY
      echo "Clearing /dev/ram1."
      dd if=/dev/zero of=/dev/ram1 bs=1k count=4096
      echo "Loading compressed image from /dev/fd0 into /dev/ram1..."
      (dd if=/dev/fd0 bs=1k | gunzip -cq) >/dev/ram1 2>/dev/null
      fsck -fp /dev/ram1
      if [ $(($?)) -gt $((1)) ]; then
        echo "Filesystem errors on /dev/ram1!  Manual intervention required."
      else
        echo "Mounting /usr."
        mount /dev/ram1 /usr
      fi
    fi
    #
    # end of usr_image

Configureer het script zo dat het direct nadat root is gemount wordt uitgevoerd.

    bash# ln -s ../init.d/usr_image ~/fase/etc/rcS.d/S21usr_image

#### Maak een gecomprimeerde rootdisk aan

    bash# cd /
    bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
    bash# mke2fs -m0 /dev/ram7
    bash# mount /dev/ram7 /mnt
    bash# cp -dpR ~/fase/* /mnt
    bash# umount /dev/ram7
    bash# dd if=/dev/ram7 of=~/phase8-image bs=1k
    bash# gzip -9 ~/phase8-image

Doe de diskette met het label "rootdisk" in station fd0.

    bash# dd if=~/phase8-image.gz of=/dev/fd0 bs=1k

#### Ontkoppel de rootdisk

    bash# cd /
    bash# umount /mnt
    bash# sync

### Maak voor mp3blaster een gecomprimeerde /usr disk

De gecomprimeerde /usr diskette zal worden aangemaakt aan de hand van hetzelfde proces dat werd gebruikt om de gecomprimeerde rootdisk aan te maken. We zullen bestanden naar een fasegebied kopiëren, het fasegebied naar ramdisk kopiëren, de ramdisk comprimeren en het naar diskette wegschrijven.

#### Aanmaken van het fasegebied

    bash# mkdir ~/usr-fase
    bash# cd ~/usr-fase
    bash# mkdir bin lib
    bash# mkdir -p share/termcap/l

#### Installeer het mp3blaster programma

Download de laatste versie van de broncode van mp3blaster vanaf de homepage op http://www.stack.nl/~brama/mp3blaster.

    bash# cd ~/usr/src/mp3blaster-3.13
    bash# ./configure
    bash# make
    bash# cp src/mp3blaster ~/usr-fase/bin

#### Kopieer aanvullende library's en terminfo

Noot: Dit is een voorbeeld van het ontwikkelsysteem van de auteur. Andere systemen kunnen iets andere resultaten laten zien.

    bash# cd ~/usr-fase/lib
    bash# ldd ~/usr-fase/bin/mp3blaster
    bash# cp /usr/lib/ncurses.so.5.0  .
    bash# cp /usr/lib/stdc++.so.3 .
    bash# cp /lib/libm.so.6 .
    bash# cp /usr/lib/libgcc_s.so.1 .
    bash# cd ~/usr/fase/share/terminfo/l
    bash# cp /usr/share/terminfo/l/linux .

#### Maak een gecomprimeerd image aan en kopieer het naar diskette

    bash# cd /
    bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096
    bash# mke2fs -m0 /dev/ram7
    bash# mount /dev/ram7 /mnt
    bash# cp -dpR ~/usr-fase/* /mnt
    bash# umount /dev/ram7
    bash# dd if=/dev/ram7 of=~/mp3blaster-image bs=1k
    bash# gzip -9 ~/mp3blaster-image

Doe de diskette met het label "mp3blaster" in station fd0.

    bash# dd if=~/mp3blaster-image.gz of=/dev/fd0 bs=1k

### Maak voor het testen een gegevensdiskette aan

Ga naar de internetsite http://www.paul.sladen.org en download het mp3-bestand waarin Linux Torvalds "Linux." uitspreekt. De directe link is: http://www.paul.sladen.org/pronunciation/torvalds-says-linux.mp3. Maak een Second Extended (ext2) filesystem aan op een diskette en kopieer het mp3-bestand naar de diskette.

## Implementatie

### Systeemstart

1. Boot van de kernel-diskette.

2. Doe de root-diskette in het diskettestation wanneer dit wordt aangegeven.

3. Antwoord 'Y', wanneer wordt gevraagd om een /usr diskette.

4. Doe de mp3blaster diskette in het diskettestation en druk op Enter.

### Verifieer of de /usr diskette juist werd geladen

    bash# mount
    bash# ls -lR /usr

### Controleer de initialisatie van het audio-device

    bash# dmesg | more

Als alles werkte dan zou er een regel of twee zijn waarin zou worden aangegeven dat de kernel de audio-hardware vond. In het voorbeeld hieronder wordt getoond hoe de kernel een geïntegreerd Yamaha geluidssysteem zou kunnen rapporteren.

    ymfpci: YMF740C at 0xf4000000 IRQ 10
    ac97_codec: AC97 Audio codec, id: 0x4144:0x5303 (Analog Devices AD1819)

### Test de audio-uitvoer

    bash# echo "10101010" > /dev/dsp

Een statische uitbarsting komend uit de luidsprekers van de PC duidt erop dat het geluid werkt.

### Speel een voorbeeldbestand af

    mount /dev/fd0 /home
    bash# /usr/bin/mp3blaster

Gebruik mp3blaster om het bestand `/home/torvalds-says-linux.mp3` te selecteren en af te spelen. Gebruik mp3blaster's mixer controls om zonodig het volume aan te passen.

### Systeem afsluiten

Sluit het systeem elegant af met de opdracht `shutdown`.