Løsningsforslag til eksamen i INF03 Kjell Åge Bringsrud (oppgave 5) Dag Langmyhr (oppgave 2 og 3) Carsten Griwodz (oppgave 4) Sigbjørn Næss (oppgave og 6) 6. desember 2002 Boolsk algebra og CPU-design a Ved hjelp av diagrammet i figur på neste side kan funksjonen forenkles til F = ac + bd + bc. b En addisjonsoperasjon kjennetegnes ved at OP-koden er 000. Siden instruksjonen ligger i instruksjonsregisteret IR, må man se på de fire mest signifikante bit-ene for å utlede ALU_ADD: ALU_ADD = IR[5] * IR[4] * IR[3] * IR[2] der * betyr logisk AND. Dette kan implementeres slik det er vist i figur 2 på neste side. c Hvis instruksjonen er av type ADD eller AND, vil bit nummer 6 fra høyre i intruksjonen (dvs IR[5]) angi om operand nummer 2 er et register (IR[5]=) eller en 5-bits konstant (IR[5]=0). Hvis operand 2 er et register, skal alle 6 bit-ene i MDR kopieres over til IN_2 (som da også må være 6 bit selv om dette ikke er spesifisert på figuren i oppgaven). Hvis operand to skal være en 5-bits konstant må man utvide denne til en 6-bits konstant før man kopierer den inn i IN_2. Det er ikke spesifsert i oppgaven om 5-bits konstanten skal være med eller uten fortegn. Hvis man forutsetter at konstanten kan være med fortegn, kan man gjøre «sign extension» ved å kopiere bit IR[4] inn i IN_2[5] til IN_2[5] (figur 3 på side 3). Hvis konstanten er uten fortegn, settes IN_2[5] til IN_2[5] alle lik 0 (figur 4 på side 3). IR[5] brukes som select signal inn på alle 6 2--multiplekserne. d Man kan finne ut om et program prøver å aksessere over halvdel av hukommelsen enten ved å sjekke innholdet i «Program Counter» (PC) eller «Memory Address Register» (MAR). I begge tilfeller kan sjekken utføres ved å se om det mest signifikante bit-et er satt (dvs PC[5]= eller MAR[5]=). Forskjellen er som følger: Hvis man sjekker om PC[5]=, vil man fange opp de tilfeller hvor man vil prøve å hente neste instruksjon fra den ulovlige delen av hukommelsen, mens MAR[5]= vil fange opp de tilfeller hvor man
d a c b Figur : Bruk av Carnaugh-diagram IR[5] IR[4] IR[3] ALU_ADD IR[2] Figur 2: Sjekk på ADD-instruksjon 2
MDR[5] 2- MUX IN_2[5] MDR[5] 2- MUX IN_2[5] IR[4] MDR[4] 2- MUX IN_2[4] IR[0] MDR[0] 2- MUX IN_2[0] IR[5] Figur 3: Adressering med «sign extension» MDR[5] 0 2- MUX IN_2[5] MDR[5] 0 2- MUX IN_2[5] IR[4] MDR[4] 2- MUX IN_2[4] IR[0] MDR[0] 2- MUX IN_2[0] IR[5] Figur 4: Adressering uten «sign extension» 3
uansett data eller instruksjon aksesserer den øvre delen av hukommelsen i nåværende klokkesykel. Hvis man ønsker å detektere begge disse tilfellene (dvs både hva som skjer nå og hvilken instruksjon som skal hentes i klokkesykel) kan man sette at ILLEGAL_MEMORY_ACCESS = PC[5] + MAR[5] der + betyr logisk OR. 2 Oversettelse Denne oversettelsen er laget helt rett frem uten noen smarte triks. Det eneste ikke-trivielle elementet er at for å sammenligne tegnene, må man legge sammen det ene med den negative verdien av det andre. Men dette har det vært trent ganske mye på. ; Rutinenavn: mystrchr 2 ; Synopsis: Finner et tegn i en tekst 3 ; Signatur i C: char *mystrchr (char *s, char c) 4 ; Inn-parametre: R0: s 5 ; R: c 6 ; Ut-paramtre: R0: Adressen til tegnet, eller 0. 7 ; Registre: R2: *s 8 ; R3: -c 9 0 mystrchr: st R2,SaveR2 ; Gjem unna R2 st R3,SaveR3 ; og R3. 2 3 not R3,R ; Beregn -c og legg 4 add R3,R3,# ; i R3. 5 6 my_lop: ldr R2,R0,#0 ; Hent *s. 7 brz my_x0 ; Ferdig om *s==0. 8 add R2,R2,R3 ; Sjekk om *s==c; i så fall, 9 brz my_x ; hopp ut. (Svaret allerede i R0.) 20 add R0,R0,# ; Øk s. 2 br my_lop ; Gå i løkke. 22 23 ;; Uthopp når tegnet ikke finnes: 24 my_x0: and R0,R0,#0 ; Legg 0 i R0. 25 ;; Uthopp når adressen til tegnet ligger i R0: 26 my_x: ld R2,SaveR2 ; Hent tilbake R2 27 ld R3,SaveR3 ; og R3. 28 ret ; Retur. 29 30 SaveR2:.fill #0 ; Gjemmested for R2 3 SaveR3:.fill #0 ; og R3. 3 Programmering i C Funksjonen firsttok Denne løsningen er ganske rett frem; det er vanskelig å se at den kan løses på noen annen fornuftig måte. char *firsttok (char *s, char c) 2 { 3 char *b; 4 5 /* Hopp over innledende skilletegn: */ 4
6 while (*s && *s==c) ++s; 7 8 /* Er vi kommet til slutten? */ 9 if (*s == 0) return NULL; 0 b = s; /* Husk hvor ordet starter. */ 2 3 /* Hopp så over alle tegnene i ordet: */ 4 while (*s && *s!=c) ++s; 5 6 /* Legg inn 0-byte for å avslutte teksten: */ 7 *s = 0; 8 9 /* Returnér med adressen til starten av ordet: */ 20 return b; 2 } Funksjonen strtok Denne løsningen bør også være grei. Det eneste «lure» er å bruke strchr til å sjekke om tegnet finnes blant de som er i teksten c. char *strtokaddr; 2 char *strtok (char *s, char *c) 3 { 4 char *b; 5 6 /* Hopp over innledende skilletegn: */ 7 if (s == NULL) s = strtokaddr; 8 while (*s && strchr(c,*s)) ++s; 9 if (*s == 0) return NULL; 0 b = s; 2 /* Hopp så over alle tegnene i ordet: */ 3 while (*s &&! strchr(c,*s)) ++s; 4 5 /* Avslutt: */ 6 strtokaddr = s; 7 if (*strtokaddr) ++strtokaddr; 8 *s = 0; 9 return b; 20 } Programmeringsfeil Følgende skjer:. line peker på et nyallokert område. Den innleste linjen legges der. 2. Etter kallet på strtok peker param på første tegn på linjen, altså er line=param. 3. Det allokerte området frigis, men param peker stadig på det. 4. message peker på et nyallokert område, som sannsynligvis er det nettopp frigjorte området line pekte på. I så fall er message=param. 5. Kallet strcat(message,param) vil derforlese og skrive fra samme område og dermed gå i evig løkke inntil den kommer til en ulovlig adresse. Det var ikke tilfeldig at akkurat denne funksjonen ble gitt som oversettelsesoppgave. 5
Uansett er det galt å frigi området line peker på mens det ennå er pekere inn i det. Den enkleste løsningen å flytte free(line) til rett før return. 4 Datakommunikasjon 4a It is not sufficient to specify an application layer protocol. It is necessary to specify also the port that you choose for the transport layer. Protocol definition at the transport layer: client and server communicate via TCP the client contacts the server on port 7890 Protocol definition at the application layer: 4b The client sends the data and comments of the appointment to the server and does not expect a response at the application level. The client sends the length of the data string as a 4 byte integer in network byte order, the data string as it has been received on the command line, without the ; symbol but with a trailing zero, the length of the comment string as a 4 byte integer in network byte order, and the comment string as it has been received on the command line, without the ; symbol but with a trailing zero. The client closes the TCP connection. #include <stdio.h> 2 #include <string.h> 3 #include <netinet/in.h> 4 #include <netdb.h> 5 6 #define PORT 7890 7 8 void errorexit( const char* c ) 9 { 0 printf( "Error: %s\n", c ); exit( - ); 2 } 3 4 static int connectto( const char* host, unsigned short port ) 5 { 6 struct hostent* hostp; 7 struct sockaddr_in server; 8 int sock; 9 struct linger linger; 20 2 /* Open the client socket */ 22 if( (sock = socket(pf_inet, SOCK_STREAM, IPPROTO_TCP)) < 0 ) 23 { 24 perror("can t create socket."); 25 exit(); 6
26 } 27 28 /* Fetch the IP address of the given hostname */ 29 if( (hostp = gethostbyname(host)) == 0 ) 30 { 3 fprintf(stderr,"%s: unknown host\n",host); 32 exit(); 33 } 34 35 /* Fill the IP address of the server and port that is defined 36 * by the protocol into an address structure */ 37 memset( &server, 0, sizeof(struct sockaddr_in) ); 38 server.sin_family = AF_INET; 39 memcpy( &server.sin_addr, hostp->h_addr, hostp->h_length); 40 server.sin_port = htons(port); 4 42 /* connect the client socket */ 43 if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0) 44 { 45 close(sock); 46 perror("can t connect to server"); 47 exit(); 48 } 49 50 /* since the client closes the socket after sending the string, 5 * it is appropriate to wait until all data has actually been 52 * sent out. */ 53 linger.l_onoff = ; 54 linger.l_linger = 5; 55 setsockopt( sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger) ); 56 57 return sock; 58 } 59 60 static void safewrite( int sock, const char* buf, size_t sz ) 6 { 62 /* send in a persistant manner 63 * TCP may send buffers partially and it is quite likely that it will 64 * do this */ 65 ssize_t w; 66 while( sz > 0 ) 67 { 68 w = write( sock, buf, sz ); 69 if( w == - ) 70 { 7 perror( "Error writing to socket." ); 72 exit( ); 73 } 74 buf += w; 75 sz -= w; 76 } 77 } 78 79 int main( int argc, char* argv[] ) 80 { 8 char* hostname; 82 char* date; 83 char* comment; 84 int sock; 85 size_t sz; 86 size_t len; 87 7
minfil.txt liste.c key.txt 5 2 33 9 6 52 77 end 7 43 40 89 76 end 65 end Tabell : Blokkallokering på disk 88 if( argc!= 2 ) 89 { 90 errorexit( "Call this programs with an appointment string of the form" 9 "niu.ifi.uio.no;06.2.2002.0:00;write C code" ); 92 } 93 94 /* extract the 3 parts of the appointment string */ 95 hostname = strdup( argv[] ); 96 hostname = strtok( hostname, ";" ); 97 if( hostname == NULL ) errorexit( "no hostname in appointment string" ); 98 date = strtok( NULL, ";" ); 99 if( date == NULL ) errorexit( "no date in appointment string" ); 00 comment = strtok( NULL, ";" ); 0 if( comment == NULL ) errorexit( "no comment in appointment string" ); 02 03 sock = connectto( hostname, PORT ); 04 05 /* Send the appointment according to the protocol that was defined in 4a */ 06 sz = strlen(date) + ; 07 len = htonl(sz); 08 safewrite( sock, (const char*)&len, 4 ); 09 safewrite( sock, date, sz ); 0 sz = strlen(comment) + ; len = htonl(sz); 2 safewrite( sock, (const char*)&len, 4 ); 3 safewrite( sock, comment, sz ); 4 5 close( sock ); 6 exit( 0 ); 7 } 5 Operativsystemer 5a Blokkallokering Indeks-blokkene for de oppgitte filene kan for eksempel se ut som vist i tabell. Det kreves ikke at det avsettes fysiske blokker til indeks-blokkene, men det er OK at man gjør det; det mangler da minst én ledig blokk på figur 4. Intern fragmerntering Det er her viktig å legge merke til at det spørres om intern fragmentering ved allokeringen av minfil.txt (jfr definisjon i læreboka). Siden det forut- 8
Jobb Ferdigtid ved SJF Ferdigtid ved RR J 80 ms 360 ms J2 380 ms 570 ms J3 80 ms 220 ms J4 30 ms 40 ms J5 630 ms 630 ms Tabell 2: Jobb-dispatching settes brukt 2 bytes (6 bit) til blokkaddressering, betyr dette at man vil bruke 3570 bytes pluss 4 bytes for minfil.txt dersom linket allokering benyttes. Dette antallet bytes (3584) svarer nøyaktig til 7 hele blokker slik at man i dette tilfellet ikke har noen intern fragmentering (slik det er oppgitt i oppgaven). Ved bruk av indeksert allokering benyttes det imidlertid ikke link til neste blokk, slik at det i dette tilfellet er 4 bytes ubrukt, dvs en intern fragmentering på 4 bytes i fila. Byte nr 3000 Siden den sjette blokken i fila inneholder byte nr 256 til og med byte nr 3072, vil byte nr 3000 ligge i blokk 6. 5b Løsningen er vist i tabell 2; tallene i tabellen er fremkommet på følgende måte: SJF RR J4: 30 ms J3: (30 + 50)ms = 80 ms J: (80 + 00) ms = 80 ms J2: (80 + 200) ms = 380 ms J5: (380 + 250) ms = 630 ms J4: (2*0*5+4*0) ms = 40 ms J3: (40+0+4*0+3*0) ms = 220 ms J: (220+0+4*0*3+0) ms = 360 ms J2: (360+2*0+9*0*2+0) ms = 570 ms J5: (570+0+5*0) ms = 630 ms Gjennomsnittelig tid i jobbkø SJF: RR: 300/5 ms = 260 ms 920/5 ms = 384 ms 5c Det henvises her til figur 6.24 i læreboka. 9
6 Flervalgsoppgave Oppgave Korrekt a 3 b c 5 d 3 e f 5 g 2 h 4 0