It can be said that the kernel turns the hardware into a virtual machine. That is, the kernel supplies abstraction layer that allows the application programmer to use the same system calls across different devices.
This gives many benefits to the application programmer. Mainly:
- The application programmer doesn't have to use several different calls for different pieces of hardware. The operating system takes care of this. For example, if the programmer wanted to make some write to a hard disk, memory key, etc. Its just a matter of calling the appropriate I/O instructions supplied by the kernel.
- It takes care of context switches between threads and processes.
Dual-mode operation forms the basis for I/O protection, memory protection and CPU protection. In dual mode operation there are two modes: Kernel mode and user mode. In kernel mode, the CPU can use all instructions and access all areas of memory. In user mode, the CPU is restricted to unprivileged instructions and a specified area of memory.
Since each users process is allocated specific areas of memory and they are executed within user mode they are unable to modify each other without using system calls.
Again, since a users process is ran in user mode it only has access to a specific area of memory. This prevents the users process from injecting code into the operating system area.
x - data
p - heap
*p - stack
Thread control block contains:
- Thread ID
- Saved registers, stack pointer, instruction pointer.
- Stack
- Signal Mask
- Priority
Process control block contains:
- Machine state
- Parent process state
- Process state
- Event descriptor
- Memory map
- Open file descriptors
- Owner
- Scheduling Paramaters
- Signals that have not yet been handled
- Timers for accounting
- Process group
A Process control block is bigger.
Pass some shared integer to each thread. Only allow the thread to execute when the integer is a certain value.
E.g.
public synchronized void run() {
while(turn != 2) {
try {
wait();
} catch(InterruptedException e) {
}
System.out.print("Love ");
turn = 1;
notifyAll();
}
}Pass a shared semaphore to all of the reads. Set the semaphore state to be 0. After the first thread finishes executing release the semaphore.
E.g.
public void run() {
System.out.print("We ");
sem.release();
}public void run() {
try {
sem.acquire()
sleep((int)(Math.random()*100));
} catch(InterruptedException e) {
}
System.out.println("love ");
sem.release();
}
