Anda di halaman 1dari 9

CS61: Systems Programming and

Machine Organization
Section Notes
Week of Nov 9
th

Outline for this week:
! Forks
! Signal Handlers
! Threads
Forks and Handlers
Question 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?
Threads
Allow 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.
Answers
Question 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 = 1
Counter = 4
Counter = 3

Anda mungkin juga menyukai