Unit I: 1.1 OS Structures
Unit I: 1.1 OS Structures
1.1 OS Structures:
1.1.1 Monolithic Operating System
A monolithic kernel is an operating system architecture where the entire operating system is
working in kernel space.
The monolithic model differs from other operating system architectures (such as the microkernel
architecture) in that it alone defines a high-level virtual interface over computer hardware.
A set of primitives or system calls implement all operating system services such as process
management, concurrency, and memory management.
The operating system is divided into a number of layers (levels), each built on top of lower layers.
The bottom layer (layer 0) is the hardware; the highest (layer N) is the user interface.
With modularity, layers are selected such that each uses functions (operations) and services of only
lower-level layers.
The problem is deciding what order in which to place the layers, as no layer can call upon the
services of any higher layer, and so many chicken-and-egg situations may arise.
1.1.3 Microkernel System Structure
Move as much functionality as possible from the kernel into “user” space.
Only a few essential functions in the kernel: primitive memory management (address space), I/O
and interrupt management, Inter-Process Communication (IPC), basic scheduling
Mach was the first and most widely known microkernel, and now forms a major component of Mac
OSX.
Benefits:
More secure
Detriments:
A virtual machine takes the layered approach to its logical next step. It treats hardware and the
operating system kernel as though they were all hardware
The operating system host creates the illusion that a process has its own processor (and virtual
memory)
1.1.5 Exokernel
The idea behind exokernels is to force as few abstractions as possible on application developers,
enabling them to make as many decisions as possible about hardware abstractions.
Exokernels are tiny, since functionality is limited to ensuring protection and multiplexing of
resources, which is considerably simpler than conventional microkernels' implementation of
message passing and monolithic kernels' implementation of high-level abstractions.
More efficient use of hardware resources through precise resource allocation and revocation
1.2 SERVICES PROVIDED BY AN OS:
o The purpose of a computer systems is to allow the user to execute programs. So the
operating systems provides an environment where the user can conveniently run
programs. The user does not have to worry about the memory allocation or multitasking
or anything. These things are taken care of by the operating systems.
o Running a program involves the allocating and deallocating memory, CPU scheduling in
case of multiple process. These functions cannot be given to the user-level programs. So
user-level programs cannot help the user to run programs independently without the help
from operating systems.
I/O Operations
o Each program requires an input and produces output. This involves the use of I/O. The
operating systems hides the user the details of underlying hardware for the I/O. All the
user sees is that the I/O has been performed without any details.
o The output of a program may need to be written into new files or input taken from some
files. The operating system provides this service. The user does not have to worry about
secondary storage management. User gives a command for reading or writing to a file
and sees his / her task accomplished.
Communications
o There are instances where processes need to communicate with each other to exchange
information. It may be between processes running on the same computer or running on
the different computers.
o By providing this service the operating system relieves the user of the worry of passing
messages between processes. In case where the messages need to be passed to processes
on the other computers through a network it can be done by the user programs.
Error Detection
o An error is one part of the system may cause malfunctioning of the complete system. To
avoid such a situation the operating system constantly monitors the system for detecting
the errors. This relieves the user of the worry of errors propagating to various part of the
system and causing malfunctioning.
Parent process create children processes, which, in turn create other processes, forming a tree of processes
Resource sharing
Execution
Address space
UNIX examples
exec system call used after a fork to replace the process’ memory space with a new program
Process executes last statement and asks the operating system to delete it (exit)
Some operating system do not allow child to continue if its parent terminates
These OS are used in big data centers. They can handle thousand of GB of memory. In a batch processing
operating system interaction between the user and processor is limited or there is no interaction at all during
the execution of work. Data and programs that need to be processed are bundled and collected as a ‘batch’
and executed together.
1.4.2 Server OS
They allow many users to connect over a network simultaneously and share hardware & software
resources.
1.4.3 Multiprocessor OS
An operating system that is capable of supporting and utilizing more than one computer processor. Some
examples of multiprocessing operating systems are Linux, Unix, Windows 2000
It is a multitasking operating system that aims at executing real-time applications. Real-time operating
systems often use specialized scheduling algorithms so that they can achieve a deterministic nature of
behavior. The main object of real-time operating systems is their quick and predictable response to events.
They either have an event-driven or a time-sharing design. An event-driven system switches between tasks
based of their priorities while time-sharing operating systems switch tasks based on clock interrupts. They
are of two types:
Hard real time systems
1.4.6 Embedded OS
The operating systems designed for being used in embedded computer systems are known as
embedded operating systems.
They are designed to operate on small machines like PDAs with less autonomy. They are able to
operate with a limited number of resources. They are very compact and extremely efficient by
design. Windows CE, FreeBSD and Minix 3 are some examples of embedded operating systems.
Each process is represented in operating system by a process control block. It contains the following
information associated with each process -
CPU registers: The registers like accumulators, index registers, stack pointer and all the general
purpose registers.
CPU scheduling information: The information includes process priority and other scheduling
parameters.
Memory-management information: the information may include the value of base and limit
registers, page tables and segment tables.
Accounting information: the information includes amount of CPU time used and process numbers.
I/O status information: It includes list of I/O devices allocated to the process.
1.5.2 Process States
When CPU switches to another process, the system must save the state of the old process and load
the saved state for the new process
Context-switch time is overhead; the system does no useful work while switching
A scheduler is a type of system software that allows you to handle process scheduling.
Long term is also known as a job Short term is also known as CPU Medium-term is also called
scheduler scheduler swapping scheduler.
Speed is less compared to the short Speed is the fastest compared to the It offers medium speed.
term scheduler. short-term and medium-term
scheduler.
Preemptive scheduling is used when a process switches from running state to ready state or from
waiting state to ready state.
The resources (mainly CPU cycles) are allocated to the process for the limited amount of time and
then is taken away, and the process is again placed back in the ready queue if that process still has
CPU burst time remaining.
That process stays in ready queue till it gets next chance to execute.
There are several different criteria to consider when trying to select the "best" scheduling algorithm for a
particular situation and environment, including:
In general one wants to optimize the average value of a criteria (Maximize CPU utilization and throughput,
and minimize all the others.) However sometimes one wants to do something different, such as to minimize
the maximum response time.
Since context switches only occur upon process termination, and no reorganization of the process
queue is required, scheduling overhead is minimal.
Throughput can be low, since long processes can hog the CPU
Turnaround time, waiting time and response time can be high for the same reasons above
No prioritization occurs, thus this system has trouble meeting process deadlines.
The lack of prioritization means that as long as every process eventually completes, there is no
starvation.
If a shorter process arrives during another process' execution, the currently running process may be
interrupted (known as preemption), dividing that process into two separate computing blocks. This
creates excess overhead through additional context switching. The scheduler must also place each
incoming process into a specific place in the queue, creating additional overhead.
Waiting time and response time increase as the process' computational requirements increase.
Overall waiting time is smaller than FCFS, however since no process has to wait for the termination
of the longest process.
No particular attention is given to deadlines; the programmer can only attempt to make processes
with deadlines as short as possible.
Starvation is possible, especially in a busy system with many small processes being run.
Waiting time and response time depend on the priority of the process. Higher priority processes
have smaller waiting and response times.
Starvation of lower priority processes is possible with large amounts of high priority processes
queuing for CPU time.
Balanced throughput between FCFS and SJF, shorter jobs are completed faster than in FCFS and
longer processes are completed faster than in SJF.
Fastest average response time, waiting time is dependent on number of processes, and not average
process length.
Because of high waiting times, deadlines are rarely met in a pure RR system.
Starvation can never occur, since no priority is given. Order of time unit allocation is based upon
process arrival time, similar to FCFS.
This is used for situations in which processes are easily divided into different groups.
For example, a common division is made between foreground (interactive) processes and
background (batch) processes. These two types of processes have different response-time
requirements and so may have different scheduling needs.
Processes frequently need to communicate with other processes. For example, in a shell pipeline, the output
of the first process must be passed to the second process, and so on down the line. Thus there is a need for
communication between processes, preferably in a well-structured way not using interrupts.
1.10.1 Message passing vs Shared memory
Situations where two or more processes are reading or writing some shared data and the final result depends
on who runs precisely when are called race conditions. Debugging programs containing race conditions is
very complex.
The problem of avoiding race conditions can also be formulated in an abstract way. Part of the time, a
process is busy doing internal computations and other things that do not lead to race conditions. However,
sometimes a process may be accessing shared memory or files. That part of the program where the shared
memory is accessed is called the critical region or critical section. If we could arrange matters such that no
two processes were ever in their critical regions at the same time, we could avoid race conditions.
In this section we will examine various proposals for achieving mutual exclusion, so that while one process
is busy updating shared memory in its critical region, no other process will enter its critical region and
cause trouble.
Disadvatages
In fact, this solution requires that the two processes strictly alternate in entering their critical regions, for
example, in spooling files. Neither one would be permitted to spool two in a row. While this algorithm does
avoid all races, it is not really a serious candidate as a solution because a process outside its critical section
is prohibiting another process from entering its critical section.
Now let us look at a proposal that requires a little help from the hardware. Many computers, especially
those designed with multiple processors in mind, have an instruction
(Test and Set Lock) that works as follows: it reads the contents of the memory word LOCK into register
RX and then stores a nonzero value at the memory address LOCK. The operations of reading the word and
storing into it are guaranteed to be indivisible. No other processor can access the memory word until the
instruction is finished. The CPU executing the TSL instruction locks the memory bus to prohibit other
CPUs from accessing memory until it is done.
To use the TSL instruction, we will use a shared variable, LOCK, to coordinate access to shared memory.
When LOCK is 0, any process may set it to 1 using the TSL instruction and then read or write the shared
memory. When it is done, the process sets LOCK back to 0 using an ordinary move instruction.
There a four-instruction subroutine in a fictitious (but typical) assembly language is shown. The first
instruction copies the old value of LOCK to the register and then sets LOCK to 1. Then the old value is
compared with 0. If it is nonzero, the lock was already set, so the program just goes back to the beginning
and tests it again. Sooner or later it will become 0 (when the process currently in its critical region is done
with its critical region), and the subroutine returns, with the lock set. Clearing the lock is simple. The
program just stores a 0 in LOCK. No special instructions are needed.
enter_region:
JNE ENTER_REGION |if it was non zero, LOCK was set, so loop
RET |return to caller; critical region entered
leave_region:
Not only do the above approaches waste CPU time, but it can also have unexpected effects. Consider a
computer with two processes, H, with high priority and L, with low priority, which share a critical region.
The scheduling rules are such that H is run whenever it is in ready state. At a certain moment, with L in its
critical region, H becomes ready to run (e.g., an I/O operation completes). H now begins busy waiting, but
since L is never scheduled while H is running, L never gets the chance to leave its critical region, so H
loops forever. This situation is sometimes referred to as the priority inversion problem.
Now let us look at some inter process communication primitives that block instead of wasting CPU time
when they are not allowed to enter their critical regions. One of the simplest is the pair sleep and wakeup.
Sleep is a system call that causes the caller to block, that is, be suspended until another process wakes it up.
The wakeup call has one parameter, the process to be awakened. Alternatively, both sleep and wakeup each
have one parameter, a memory address used to match up sleeps with wakeups.
1.10.6 Semaphores
It is simply a variable which is non-negative and shared between threads. This variable is used to solve the
critical section problem and to achieve process synchronization in the multiprocessing environment.
Semaphores are of two types:
Binary Semaphore
o This is also known as mutex lock.
o It can have only two values – 0 and 1. Its value is initialized to 1. It is used to implement the
solution of critical section problem with multiple processes.
Counting Semaphore
o Its value can range over an unrestricted domain.
o It is used to control access to a resource that has multiple instances.
Now, look at two operations which can be used to access and change the value of the semaphore variable.
1. P operation is also called wait, sleep or down operation and V operation is also called signal, wake-
up or up operation.
2. Both operations are atomic and semaphore(s) is always initialized to one. Here atomic means that
variable on which read, modify and update happens at the same time/moment with no pre-emption
i.e. in between read, modify and update no other operation is performed that may change the
variable.
3. A critical section is surrounded by both operations to implement process synchronization. See below
image - critical section of Process P is in between P and V operation.
Now, let us see how it implements mutual exclusion. Let there be two processes P1 and P2 and a
semaphore s is initialized as 1. Now if suppose P1 enters in its critical section then the value of semaphore s
becomes 0. Now if P2 wants to enter its critical section then it will wait until s > 0, this can only happen
when P1 finishes its critical section and calls V operation on semaphore s. This way mutual exclusion is
achieved. Look at the below image for details which is Binary semaphore.
1.11 Threads:
They are the smallest unit of execution. Each thread has its own TCB.
Each process has its own address space, but the threads within the same process share that address
space. Threads also share any other resources within that process. This means that it’s very easy to
share data amongst threads, but it’s also easy for the threads to step on each other, which can lead to
bad things.
The overhead (the cost of communication) between threads is very low relative to processes.
Threads are easier to create than processes since they don't require a separate address space.
Threads are considered lightweight because they use far less resources than processes.
Advantages
Responsiveness: If a thread gets a lot of cache misses, the other thread(s) can continue, taking
advantage of the unused computing resources, which thus can lead to faster overall execution.
Resource sharing: If a thread cannot use all the computing resources of the CPU (because
instructions depend on each other's result), running another thread can avoid leaving these idle.
Utilization of multiprocessor architectures. The benefits of multithreading can be greatly increased
in a multiprocessor architecture, where threads may be running in parallel on different processors. A
single threaded process can only run on one CPU, no matter how many are available.
Economy: Allocating memory and resources for process creation is costly. Because threads share
resources of the process to which they belong, it is more economical to create and context-switch
threads.
Disadvantages
Multiple threads can interfere with each other when sharing hardware resources such as caches or
translation lookaside buffers (TLBs).
Execution times of a single thread are not improved but can be degraded, even when only one thread
is executing. This is due to slower frequencies and/or additional pipeline stages that are necessary to
accommodate thread-switching hardware.
Hardware support for multithreading is more visible to software, thus requiring more changes to
both application programs and operating systems than multiprocessing.
Advantages:
Because kernel has full knowledge of all threads, Scheduler may decide to give more time to a
process having large number of threads than process having small number of threads.
Kernel-level threads are especially good for applications that frequently block.
Disadvantages:
The kernel-level threads are slow and inefficient. For instance, threads operations are hundreds of
times slower than that of user-level threads.
Since kernel must manage and schedule threads as well as processes. It requires a full thread control
block (TCB) for each thread to maintain information about threads. As a result there is significant
overhead and increased in kernel complexity.
1.11.2.2 User-Level Threads
User-Level threads are managed entirely by the run-time system (user-level library).
The kernel knows nothing about user-level threads and manages them as if they were single-
threaded processes.
User-Level threads are small and fast, each thread is represented by a PC, register, stack, and small
thread control block.
Advantages:
The most obvious advantage of this technique is that a user-level threads package can be
implemented on an Operating System that does not support threads.
User-level threads do not require modification to operating systems.
Simple Management: This simply means that creating a thread, switching between threads and
synchronization between threads can all be done without intervention of the kernel.
Fast and Efficient: Thread switching is not much more expensive than a procedure call.
Disadvantages:
Since, User-Level threads are invisible to the OS they are not well integrated with the OS. As a
result, Os can make poor decisions like scheduling a process with idle threads, blocking a process
whose thread initiated an I/O.
There is a lack of coordination between threads and operating system kernel. Therefore, process as
whole gets one time slice irrespective of whether process has one thread or 1000 threads within. It is
up to each thread to relinquish control to other threads.
1.11.3 Multithreading models
1.11.3.1 Many-to-one
In this model, the library maps all threads to a single lightweight process
Mainly used in language systems, portable libraries
Advantages:
totally portable
easy to do with few systems dependencies
Disadvantages:
cannot take advantage of parallelism
may have to block for synchronous I/O
there is a clever technique for avoiding it
1.11.3.2 One-to-one
In this model, the library maps each thread to a different lightweight process
Used in LinuxThreads and other systems where LWP creation is not too expensive
Advantages:
Disadvantages:
1.11.3.3 Many-to-many
In this model, the library has two kinds of threads: bound and unbound
o bound threads are mapped each to a single lightweight process
o unbound threads may be mapped to the same LWP
Probably the best of both worlds.