Upload
devendra-kumar
View
3
Download
0
Embed Size (px)
DESCRIPTION
ghhihjhjhjhjhjh
Citation preview
CS61: Systems Programming and Machine Organization
Section NotesWeek of Nov 9th
Outline for this week:● Forks● Signal Handlers● Threads
Forks and HandlersQuestion 1
(i) How many output lines are printed?
void fn() { fork(); fork(); printf("hello\n"); return;}
int main() { fn(); printf("hello\n"); exit(0);}
(ii) How many output lines are printed?
void fn() { if (fork() == 0) { fork(); printf("hello\n");
exit(0); } return;}
int main() { fn(); printf("hello\n"); exit(0);}
(iii) How many output lines are printed?
void fn() { if (fork() == 0) { fork(); printf("hello\n");
return; } return;}
int main() { fn(); printf("hello\n"); exit(0);}
(iv) What does this program print?
int counter = 1;
int main() { if (fork() == 0) {
counter--; exit(0);
} else {wait(NULL); counter++; printf("counter = %d\n", counter);
} exit(0);}
Question 2
Consider the following program:
void end(void) {
printf(“2”);
}
int main() {
if (fork() == 0)
atexit(end);
if (fork() == 0)
printf(“0”);
else
printf(“1”);
exit(0);
}
Determine which of the following outputs are possible. Note: The atexit function takes a pointer to a function and adds it to a list of functions (initially empty) that will be called when the exit function is called.
A. 112002
B. 211020
C. 102120
D. 122001
E. 100212
Question 3
int counter = 0;
int main() {int i;for (i = 0; i < 2; i ++){ fork(); counter++; printf("counter = %d\n", counter);}
printf("counter = %d\n", counter); return 0;}
(i) How many times is the value of counter printed?
(ii) What is the value of counter printed in the first line?
(iii)What is the value of counter printed in the last line?
Question 4
Dixon Hill is thinking of using signals to allow a parent process to count events that occur in a child process. The idea is to notify the parent each time an event occurs by sending it a signal, and letting the parent's signal handler increment a global counter variable, which the parent can then inspect after the child has terminated. However, when he runs the test program shown below on his system, we discovers that when the parent calls printf, counter always has a value of 2, even though the child has sent five signals to the parent. Perplexed, he comes to you for help. Can you explain the bug?
int counter = 0;
void handler(int sig) {
counter++;
sleep(1);
return;
}
int main() {
int i;
Signal(SIGUSR2, handler);
if (Fork() == 0) {
for (i = 0;i < 5;i++) {
Kill(getppid(), SIGUSR2);
printf(“sent SIGUSR2 to parent\n”);
}
exit(0);
}
Wait(NULL);
printf(“counter=%d\n”, counter);
exit(0);
}
Question 5
pid_t pid;
int counter = 0;
void handler1(int sig) {counter ++; printf("counter = %d\n", counter);
/* Flushes the printed string to stdout */fflush(stdout); kill(pid, SIGUSR1);
}
void handler2(int sig) {counter += 4; printf("counter = %d\n", counter); exit(0);
}
main() { signal(SIGUSR1, handler1); if ((pid = fork()) == 0) {
signal(SIGUSR1, handler2); kill(getppid(), SIGUSR1); while(1) {};
} else {pid_t p; int status; if ((p = wait(&status)) > 0) {
counter += 2; printf("counter = %d\n", counter);
}}
}
What is this program's output?
ThreadsAllow a single program to perform multiple tasks concurrently.
Difference between threads and processes:
Multiple threads (within a process) share memory address space, privileges and all other resources provided by the OS (open files, network sockets... etc.)
What is different between two threads?
CPU register, stack and program counter. These are maintained in the thread control block (TCB).
Challenge: Making sure program executes correctly in all possible interleaving of threads. For example, what happens when you run the following C program?
#include "csapp.h"
#define NITERS 2000000
void *count(void *arg);
unsigned int cnt = 0; /* shared counter variable */
int main() {
pthread_t tid1, tid2;
Pthread_create(&tid1, NULL, count, NULL);
Pthread_create(&tid2, NULL, count, NULL);
Pthread_join(tid1, NULL);
Pthread_join(tid2, NULL);
if (cnt != (unsigned)NITERS*2)
printf("BOOM! cnt=%d\n", cnt);
else
printf("OK cnt=%d\n", cnt);
exit(0);
}
void *count(void *arg) { /* thread routine */
int i;
for (i = 0; i < NITERS; i++)
cnt++;
return NULL;
}
# Run the program over and over
$ sh test.sh
OK cnt=4000000
BOOM! cnt=3490653
BOOM! cnt=3471683
BOOM! cnt=3404617
...
Part of disassembly of the for loop code of function count():
C:
for (i = 0; i < NITERS; i++)
cnt++;
Assembly:
.L12:
movl cnt, %eax #L: Load cnt
leal 1(%eax), %eax #U: Update cnt
movl %eax, cnt #S: Store cnt
Interleaving 1:
Step Thread Instruction %eax1 %eax2 cnt
1 1 L1 0 - 0
2 1 U1 1 - 0
3 1 S1 1 - 1
4 2 L2 - 1 1
5 2 U2 - 2 1
6 2 S2 - 2 2
7 1 L1 2 - 2
8 1 U1 3 - 2
9 1 S1 3 - 3
Interleaving 2:
Step Thread Instruction %eax1 %eax2 cnt
1 1 L1 0 - 0
2 1 U1 1 - 0
3 2 L2 - 0 0
4 1 S1 1 - 1
5 2 U2 - 1 1
6 2 S2 - 1 1
7 1 L1 1 - 1
8 1 U1 2 - 1
9 1 S1 2 - 2
In the next few lectures we'll cover ways to synchronize threads to avoid this problem.
AnswersQuestion 1:
(i) 8 lines(ii) 3 lines(iii)5 lines(iv)counter = 2
Question 2:A, C, and E are possible results. The rest are not.
Question 3:(v) 10(vi) 1(vii) 2
Question 4:Signals cannot be used to count events in other processes because signals are not queued. Solving this problem requires inter-process communication (IPC) mechanisms.
Question 5:Counter = 1Counter = 4Counter = 3