A
real-time system is used when there is a rigid time requirement in the
operation. For example, for medical equipment, traffic lights, computer
systems for cars, etc. There are two types of real-time systems. A hard
real-time systems deal with critical tasks that should be completed on
time while soft real-time systems deal with critical tasks that get the
highest priority until completion.
In
kernel mode, the system has access to an extended set of instructions;
it can modify the interrupt vector, and can modify any section of memory.
In user mode, the system has access to only a restricted set of instructions,
cannot modify the interrupt vector, and has access to a restricted range
of memory.
Modern
CPU's have kernel and user mode because of reliability and security. Reliability
because the user program can crash without crashing other programs. Security
because different user processes are kept separate, and resources can be
protected by unwanted users.
System
calls use software interrupts because software interrupts allow switching
from user to kernel mode. System calls is the way to access operating system
services and need to run in kernel mode. In kernel mode, the system will
have access to the interrupt vector and the memory it will need to perform
its operations.
Steps
for servicing an interrupt
a. interrupt
b. save registers, program counter, return address, etc.
c. go to interrupt vector and jump to address corresponding to that
interrupt
d. execute driver
e. restore all registers and other memory saved in b.
f. return to place in code where interrupt was executed -> to return
address
There
is one program counter and one set of registers for each thread in the
process.
Processes
are in the "waiting" state most of the time. The exception are numerical
analysis programs and screen-savers that are CPU intensive and do not require
to wait for input.
The
advantages of using threads are that process creation is more expensive
than thread creation and context switch among threads are less expensive.
The communication among threads are also very fast. The disadvantages of
threads vs. processes are that with threads there is more chance for a
deadlock and that multiple threads are less robust than multiple processes.
If one thread crashes, the entire process and all the threads will have
to exit.
When
choosing a quantum, you have to consider whether you want a short quantum
or a long quantum. A short quantum produces a short response time, a high
context switch overhead, is good for interactive programs, and produces
longer total time for programs. A long quantum produces longer response
time, lower context switch overhead, is good for batch programs, and produces
shorter total time for programs.
The
advantages of using spinlock vs. disable/enable interrupts are that the
CPU does not need to disable interrupts and that spinlocks can be done
in user space. Disable interrupts is a privileged command done in the kernel.
The disadvantage of spinlock include the CPU being consumed by spinning.
Int test_and_set (
int *v )
{
int
oldval = *v;
*v
= 1;
return
oldval;
}
void spinlock ( int *lock )
{
while
(test_and_set(lock));
}
void spinunlock ( int *lock
)
{
*lock
= 0;
}
This
works because lock is initially set to 0. When the first process calls
spinlock, test_and_set will set lock to 1 and cause the while loop to terminate.
Then, when another process calls spinlock, the lock is already taken and
the new process will continue "spinning" in the while loop until the first
process calls spinunlock which will reset lock to 0.
Process
|
Time
needed for completion (ms)
|
P1
|
40
|
P2
|
5
|
P3
|
30
|
FCFS:0
+ 40 + 45 / 3 = 28.3 ms
SJF:0
+ 5 + 35 / 3 = 13.3 ms
Round
Robin (Quantum=10ms): 0
+ 10 + 15 / 3 = 8.3 ms
13.
(6 pts.) Mark the "C" expressions that are equivalent to a[i]. The
type of a[i] is not necessarily char.
|
||||||||||||||||||
|
14.
(6 pts.) Write a procedure arrayMapper() , that calls the function
func in all the n elements of the array a. The size
of each element in the array a is elementSize. The address
of the array element is passed to func every time func is
called.
|
Note:
The code in red color is the solution. The rest was provided with the problem.
typedef void (*FuncPtr)(void * arg); void arrayMapper( void * a, FuncPtr func, int
n, int elementSize)
} |
15.
(6 pts.) The following code implements a concurrent stack. The push() and
pop() calls can be called simultaneously by different threads. The push()
call blocks until space is available in the stack. The pop() call blocks
until data is available in the stack. Insert the necessary semaphore calls
to implement this behavior. Remember to initialize the semaphores
in main().
|
Note:
The code in red color is the solution. The rest was provided with the problem.
int
stackPointer;
|
16.
(6 pts.) The following program consists of two threads: a client thread
and a server thread. First the client thread reads the numbers a and b,
wakes up the server thread, and then blocks until c is ready. When the
server thread wakes up, it adds a and b, assigns the result to c, wakes
up the client thread, and then goes to sleep. When the client wakes up,
prints the value of c and starts all over again. Complete the following
code and insert semaphore calls where necessary. Remember to initialize
the semaphores in main().
|
Note:
The code in red color is the solution. The rest was provided with the problem.
client_thread()
|
17.
(6 pts.) Complete the procedure redirectStdin( fileName ) to redirect
the standard input from file fileName. The procedure will
return -1 if any error occurrs or 0 if it succeeds. Look at main() to see
how redirectStdin( ) is used. NOTE: ERROR CHECKING IS IMPORTANT.
Also notice that the procedure is called redirectStdin and not redirectStdout.
|
Note:
The code in red color is the solution. The rest was provided with the problem.
int
redirectStdin ( char *filename)
|
18.
(6 pts.) Complete the procedure redirectStdinFromPipe( command, arg1)
that creates a pipe, redirects stdin from the pipe, forks a child process
that redirects its output to the pipe, and then executes a command with
argument arg1. redirectStdinFromPipe() will return -1 if an error
occurrs or 0 if it succeeds. Look at main() to see how redirectStdinFromPipe(
) is used. NOTE: ERROR CHECKING IS IMPORTANT. Also see that the
procedure is called redirectStdinFromPipe and not redirectStdoutToPipe.
|
Note:
The code in red color is the solution. The rest was provided with the problem.
int
redirectStdinFromPipe ( char *command, char *arg1)
const
int bufferSize = 1024;
|
19.
(6 pts.) Write the instructions necessary to eliminate zombie processes.
Your code should print "Child exited" when a child exits.
|
Note:
The code in red color is the solution. The rest was provided with the problem.
void
zombie_process(int x)
struct sigaction z; int main()
|
20.
(6 pts.) Write the code for the function strcpy().
|
Note:
The code in red color is the solution. The rest was provided with the problem.
char
*strcpy ( char *dest, char *src )
*dest = 0;
return(tmp); } |