Answer: From Running to Ready
> Why is this done (rather than just letting
the process run to completion)?
>
Answer: To allow multitasking/timesharing.
This gives the illusion to a
number of users using the computer as if their
requests are being serviced
concurrently.
>
> Name two pieces of information about the
process that need to be saved when
> this transition occurs and explain why they
need to be saved.
>
>
Two things which might need to be saved are,
PC : This is required so that when the process
is re-scheduled, the kernel
should know which instruction to start executing.
Other registers, stack, and process environment
need to be saved so that
when the process resumes it has the same environment
that it had before.
> B. Protection.
>
> How can an O/S protect one process from
interference from another process
> (such as having its memory overwritten)?
An OS can protect a process from modifying
its own code segment by
making it read-only. The OS can manage the
memory of several processes
from interfering with each other by keeping
track of the memory in usage
by different processes in their process table.
Since the OS is the only
entity to allocate and deallocate memory resources
for the processes and
keep track of it, it ensures protection.
> What hardware is needed to enforce this protection? Why?
Processors need to have hardware bits which
indicate priveleage
levels. For example if you have 2 hardware
bits then upto 4 priveleage
levels can be formed. These are sometimes
called segments. A base register and a
length register can identify a valid adress
within a segment. (For more
information refer to Tannenbaum chapter 2
pg 94)
For a shell to execute the given command line, how many times would it
fork?_3___
For each command (man, grep, grep), the shell will fork off a child and call exec for the given command. Here "-K convert" are the arguments for the" man "command.
So the shell fork off 3 times and call exec functions 3 times.
B. Process termination.
If the shell contained the following code, executed before it begins to
read commands from the prompt, how many times would the printf statement be
called when executing the command line given above? (Assume that the
registration of the exit function succeeds.) Explain your answer.
Q4. Process Control, again. (20 pts.)
...
int main(void){
pid_t cpid; int status;
cpid = fork();
if (cpid == 0) {
printf("Child Process\n");
if (wait (NULL) > 0)
exit(0);
else
exit(1);
} else if (cpid > 0){
waitpid(-1, &status, WNOHANG);
printf("Parent Process\n");
exit(0);
} else {
printf("Fork failed\n");
exit(2);
}
}
Given the code above, which statement will
be printed first on a
POSIX-compliant system, assuming that the fork
succeeds? Explain your
answer.
Either of the printf
statements, "Child Process" or "Parent Process". Since the waitpid in the
parent process is executed with a WNOHANG clause. The parent does not wait
for the child and can print the statement. Since we assume the fork succeeds
the child can also execute the printf statement in its code.
What value will be returned by the parent process?
Explain your answer.
Parent returns a value
0, if the fork is successful. The parent code has a non-blocking wait,
a print and an exit statement with 0 as status, which is returned.
What value will be returned by the child process?
Explain your answer.
1. Since child process
does not have a child of its own the Wait(NULL) returns a value 0 and the
else block gets executed and it has an exit statement with 1 as status.
If this program is compiled and run from a
shell, what value will be
returned to the shell? Explain your answer.
0. Only the parent process
returns to the shell. The child process returns to the parent. Since parent
executes exit(0), 0 is returned to the shell.
Q5. Signals. (20 pts.)
/* Code Style 1 */
...
/* fork off child */
...
while (cpid = waitpid(-1, &status, WNOHANG)
== 0)
sleep(30);
...
/* deal with exited child */
...
________________________________________
/* Code Style 2 */
...
void handle_child_exit(int);
static struct sigaction act;
act.sa_handler = handle_child_exit;
sigfillset(&(act.sa_mask));
sigaction(SIGCHLD, &act, NULL);
...
/* fork off child */
...
void handle_child_exit(int signo){
...
/* deal with exited child */
...
}
List and explain two advantages of the second
coding style over the first.
adv 1: The first code
sleeps for 30 seconds everytime before seeing if the child has finished
executing. This could potentially waste 30 secs of time. If the child exits
just after the wait is done by the parent. The second code immediately
handles the exited child.
adv 2: In the second
code the parent can do some other useful work instead of waiting for the
child process. In the first code, parent process is stuck in the loop.
adv 3: The first code
wastes extra CPU cycles since it executes a wait statement every 30 seconds
even if the child isn't ready.
adv 4: The second code
can mask any signals from disturbing it when handling the child exit.
% man -k convert | grep pnm | grep ps
A. fork and exec.
How many time would it call an exec family function? _3___
Explain your answers.
...
void my_exit_fcn (void){
printf ("Exiting shell ... \n");
}
...
atexit(my_exit_fcn);
...
/* code for reading from command lines, forking, exec-ing, etc. */
...
Ans:
This printf statement would never be showed up on the screen. This code would never be executed unless the shell itself exits.In the above, the shell forks off 3 processes and executed and they have their own exit handlers when they are finished.So the shell would wait for the users to input after the above command is executed.