Midterm Examination #1 | COP 4610 - Operating Systems |
This is a closed-book examination. You are not allowed to use any notes or other references during the exam. You will have 50 minutes to answer all the questions. Answer the true/false and short-answer questions on this paper. Answer the long-answer questions on the paper provided to you. There are 12 numbered questions, each worth 10 points, but you will probably find some questions are easier for you than others. Therefore, it is important to budget your time. Do not miss the chance to answer some easier questions by puzzling too long over a question that is giving you difficulty. Remember to write your name on every page, and turn in all pages of the exam.
It is not deallocated until the "last close". That is, until the count of references from file descriptors of processes to the open file description goes to zero.
This is also true for open file descriptions.
Kernel traps have more execution time overhead than function calls.
The reverse is true. Reducing process-level blocking is one of the main reasons for putting the thread implementation into the OS kernel.
This was his first example of the suspended state.
Static local variables are sure to make the procedure non-reentrant.
What is the effect of the Unix kill() system call?
To send a specified signal to a process or a set of processes.
Describe the possible effects on a Unix process of receiving a signal, such as SIGALRM.
For most signals, including SIGALRM the default signal action is to terminate the process. That is the effect if there is no handler installed for the signal. If a handler is installed, the effect of the signal is to cause the handler to be executed by the process, interrupting whatever the process is doing at the time. (There are more details and special cases, but that is enough to earn full credit for this question.)
What are the three main disadvantages/problems with using a machine instruction to implement mutual exclusion, e.g., using a test-and-set instruction to busy-wait on a lock variable?
busy-waiting wastes processor time
starvation is possible
if the processor can be preempted (in response to an interrupt) during a critical section, we have deadlock
Give four examples of information that ordinarily would be saved in a process control block, but not in a thread control block.
process id
reference/link to parent process
reference/link to set of child processes
reference/link to set of threads
signal handler/action mapping table
information needed to manage virtual memory
etc.
Explain what is meant by starvation in the context of a solution to the mutual exclusion problem.
A condition in which a process is indefinitely delayed because other processes are always given preference. This is distinguished from deadlock by the fact that all the resources continue to be granted and released. The problem is that they are always going to other processes.
Suppose there is a (non-virtual memory) system that has only 200 Mb of main memory and there are two processes that make the following sequence of requests:
P1 | P2 | |
---|---|---|
... | ... | |
Request 80Mb; | Request 70Mb; | |
... | ... | |
Request 60Mb; | Request 80Mb; |
How could a system avoid this kind of deadlock?
The system should apply the Banker's Algorithm, which would have the effect of delaying granting the first request of one of the processes until the other process has completed and released its resources. A complete answer would show how the algorithm would avoid the deadlock.
Is it possible for the two threads to deadlock by concurrent calls to the functions A and B below? If so, give an example of an execution trace that leads up to deadlock. If not, explain why deadlock is impossible, appealing to the four necessary conditions for deadlock in Chapter 6. Answer on a separate sheet of paper.
void A (){ ... pthread_mutex_lock (&M2); pthread_mutex_lock (&M1); ... critical section ... pthread_mutex_unlock (&M1); pthread_mutex_unlock (&M2); } void B (){ ... pthread_mutex_lock (&M1); pthread_mutex_lock (&M2); ... critical section ... pthread_mutex_unlock (&M2); pthread_mutex_unlock (&M1); }
There is a deadlock if the two processes execute in the following interleaved order:
A | pthread_mutex_lock (&M2); | succeeds |
B | pthread_mutex_lock (&M1); | succeeds |
A | pthread_mutex_lock (&M1); | blocks |
B | pthread_mutex_lock (&M2); | blocks |
What is the output of the following program? Answer by writing on this page.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> int main () { int n, status; pid_t child; n = 0; if (!(child = fork())) { n = 1; fprintf (stderr, "n = %d\n", n); n = 2; } else { n = 3; fprintf (stderr, "n = %d\n", n); n = 4; exit (0); fprintf (stderr, "n = %d\n", n); } waitpid (child, &status, 0); n = 5; fprintf (stderr, "n = %d\n", n); return 0; }
This program is similar-looking to the one in the sample examination, but important details have been changed. This program reflects what would happen if a person made two typical programming errors:
Three different output sequences are possible, depending on how the system schedules processes. The most likely scheduling is for the system to allow the parent process to continue until it blocks, and then execute the child process. That would result in the following output:
n = 3 n = 1 n = 5
The following code is intended to implement one of the operations on a counting semaphore.
pthread_mutex_lock (&S.mut); while (S.count == 0) pthread_cond_wait (&S.cond, &S.mut); S.count --; pthread_mutex_unlock (&S.mut);
The name of the operation implemented above is ___wait___
The other operation can be implemented as follows:
pthread_mutex_lock (&S.mut); S.count++; pthread_cond_signal (&S.cond); pthread_mutex_unlock (&S.mut);
Explain how a lockfile may be used to implement mutual exclusion between two processes. Your answer should include pseudo-code for the lock and unlock operations. Answer on separate paper.
Before entering a critical section, each process tries to create a lockfile, using the same pathname for the file. If a process fails to create the file, it sleeps a short time and then retries. Once a process has created the lockfile it enters the critical section. On leaving the critical section, a process unlinks the lockfile.lock: while (attempt to create lockfile fails) { sleep a short time; } unlock: unlink lockfile;