Operativsystem för civilingenjörer
fredag 29 augusti 2025
Gäller som tentamen för:
DT513G Operativsystem för civilingenjörer, provkod A001
Hjälpmedel: | Ordbok för översättning. |
Poängkrav: | Maximal poäng är 40. För godkänt betyg krävs 24 poäng. |
Resultat: | Meddelas senast 15 arbetsdagar efter tentamensdatum. |
Återlämning av tentor: | Elektroniskt via webbportalen Studenttjänster. |
Examinator och jourhavande: | Thomas Padron-McCarthy, telefon 070 - 73 47 013. |
20 = 1 | 224 = 16777216 | 248 = 281474976710656 |
21 = 2 | 225 = 33554432 | 249 = 562949953421312 |
22 = 4 | 226 = 67108864 | 250 = 1125899906842624 |
23 = 8 | 227 = 134217728 | 251 = 2251799813685248 |
24 = 16 | 228 = 268435456 | 252 = 4503599627370496 |
25 = 32 | 229 = 536870912 | 253 = 9007199254740992 |
26 = 64 | 230 = 1073741824 | 254 = 18014398509481984 |
27 = 128 | 231 = 2147483648 | 255 = 36028797018963968 |
28 = 256 | 232 = 4294967296 | 256 = 72057594037927936 |
29 = 512 | 233 = 8589934592 | 257 = 144115188075855872 |
210 = 1024 | 234 = 17179869184 | 258 = 288230376151711744 |
211 = 2048 | 235 = 34359738368 | 259 = 576460752303423488 |
212 = 4096 | 236 = 68719476736 | 260 = 1152921504606846976 |
213 = 8192 | 237 = 137438953472 | 261 = 2305843009213693952 |
214 = 16384 | 238 = 274877906944 | 262 = 4611686018427387904 |
215 = 32768 | 239 = 549755813888 | 263 = 9223372036854775808 |
216 = 65536 | 240 = 1099511627776 | 264 = 18446744073709551616 |
217 = 131072 | 241 = 2199023255552 | 265 = 36893488147419103232 |
218 = 262144 | 242 = 4398046511104 | 266 = 73786976294838206464 |
219 = 524288 | 243 = 8796093022208 | 267 = 147573952589676412928 |
220 = 1048576 | 244 = 17592186044416 | 268 = 295147905179352825856 |
221 = 2097152 | 245 = 35184372088832 | 269 = 590295810358705651712 |
222 = 4194304 | 246 = 70368744177664 | 270 = 1180591620717411303424 |
223 = 8388608 | 247 = 140737488355328 | 271 = 2361183241434822606848 |
2x * 2y = 2x+y
2x / 2y = 2x-y
b) Vad menas med en mikrokärna?
c) Vilka fördelar och nackdelar ger en mikrokärna?
#include <stdio.h> #include <unistd.h> int x = 1; int main(void) { int y = 1; fork(); x = x + 1; y = y + 1; fork(); fork(); printf("x = %d, y = %d!\n", x, y); } |
b) En process kan befinna sig i olika tillstånd, som "ny", "redo", "körande", "färdig" och "väntar". Rita upp ett tillståndsdiagram för hur processens tillstånd kan ändras, med de händelser som kan göra att det ändras.
c) Operativsystemkärnan innehåller att antal köer som processerna placeras i. Vilka är det? Hur hänger köerna ihop med de olika tillstånden från uppgiften ovan?
d) Processkontrollblocket (PCB) eller task-structen har bland annat plats för innehållet i processorns register. Varför det? Registerinnehållet finns väl i registren?
#include <stdio.h> #include <pthread.h> volatile int g = 0; void *thread_body(void *arg) { int thread_number = (int)arg; printf("Startat tråd %d...\n", thread_number); for (int i = 0; i < 100 * 1000 * 1000; ++i) { ++g; } printf("Avslutar tråd %d...\n", thread_number); return NULL; } int main(void) { pthread_t thread_1, thread_2, thread_3; pthread_create(&thread_1, NULL, thread_body, (void*)1); pthread_create(&thread_2, NULL, thread_body, (void*)2); pthread_create(&thread_3, NULL, thread_body, (void*)3); printf("Trådarna kör...\n"); pthread_join(thread_1, NULL); pthread_join(thread_2, NULL); pthread_join(thread_3, NULL); printf("Klart! g = %d\n", g); } |
Vid en provkörning av programmet får vi den här utskriften:
Trådarna kör... Startat tråd 3... Startat tråd 1... Startat tråd 2... Avslutar tråd 3... Avslutar tråd 1... Avslutar tråd 2... Klart! g = 118428316 |
a) Eftersom var och en av de tre trådarna ökar variabeln g med ett 100 miljoner gånger, borde utskriften bli 300000000, men i stället blev den 118428316. Vad beror det på?
b) Utskriften av Trådarna kör står efter pthread_create-anropen i main som startar de tre trådarna. Hur är det möjligt att den kan komma före utskrifterna om att trådarna har startat?
c) Skulle även utskriften Klart! kunna komma "konstigt", dvs på en annan plats än som sista raden? Förklara!
#include <stdio.h> #include <pthread.h> volatile int g = 0; volatile int the_lock = 0; // 0 = ledigt, 1 = låst void lock(void) { // Först, vänta på att låset blir ledigt while (the_lock != 0) { } // Nu är låset ledigt, så vi låser det the_lock = 1; } void unlock(void) { the_lock = 0; } void *thread_body(void *arg) { int thread_number = (int)arg; printf("Startat tråd %d...\n", thread_number); for (int i = 0; i < 100 * 1000 * 1000; ++i) { lock(); ++g; unlock(); } printf("Avslutar tråd %d...\n", thread_number); return NULL; } int main(void) { pthread_t thread_1, thread_2, thread_3; pthread_create(&thread_1, NULL, thread_body, (void*)1); pthread_create(&thread_2, NULL, thread_body, (void*)2); pthread_create(&thread_3, NULL, thread_body, (void*)3); printf("Trådarna kör...\n"); pthread_join(thread_1, NULL); pthread_join(thread_2, NULL); pthread_join(thread_3, NULL); printf("Klart! g = %d\n", g); } |
a) Fungerar låset, så resultatet i variabeln g alltid blir 300 miljoner? Förklara!
b) Det här är en variant på ett så kallat spin-lock. Vad innebär spin-lock?
c) Oavsett om just detta spin-lock fungerar eller inte, är det lämpligt att använda spin-lock här? Förklara!
a) Hur stor är den virtuella adressrymden?
b) Vi har satt i så mycket primärminne i datorn att hela den fysiska adressrymden kan utnyttjas. Hur mycket primärminne har datorn?
c) Hur många bitar av den virtuella adressen används för att ange offset inom en minnessida?
d) Hur många bitar av den fysiska adressen används för att ange offset inom en frame?
e) Hur många minnessidor är den virtuella minnesrymden indelad i?
f) Hur många olika ramar ("frames") är det fysiska minnet indelat i?
g) Om vi antar att sidtabellen ("page table") består av en array med en plats för varje virtuell minnessida, skulle den tabellen få plats i det fysiska minnet? Förklara!
Svaret var förstås att det beror på, särskilt på vad det är för medium man skriver till, som om det är en SSD, en mekanisk hårddisk, ett primärminnesfilsystem med hela filsystemet lagrat i primärminne, eller om man skriver till specialfilen /dev/null på Linux, som bara kastar bort alla data.
I lösningsförslagen fanns den här tabellen från en provkörning av ett Linux-program som skriver en gigabyte data, med olika tider för olika media:
Medium | write-anropen | close-anropet | sync-anropet | Total tid |
---|---|---|---|---|
SSD | 0.32 | 0.39 | 0.02 | 0.73 |
Mekanisk hårddisk | 0.31 | 6.63 | 0.16 | 7.10 |
Primärminnesfilsystem | 0.16 | 0.00 | 0.00 | 0.16 |
/dev/null | 0.00 | 0.00 | 0.00 | 0.00 |
Programmet öppnade filen som skulle skrivas med systemanropet open, skrev datat med flera anrop till write, och stängde filen med close. Därefter använde det sync, som vi känner igen från programmet flush_cache.c från en av labbarna.
a) Varför tar close-anropet ibland så lång tid, ibland mycket längre än den sammanlagda tiden för write-anropen? Förklara!
b) Varför har man gjort så det blir så?