Tid: 08:15 - 13:15
Instruktioner inför digital hemtentamen/ examination
Jag vill undvika fusk - hur gör jag? / All form av fusk anmäls
Lägg undan mobilen. Stäng av sociala medier.
Du får inte använda hjälpmedel.
Det vill säga att du får inte använda dig av något annat än det som står angivet i instruktionerna.
Konsekvenser av fusk Om du fuskar kan detta leda till en avstängning som kan få följder både för dina studier och privat:
|
b) Långt efter att systemanropet gjorts kan det förekomma fler interrupt, som en del av arbetet som utförs av systemanropet. Beskriv hur det kan gå till!
a) Vad används den till?
b) Vad innehåller den?
c) Task-structen förekommer i flera olika köer i operativsystemkärnan. Vad är det för köer, och vad används de till?
a) Hur stor är en minnessida ("page")? Visa hur du räknat.
b) Fysiska ramar ("frames") kommer att vara lika stora som minnessidorna. Förklara varför!
c) På den här processorn har fysiska adresser fler bitar än virtuella adresser. Är det något konstigt med det? Vad innebär det?
d) Hur mycket plats (i byte) tar page-tabellen för en process? Gör rimliga antaganden, redovisa dem, och förklara hur du räknat!
e) Den virtuella minnessidan nummer 2 (binärt: 10) lagras i fysisk frame nummer 0 (binärt: 0). På vilken fysisk minnesplats finns den virtuella adressen 4097 (binärt 1000000000001)?
Programmet threads-1.c:
// threads-1.c #include <stdio.h> #include <pthread.h> volatile long long data = 0; void *thread_body(void *arg) { for (int i = 0; i < 1000*1000; ++i) { ++data; } return NULL; } int main(void) { pthread_t thread1, thread2; pthread_create(&thread1, NULL, thread_body, NULL); pthread_create(&thread2, NULL, thread_body, NULL); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("Result: data = %lld\n", data); } |
a) Vi kör programmet, men variabelns värde blir inte alls två miljoner, utan 1028606. Vad beror det på att det blir fel värde?
b) Vi flyttar om raderna i main-funktionen så den ser ut enligt nedan. Vad blir variabelns värde nu, och vad beror det på?
Ur programmet threads-2.c:
int main(void) { pthread_t thread1, thread2; pthread_create(&thread1, NULL, thread_body, NULL); pthread_join(thread1, NULL); pthread_create(&thread2, NULL, thread_body, NULL); pthread_join(thread2, NULL); printf("Result: data = %lld\n", data); } |
c) Kan man gissa något om hur körtiden för threads-2 kommer att bli, jämfört med threads-1? Vad beror det på? (Vi talar om den så kallade "väggklocketiden", som är den verkliga tid som det tog att köra programmen, och som man till exempel skulle kunna mäta genom att titta på en väggklocka).
d) Vi har glömt hur man skrev för att använda pthread-paketets lås, så vi försöker göra ett lås själva, så programmet ser ut enligt nedan. Fungerar låset? Kommer variabelns värde att bli två miljoner nu? Förklara!
Programmet threads-3.c:
// threads-3.c #include <stdio.h> #include <pthread.h> volatile long long data = 0; volatile int locked = 0; void *thread_body(void *arg) { for (int i = 0; i < 1000*1000; ++i) { // First, wait for the lock in a loop: while (locked) { } // Lock is free, lock it: locked = 1; ++data; // Release the lock: locked = 0; } return NULL; } int main(void) { pthread_t thread1, thread2; pthread_create(&thread1, NULL, thread_body, NULL); pthread_create(&thread2, NULL, thread_body, NULL); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("Result: data = %lld\n", data); } |
e) Visa hur man gör låsningen på rätt sätt, med pthread-paketets lås.
// create-garbage-1.c #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #define KILO 1024 #define MEGA KILO*KILO int main(void) { char buffer[1]; buffer[0] = 'x'; int outfd = open("garbage", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); for (int i = 0; i < 10*MEGA; ++i) write(outfd, buffer, sizeof buffer); close(outfd); } |
// create-garbage-2.c #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #define KILO 1024 #define MEGA KILO*KILO char buffer[KILO]; int main(void) { for (int i = 0; i < sizeof buffer; ++i) buffer[i] = 'x'; int outfd = open("garbage", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); for (int i = 0; i < 10*KILO; ++i) write(outfd, buffer, sizeof buffer); close(outfd); } |
// create-garbage-3.c #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #define KILO 1024 #define MEGA KILO*KILO char buffer[10*KILO]; int main(void) { for (int i = 0; i < sizeof buffer; ++i) buffer[i] = 'x'; int outfd = open("garbage", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); for (int i = 0; i < KILO; ++i) write(outfd, buffer, sizeof buffer); close(outfd); } |
// create-garbage-4.c #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #define KILO 1024 #define MEGA KILO*KILO char buffer[10*MEGA]; int main(void) { for (int i = 0; i < sizeof buffer; ++i) buffer[i] = 'x'; int outfd = open("garbage", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); write(outfd, buffer, sizeof buffer); close(outfd); } |
// create-garbage-5.c #include <stdio.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #define KILO 1024 #define MEGA KILO*KILO char buffer[MEGA]; void *thread_body(void *arg) { int thread_number = (int)arg; printf("starting thread %d...\n", thread_number); int outfd = open("garbage", O_WRONLY); // lseek moves to the place in the file where this thread will write lseek(outfd, thread_number * MEGA, SEEK_SET); write(outfd, buffer, sizeof buffer); close(outfd); printf("done thread %d\n", thread_number); return NULL; } int main(void) { for (int i = 0; i < sizeof buffer; ++i) buffer[i] = 'x'; // To ensure the file exists and is empty before the threads start int outfd = open("garbage", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU); close(outfd); pthread_t threads[10]; for (int thread = 0; thread < 10; ++thread) pthread_create(&threads[thread], NULL, thread_body, (void*)thread); for (int thread = 0; thread < 10; ++thread) pthread_join(threads[thread], NULL); } |
När vi provkör programmen mäter vi upp dessa körtider:
Program | Körtid |
---|---|
create-garbage-1 | 6.253 s |
create-garbage-2 | 0.019 s |
create-garbage-3 | 0.013 s |
create-garbage-4 | 0.018 s |
create-garbage-5 | 0.005 s |
a) Varför är create-garbage-1 så väldigt långsamt? Förklara!
b) Kan man förklara körtiderna för programmen create-garbage-2, create-garbage-3 och create-garbage-4?
c) Kan man säga något om hur många processorkärnor som datorn vi provkörde på har? Vad, och varför?
d) Ett program kan vara flertrådat, men man talar också om flertrådade operativsystemkärnor. Kan man säga något om ifall operativsystemkärnan på datorn som vi provkörde på är flertrådad? Vad, och varför?