Løsningsforslag for oppgavene i operativsystemer og C, uke 38 (19.9-23.9) På terminalstue: Oppgave 1: List alle filer og kataloger under /usr/bin som har filnavn som begynner på b. ls /usr/bin/b* Oppgave 2: Gå til roten (/) av systemet. Finn minst tre forskjellige måter å gå tilbake til hjemmekatalogen din på. cd / cd cd ~ cd ~/ cd ~/. cd $HOME Oppgave 3: Utfør en Unix-kommando som gir deg brukernavnet ditt. whoami echo $USER Oppgave 4: Skriv kommandoen echo bla bla bla > newfile, og bruk more for å se på filens innhold. Kan du forklare hva som har skjedd? Output fra echo går vanligvis til skjerm, men tegnet > sender den til filen newfile isteden. Oppgave 5: Lag en katalog med navn x. Gå til x, bruk emacs til å skrive noen tegn og lagre filen under navnet -x. Prøv å skifte navn på filen med mv fra x til x.txt. Hva skjer? Hvordan er det mulig å endre navnet? > mv./-x x.txt Oppgave 6: Finn ut hva maskinen du sitter på heter. > hostname Oppgave 7: Finn ut hva som er full path til programmet som startes når du gir kommandoen diff. > type diff
Oppgave 8: Lag først en fil fil.txt. Utfør en Unix-kommando som setter filrettighetene for filen fil.txt slik at eieren av filen (du) har alle rettigheter, medlemmer av filens gruppe har alle rettigheter untatt å skrive til filen, og alle andre kun kan lese den. > chmod 754 fil.txt Oppgave 9: Utfør følgende Unix-kommandoer i en tom katalog: > mkdir tex > mkdir oblig > mv oblig tex > mkdir oblig > mv tex oblig Tegn en liten skisse som viser katalogstrukturen i den tidligere tomme katalogen, med navn på alle katalogene etter at disse kommandoene er utført og prøv å forstå hva som skjedde. Katalogen der kom m andoene gjøres oblig tex oblig Oppgave 10: Editer en fil i din hjemmekatalog med emacs og kall den ls. Skriv inn følgende shell-script: #! /bin/bash ls Gjør scriptet kjørbart ved hjelp av kommandoen chmod 755 ls. Gi kommandoen ls.
Er det din eller systemets ls som blir utført? Legg inn linjen: Echo Dette er mitt script. før ls-kommandoen i ditt ls-script, og prøv å få systemet til å liste filene med ditt script. >./ls Oppgave 11: Gjør en kommando som bruker grep til å liste alle prosesser på maskinen som er dine. > ps aux grep $USER Oppgave 12: Finn ut hvilke grupper du selv tilhører. > groups Oppgave 13: Start emacs og lagre en fil med navn #fil.txt. Gå ut av emacs og prøv å fjerne filen. Hva tror du problemet skyldes? Det går ikke med > rm #fil.txt for alt etter # blir tolket som en kommentar. Følgende to metoder virker: > rm #fil.txt > rm./#fil.txt Oppgave 14: Skriv et shell-script som skriver ut verdien av den globale variabelen DISPLAY Hvis den er satt og gir melding om at den er udefinert hvis den ikke er satt. #! /bin/bash if [ $DISPLAY!= ] then echo DISPLAY er definert til $DISPLAY else echo DISPLAY ikke definert fi Oppgave 15: Gjør en kommando som legger til teksten Siste linje til den allerede eksisterende filen foo.txt. > echo Siste linje >> foo.txt Oppgave 16: Gjør en kommando som finner ut om det eksisterer en bruker med brukernavn paalh på systemet. Finger paalh #alt. 1 Echo ~paalh #alt. 2
Oppgave 17: Hva blir output av echo hei du der sort Forklar! Sort sorterer linjer og ikke ord for ord In the classroom: Question 1: The inventors of the C language have created a language that requires very little typing. One-character symbols are used a lot, and abbreviations are part of the syntax. Here is an example of an abbreviation in correct code: void function( char* buf )... void otherfunction( ) char buffer[200];... function( buffer ); /* <- abbreviation */... What is this actually? Solution: It means char buffer[200]; function( &buffer[0] ); /* <- abbreviation */ The array's name is the same thing as a pointer to its first element. This means also that void function( char* buf )... /* first version */ and void function( char buf[] )... /* second version */ are _nearly_ equivalent. The difference is that you can never change buf in the second version. For example, the use "free(buf)" or "buf = buf + 1" in the second version is not allowed. Question 2: You have the following code: void function( int a, int* b, char c, char* d, char e[] ) a = 2; *b = 3; b = &a; c = 'x';
*d = 'y'; d = &c; e[2] = 'z'; int main( ) int k,l; int* m; char n,o; char* p; char q[5]; k = 100; l = 101; m = &l; n = 'n'; o = 'o'; p = &o; q[0] = 'h'; q[1] = 'e'; q[2] = 'r'; q[3] = 'e'; q[4] = '\0'; function( k,m,n,p,q ); printf( "k=%d l=%d *m=%d\n", k, l, *m ); printf( "n=%c o=%c *p=%c\n", n, o, *p ); printf( "q=%s\n", q ); What is printed onto the screen? Why? Solution: This is printed: k=100 l=3 *m=3 n=n o=y *p=y q=heze When function is called, it receives _copies_ of the values k, m, n, and p, and a pointer to the array q. (1) Because a and b are copies, k and n remain unchanged. (2) For m and p, on the other hand, function does at first not try to change m and p themselves, but the places that they point to. They point to the actual variables l and o, not to copies. So, l and o are changed. (3) After that, function changes b and d, which are only copies of m and p, so m and p are not changed. (4) The name of an array is always a pointer to the array. So, when function is called with the paramter q, e becomes also a pointer to the array q. That means that it can also change the contents of the array. And that's what it does. Question 3: You have the following code: void funa( char buf[10] ) buf[i] = 'a' + i;
void funb( char* buf ) buf[i] = 'b' + i; void func( char* buf ) *buf = 'c' + i; buf = buf + 1; int main( ) char buf[11]; memset( buf, 0, 11 ); funa( buf ); printf( "%s\n", buf ); funb( buf ); printf( "%s\n", buf ); func( buf ); printf( "%s\n", buf ); What is the output? Why? Solution: The output is abcdefghij bcdefghijk cdefghijkl First of all, the character 'a' is identical to the number 97, and the rest of the alphabet follows, 'b' is 98, and so on. This means that you can say that 'c' == 'a' + 2. Second, funa and funb are semantically identical because we have already said that array names are only pointer to their first element anyway. So clearly, char buf[10] and char* buf are essentially the same thing. func shows that you can do something more with pointers. You can change them. This is called pointer arithmetics. You can even use them the following way: void fund( char* buf ) *(buf+i) = 'c' + i; The C book by its inventors Kernighan and Ritchie clarifies why this works. They say that &buf[3] is only a transformation of buf+3 and
buf[3] is a transformation of *(buf+3) So, "*(buf+3)" is the original version, and buf[3] has been introduced into the C language to make it _easier_ for us to understand what is going on. Question 4: Imagine that you should write a program that reads a file given as program input (e.g., this file) line by line, split the line in "words" separated by space (' ') and count the number times each word occurs in the text. Assume that each line is shorter than 120 characters, each word is shorter that 40 characters and that the maximum number of different words are 500 (if more, count only the first 500). If these limitations were removed, will this affect implementation of the program? Question 5: Why do we have operating systems? What is the two ways to look at an operating system and what do they mean (two main functions)? Why is it imortant to have some knowledge about the OS and the system in general?