Løsningsforslag, Eksamen høsten 2011 Operativsystemer og Unix

Oppgave 1 - Java og prosesser (20%)

a)

javac Arr.java   # Kompilerer kildekoden og lager Arr.class lages som inneholder bytecode
java Arr           # Starter JVM (Java Virtual Machine) som kjører byte-koden og programmet utføres.

b) Programmet time måler hvor lang tid det tar når java Arr kjøres. Real: antall sekunder reell tid som ble brukt. User: CPU-tid brukt med CPU i user mode. System: CPU-tid brukt av programmet i kernel mode. Prosent-tallet gir hvor mange prosent av den totale CPU-tiden på systemet som programmet har brukt.

c) Dette lager en for-løkke som kjører to ganger og for hver runde startes en tidtagning av java Arr som en bakgrunnsprosess. Dermed oppnår man at de to Java-prosessene kjører samtidig og uavhengig av hverandre.

d) Host'en har to uavhengige CPU'er og disse kjører nå samtidig hver sin uavhengige java-prosess. Tidsbruken vil derfor bli omtrent lik som når bare en prosess kjørte, siden den da kjørte alene på en enkelt CPU.

e) Nå kjøres to like og uavhengige Java-prosesser på hver CPU. Hvis prosesseme kun brukte registere i beregningene, ville man ventet at hver prosess brukte dobbelt så lang tid, ca 6.6 sekunder. Men CPU'ene er hyperthreading og data må hentes fra minnet (trolig fra cache). Dette gjør at CPU hurtig kan bytte prosess når den venter på data fra minnet og dermed sparer noe tid. Hver prosess bruker dermed kun ca 50% lenger tid og ikke 100% lenger tid som ville vært tilfelle om CPU'ene ikke var hyperthreading. Linux behandler en hyperthreading CPU som to uavhengige CPU'er og rapproterer derfor omtrent 100% CPU-bruk fra hver CPU.

f) Det vil nå startes dobbelt så mange prosesser. Hyperthreading gjør at det kan kjøre to prosesser på hver CPU samtidig (som i forrige oppgave) men samtidig må da de 4 andre prosessene vente, helt uvirksomme. Alt vil dermed ta dobbelt så lang tid. Det vil bli åtte linjer som ser omtrent slik ut:

Real: 10.0 User:4.95 System:0.025 49%
Hver prosess bruker like mye CPU-tid som før for å fullføre, men siden de må dele CPU mellom dobbelt så mange prosesser til vil den reelle tiden bli dobbelt så lang.

Oppgave 2 - Internminne (25%)

a) Den vil bestå av 6 sider; kun hele sidere tildeles.

b) Ja, hvis en prosess er ferdig med å bruke datastrukturer som for eksempel klasser, kan disse sidene frigjøres. Enten ved at prosessen selv avgir minnet eller ved garbage collection.

c) En dirty page er en side som har blitt endret slik at den må skrives til disk om OS sin paging algoritme velger at den skal ut av RAM. Sider som inneholder den kjørebare koden blir aldri dirty siden innholdet aldri endres. Hva er en dirty page? Finnes det en type sider for en prosess som aldri blir dirty? Forklar kort.

d) En page table entry er informasjon om en gitt page i page table, hvor den ligger i minnet og andre felt med info. Det viktigste feltet er page frame nummeret som sier i hvilken frame i RAM siden ligger.

e) Dette bit'et settes når en side leses eller skrives til. Dette er nyttig info for OS sin algoritme for å ta ut sjeldent brukte sider fra RAM.

f) Sider som refereres ofte legges i TLB. Siden de per definisjon brukes ofte, trenger de ikke et eget bit som sier at de har vært i bruk.

g) RAM står for Random Access Memory. Det betyr at ethvert byte kan skrives og leses i vilkårlig rekkefølge. Det vil da også ta omtrent like lang tid å hente et byte fra RAM, uavhengig av hvor i minnet det ligger.

h) Ja, det vil da gå mye hurtigere å hente et byte som ligger i cache en om det ligger i RAM fordi cache-minnet er raskere og nærmere CPU.

i) Den vil bestå av 5000x5000x4 byte = 100 Megabyte. Mega betyr da en million i SI-betydningen (= 95.37 MebiByte).

j) Hele arrayet vil kunne være i minnet på en gang når programmet kjøres, så paging er ikke en faktor her. Uten cache ville da programmet gå like fort i begge tilfeller, siden det ville ta like lang tid å hente hvert matriseelement. Men i det første tilfellet ser man at arrayet skrives til i samme rekkefølge som det ligger lagret i RAM. Dermed vil det skrives fortløpende til bytes etterhverandre i cache som så legges samlet ut i minnet. Dette går mye raskeren enn i program to hvor det er 20000 byte mellom hvert matrise element som skrives til. Dermed vil det stort sett bare bli cache-miss og det går totalt sett mye lengre tid å skrive til minnet.

Oppgave 3 - bash (10%)

a)

#! /bin/bash
for n in $(seq 4); do 
   echo Linje $((n*2)) 
done

b) Kort fortalt: anta at scriptet heter remove.sh. Kallet $ remove.sh n vil da fjerne linje n fra filen known_hosts
I mer detalj:

  1. lineNR settes til å være scriptets første argument
  2. Filen known_hosts kopieres til en midlertidig fil
  3. Innholdet i known_hosts overskrives med et tomt tegn; med andre ord, innholdet fjernes
  4. Innholdet fra den midlertidige filen, altså det som opprinnelig lå i known_hosts, pipes til en løkke
  5. Løkken har en teller som holder rede på hvilken linje som behandles. For hver linje sjekker den om det aktuelle linjenummeret tilsvarer nummeret på den linjen som skulle fjernes. Hvis ikke skrives linjen tilbake til known_hosts.

Oppgave 4 - Perl (20%)

a)

#! /usr/bin/perl

for($i=1;$i<5;$i++){
    print "Linje ".(2*$i)."\n";
}

b) script1.pl

  1. Åpner filen syslog.txt, til filstrømmen F1
  2. kopierer alle linjene i F1 til arrayet @f1
  3. En løkke itererer over tallene mellom 0 og siste element i @f1
  4. For hver iterasjon skrives tallet $i ut, etterfulgt av den tilhørende linjen i syslog.txt.
Utskrift: Nøyaktig som den opprinnelige filen, men med hver linje nummerert fra 0 til 5

script2.pl

  1. Som i script 1.
  2. Første linje i F1 leses av, men lagres ikke noe sted.
  3. Andre linje i F1 leses av og lagres i variablen $line
  4. En løkke itererer over hver av de resterende linjene i F1. Alle linjene i syslog.txt, bortsett fra de to første, skrives ut.
Utskrift: Nøyaktig som den opprinnelige filen, men uten de to første linjene.

c)

#! /usr/bin/perl

open(F1,$0);
$i=0;
foreach(<F1>){
    $i++;
    $hash{$i}=$_;
}

for($i=1;$i<=keys(%hash);$i++){
    print "$i: $hash{$i}";
}

Oppgave 5 - Powershell (10%)

a)

 for($i=1; $i -le 5; $i++){"Linje $i"}

b)

if($args[0] -and $args[1]){
	    "Powershell er "+($args[0]+$args[1])+" ganger bedre enn cmd!"
}else{
	throw "Missing arguments"

	#Alternativt kan man tillate at det ikke er med noen else-setning. 
	#Kravet i oppgaven er bare at det skal kreves to argumenter - ikke hva som skal skje dersom dette ikke er oppfylt.
	#Den Korrekte objektorienterte måten å gjøre dette på er å kaste et unntak, dersom kravet ikke er oppfylt, men det er vel kanskje ikke pensum
}

c) Den første måten henter ut størrelsen, direkte fra feltet "Length", mens den andre måten kaller metoden get_Length().

d) Nei, bash er ikke objektorientert. Kommandoen "ls test.txt" ville i bash bare returnert en linje med tekst. Denne linjen har hverken felter eller metoder.

Oppgave 6 - Nettverk (15%)

a) En host med en offentlig IP-adresse kan kommunisere med alle andre på Internett med offentlige adresser. En internett-router vil droppe enhver pakke med en privat adresse. Disse adressene er ment for lukkede private subnett. Men NAT muligjør kommunikasjon mellom private nett og Internett.

b) De 25 første bit'ene i netmasken er enere og de 7 siste er nuller. Dermed er det de 7 siste bit'ene som utgjør host-nummeret og $2^7 = 128$ mulige adresser i dette subnettet, fra 0 til 127 (0 og 127 kan ikke brukes som host-adresser).

c) Her er de 8 siste bit i netmask nuller og deremed 256 IP-adresser. Subnettet utgjøres dermed av adressene 128.39.89.0 - 128.39.89.255 (inkludert nett og broadcast-adressen).

d) Arp-tabellen vil kun inneholde entries for maskiner i samme subnet, derfor er ikke 128.39.74.65 med, den tilhører et annet subnet og pakker dit går via en gateway.

e) I første pakke fra klient til server er SYN=1 og ACK=0. I svaret fra server er SYN=1 og ACK=1. I tredje pakke, fra klient, er SYN=0 og ACK=1. Disse bit'ene er en del av feltet Flags i TCP-headeren.


haugerud 2013-05-28