Os 101 Notes
Os 101 Notes
An Operating System (OS) is an interface between computer user and computer hardware. An operating
system is software which performs all the basic tasks like file management, memory management, process
management, handling input and output, and controlling peripheral devices such as disk drives and printers.
An operating system is a program that acts as an interface between the user and the computer hardware and
controls the execution of all kinds of programs.
Memory Management
Processor Management
Device Management
File Management
Security
o Availability : protecting system against interruption
o Confidentiality: avoiding unauthorized access of data
o Data integrity: protection of data from unauthorized modifications
o Authenticity : identity of users and validity of message or data
Control over system performance
Job accounting
Error detecting aids
Coordination between other software and users
Memory Management
Memory management refers to management of Primary Memory or Main Memory. Main memory is a large array
of words or bytes where each word or byte has its own address.
Main memory provides a fast storage that can be accessed directly by the CPU. For a program to be executed, it
must in the main memory. An Operating System does the following activities for memory management −
Keeps tracks of primary memory, i.e., what part of it are in use by whom, what parts are not in use.
In multiprogramming, the OS decides which process will get memory when and how much.
Allocates the memory when a process requests it to do so.
De-allocates the memory when a process no longer needs it or has been terminated.
Processor Management
In multiprogramming environment, the OS decides which process gets the processor when and for how much
time. This function is called process scheduling. An Operating System does the following activities for processor
management −
Keeps tracks of processor and status of process. The program responsible for this task is known as traffic
controller.
Allocates the processor (CPU) to a process.
De-allocates processor when a process is no longer required.
Device Management
An Operating System manages device communication via their respective drivers. It does the following
activities for device management −
Keeps tracks of all devices. Program responsible for this task is known as the I/O controller.
Decides which process gets the device when and for how much time.
Allocates the device in the efficient way.
De-allocates devices.
File Management
A file system is normally organized into directories for easy navigation and usage. These
directories may contain files and other directions.
An Operating System does the following activities for file management −
Keeps track of information, location, uses, status etc. The collective facilities are often known as file
system.
Decides who gets the resources.
Allocates the resources.
De-allocates the resources.
Other Important Activities
Following are some of the important activities that an Operating System performs −
Security − By means of password and similar other techniques, it prevents unauthorized access to
programs and data.
Control over system performance − Recording delays between request for a service and response from
the system.
Job accounting − Keeping track of time and resources used by various jobs and users.
Error detecting aids − Production of dumps, traces, error messages, and other debugging and error
detecting aids.
Coordination between other softwares and users − Coordination and assignment of compilers,
interpreters, assemblers and other software to the various users of the computer systems.
Problem of reliability.
Question of security and integrity of user programs and data.
Problem of data communication.
With resource sharing facility, a user at one site may be able to use the resources available at another.
Speedup the exchange of data with one another via electronic mail.
If one site fails in a distributed system, the remaining sites can potentially continue operating.
Better service to the customers.
Reduction of the load on the host computer.
Reduction of delays in data processing.
Characteristics of multiprogramming:
In a multiprogramming system there are one or more programs loaded in main memory which are ready to execute.
Only one program at a time is able to get the CPU for executing its instructions (i.e., there is at most one process
running on the system) while all the others are waiting their turn.
The main idea of multiprogramming is to maximize the use of CPU time. Indeed, suppose the currently running
process is performing an I/O task (which, by definition, does not need the CPU to be accomplished). Then, the OS
may interrupt that process and give the control to one of the other in-main-memory programs that are ready to
execute (i.e. process context switching). In this way, no CPU time is wasted by the system waiting for the I/O task to
be completed, and a running process keeps executing until either it voluntarily releases the CPU or when it blocks
for an I/O operation. Therefore, the ultimate goal of multiprogramming is to keep the CPU busy as long as there are
processes ready to execute.
Multiprocessing
Multiprocessing sometimes refers to executing multiple processes (programs) at the same time. This might be
misleading because we have already introduced the term “multiprogramming” to describe that before.
In fact, multiprocessing refers to the hardware (i.e., the CPU units) rather than the software (i.e., running processes).
If the underlying hardware provides more than one processor then that is multiprocessing. Several variations on the
basic scheme exist, e.g., multiple cores on one die or multiple dies in one package or multiple packages in one
system.
Anyway, a system can be both multiprogrammed by having multiple programs running at the same time and
multiprocessing by having more than one physical processor.
Process
A Program in execution. An instance of a program running on a computer
Process State
The current state of the process i.e., whether it is ready, running, waiting, or whatever.
Process privileges
This is required to allow/disallow access to system resources.
Process ID
Unique identification for each of the process in the operating system.
Pointer
A pointer to parent process.
Program Counter
Program Counter is a pointer to the address of the next instruction to be executed for this process.
CPU registers
Various CPU registers where process need to be stored for execution for running state.
CPU Scheduling Information
Process priority and other scheduling information which is required to schedule the process.
Memory management information
This includes the information of page table, memory limits, Segment table depending on memory used by
the operating system.
Accounting information
This includes the amount of CPU used for process execution, time limits, execution ID etc.
IO status information
This includes a list of I/O devices allocated to the process
The architecture of a PCB is completely dependent on Operating System and may contain different
information in different operating systems. Here is a simplified diagram of a PCB
The PCB is maintained for a process throughout its lifetime, and is deleted once the process terminates.
Process Life Cycle
When a process executes, it passes through different states. These stages may differ in different operating
systems. In general, a process can have one of the following five states at a time.
Start
This is the initial state when a process is first started/created.
Ready
The process is waiting to be assigned to a processor. Ready processes are waiting to have the processor
allocated to them by the operating system so that they can run. Process may come into this state after Start state or
while running it by but interrupted by the scheduler to assign CPU to some other process.
Running
Once the process has been assigned to a processor by the OS scheduler, the process state is set to running
and the processor executes its instructions.
Waiting
Process moves into the waiting state if it needs to wait for a resource, such as waiting for user input, or
waiting for a file to become available.
Terminated or Exit
Once the process finishes its execution, or it is terminated by the operating system, it is moved to the terminated
state where it waits to be removed from main memory.
In this model, a process may be in one of two states: Running or Not Running. When the OS creates a new
process, it creates a process control block for the process and enters that process into the system in the Not Running
state. The process exists, is known to the OS, and is waiting for an opportunity to execute. From time to time, the
currently running process will be interrupted and the dispatcher portion of the OS will select some other process to
run. The former process moves from the Running state to the Not Running state, and one of the other processes
moves to the Running state.
A five state process model
In two state process model, if some processes in the Not Running state are ready to execute, while others
are blocked, waiting for an I/O operation to complete. Thus, using a single queue, the dispatcher could not just select
the process at the oldest end of the queue. Rather, the dispatcher would have to scan the list looking for the process
that is not blocked and that has been in the queue the longest. To handle this situation is to split the Not Running
state into two states: Ready and Blocked.
New: A process that has just been created but has not yet been admitted to the pool of executable processes by the
OS. Typically, a new process has not yet been loaded into main memory, although its process control block has been
created.
Ready: A process that is prepared to execute when given the opportunity.
Running: The process that is currently being executed.
Blocked/Waiting: A process that cannot execute until some event occurs, such as the completion of an I/O
operation.
Exit: A process that has been released from the pool of executable processes by the OS, either because it halted or
because it aborted for some reason.
Blocked/Suspend to Ready/Suspend: A process in the Blocked/Suspend state is moved to the Ready/Suspend state
when the event for which it has been waiting occurs. Note that this requires that the state information concerning
suspended processes must be accessible to the OS.
Ready/Suspend to Ready: When there are no ready processes in main memory, the OS will need to bring one in to
continue execution. In addition, it might be the case that a process in the Ready/Suspend state has higher priority
than any of the processes in the Ready state. In that case, the OS designer may dictate that it is more important to get
at the higher-priority process than to minimize swapping.
Ready to Ready/Suspend: Normally, the OS would prefer to suspend a blocked process rather than a ready one,
because the ready process can now be executed, whereas the blocked process is taking up main memory space and
cannot be executed. However, it may be necessary to suspend a ready process if that is the only way to free up a
sufficiently large block of main memory. Also, the OS may choose to suspend a lower-priority ready process rather
than a higher priority blocked process if it believes that the blocked process will be ready soon. Several other
transitions that are worth considering are the following:
New to Ready/Suspend and New to Ready: When a new process is created, it can either be added to the Ready
queue or the Ready/Suspend queue. In either case, the OS must create a process control block and allocate an
address space to the process. It might be preferable for the OS to perform these housekeeping duties at an early time,
so that it can maintain a large pool of processes that are not blocked. With this strategy, there would often be
insufficient room in main memory for a new process; hence the use of the (New SReady/Suspend) transition. On the
other hand, we could argue that a just-in-time philosophy of creating processes as late as possible reduces OS
overhead and allows that OS to perform the process-creation duties at a time when the system is clogged with
blocked processes anyway.
Blocked/Suspend to Blocked: Inclusion of this transition may seem to be poor design. After all, if a process is not
ready to execute and is not already in main memory, what is the point of bringing it in? But consider the following
scenario: A process terminates, freeing up some main memory. There is a process in the (Blocked/Suspend) queue
with a higher priority than any of the processes in the (Ready/Suspend) queue and the OS has reason to believe that
the blocking event for that process will occur soon. Under these circumstances, it would seem reasonable to bring a
blocked process into main memory in preference to a ready process.
Running to Ready/Suspend: Normally, a running process is moved to the Ready state when its time allocation
expires. If, however, the OS is preempting the process because a higher-priority process on the Blocked/Suspend
queue has just become unblocked, the OS could move the running process directly to the (Ready/Suspend) queue
and free some main memory.
Any State to Exit: Typically, a process terminates while it is running, either because it has completed or because of
some fatal fault condition. However, in some operating systems, a process may be terminated by the process that
created it or when the parent process is itself terminated. If this is allowed, then a process in any state can be moved
to the exit state.
Other reasons
Collection of program, data, stacks, and attributes as the process image. The location of a process image
will depend on the memory management scheme being used. The process image is maintained as a contiguous, or
continuous, block of memory. This block is maintained in secondary memory, usually disk.
To execute the process, the entire process image must be loaded into main memory or at least virtual
memory. when a process is swapped out, part of the process image may remain in main memory. Thus, the OS must
keep track of which portions of the image of each process are still in main memory.
1. User Data
The modifiable part of the user space. May include program data, a user stack area, and programs
that may be modified.
2. User Program
The program to be executed
3. Stack
Each process has one or more last-in-first-out (LIFO) stacks associated with it. A stack is used to
store parameters and calling addresses for procedure and system calls.
4. Process Control Block
Data needed by the OS to control the process
Modes of Execution
Kernel Mode: The kernel is the "core" of any computer system. In Kernel mode, the executing code has complete
and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory
address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system.
Kernel Mode functions:
Memory Management
Process Management
I/O Management
User Mode: In User mode, the executing code has no ability to directly access hardware or reference memory.
Users can run applications.
Process Creation:
When OS decides to create a new process, it follows the following procedure
Process Switching
When a running process is interrupted and the OS assigns another process to the running state and turns
control over to that process. A process switch may occur any time when OS gained control over the currently
running process. When following events occur, OS may get control over the processes.
1. Interrupt
2. Trap
3. Supervisor call
Processor Scheduling
1. Long term scheduling: Long-term scheduling is performed when a new process is created. This is a
decision whether to add a new process to the set of processes that are currently active. A long-term
scheduler determines which programs are admitted to the system for processing. It is also called a job
scheduler.
2. Short term scheduling: Short-term scheduling is the actual decision of which ready process to execute next.
It is the change of ready state to running state of the process. CPU scheduler selects a process among the
processes that are ready to execute and allocates CPU to one of them. Short-term schedulers, also known as
dispatchers, make the decision of which process to execute next. Short-term schedulers are faster than long-
term schedulers. It is also called a CPU scheduler.
3. Medium term scheduling: Medium-term scheduling is a part of swapping. It removes the processes from
the memory. The medium-term scheduler is in-charge of handling the swapped out-processes.
Scheduling Criteria:
Scheduling Algorithms
Non preemptive algorithm: In non preemptive algorithms, once the process enters the running state, it can not be
preempted until it completes its allotted time.
Preemptive algorithm: In preemptive algorithms, scheduler may preempt a low priority running process any time
when a high priority process enters into a ready state.
Quantum is 5
Process TAT=WT+BT
P1 0+(15-5)+(21-20)+(21-21)+(26-26)
P2 5
P3 8+(20-13)
P4 13
Average TAT:
Priority Scheduling:
Priority scheduling is a method of scheduling processes based on priority. In this each process is
assigned with some priority. The scheduler chooses the tasks to work as per the priority. Processes with
higher priorities are carried out first. It is often possible that a priority scheduling algorithm can make a
low-priority process wait indefinitely.
P1 6 3
P2 2 2
P3 14 1
P4 6 4
P3 P2 P1 P4
0 14 16 22 28
P1 16 22
P2 14 16
P3 0 14
P4 22 28
Average W.T : 13
Average T.A.T : 20
SRT is preemptive version of SJF. The scheduler always chooses the process that has the shortest expected
remaining processing time. When a new process joins the ready queue, it may in fact have a shorter remaining
time than the currently running process. The scheduler may preempt the current process when a new process
becomes ready. It gives more TAT performance compared to SJF. There may be chance of starvation.
R= (W+S)/S
R=response ratio
W= waiting time
S= service time
When current process completes, the scheduler choose the ready process with the highest response ratio
value. The minimum R value is 1, which occurs when a process first enters into the system. HRRN is
suitable for both short job processes and highest waiting time processes.
Process Synchronization
Concurrency:
Concurrency arises in
Shared resources are loaded into a portion of memory global to all applications. The sharing of
main memory among the processes is useful to permit efficient and close interaction among the
processes. Such sharing can lead to problems.
Ex:
Void echo()
{
Chin = getchar();
Chout=chiin;
Putchar(chout);
}
Process P1 Process P2
Echo()
- Echo()
- Chin=getchar();(some input “Y”)
- Chout=chin;
- Putchar(chout) (output is “Y”)
Putchar(chout)(output is “Y”)
This problem can be caused because two processes may be executing simultaneously and both
trying to access the same global variable(resource). The solution for this problem is control
access to the shared resources
Race condition occurs when multiple processes are in race of accessing the shared data items
and the final result depends on the loser of race or order of execution of instructions.
Ex1:
Ex 2:
P3,P4 sharing the global variables b and c with initial values 1 and 2 respectively
Though the two processes updates different values, the final values depends on the order in
which the two processes are execute these tow assignments.
Process Interaction
It is property of concurrence control that prevents the simultaneous access to a shared resource.
We have to allow only one process to access the resource at any instant of time.
Critical Section
It is a area or a region where critical code is placed. Only one program is allowed into critical
section to access the shared resource.
Critical Resource
Which can not be shared.
Deadlock:
It is a situation or condition when two are more processes are each waiting for another to release
a resource. A deadlock will occur when a process enters into a waiting state because it requested
a resource which is hold by another waiting process.
Starvation:
It is a situation where a process waits for very long time for a resource or event to occur.
Mutual Exclusion: At any instance of time only once process is allowed into the critical section
to access shared resource.
Requirements for Mutual Exclusion
1. Only one process is allowed into the critical section
2. If any process is in its noncritical section, it should not be interfering with other processes
3. When critical section is free, if any process requesting to enter into critical section, it
should be allowed immediately.
4. No process should wait indefinite time to enter into critical section.
5. A process should remains inside the critical section only for the finite time.
.
Mutual Exclusion: Hardware approaches
i. Interrupt disabling
In a uniprocessor system, the fundamental reason of concurrency is that the
processor may dispatch different processes to run from time to time.
And the switching of control happens due to some kind of interrupt, such as
timeout interrupt in a time-sharing environment, I/O operation completion
interrupt, etc. Based on this observation, if we could in some way avoid
concurrency while the execution of critical sections is in progress, the mutual
exclusion problem will then be solved naturally. Hence we obtain a hardware-
based solution as below:
while (true)
{
/* disable interrupts */
/* critical section */
/* enable interrupts */
/* remainder */
}
A shared variable bolt is initialized to 0. The only process that may enter its
critical section is one that finds bolt equal to 0. All other processes at enter their
critical section go into a busy waiting mode. When a process
leaves its critical section, it resets bolt to 0; at this point one and only one of the
waiting processes is granted access to its critical section. The choice of process
depends on which process happens to execute the compare&swap instruction
next.
Void P(int i)
{
While(true)
{
While(compare_and_swap(bolt,0,1)==1)
// do nothing
/* Critical section */
Bolt=0;
}
}
Void main()
{
Bolt=0;
Parbegin(p(1),p(2)….p(n));
}
B. Exchange Instruction:
Semaphores
A semaphore, in its most basic form, is a protected integer variable that can facilitate and restrict
access to shared resources in a multi-processing environment.
A semaphore is hardware or a software tag variable whose value indicates the status of a
common resource. Its purpose is to lock the resource being used. A process which needs the
resource will check the semaphore for determining the status of the resource followed by the
decision for proceeding. In multitasking operating systems, the activities are synchronized by
using the semaphore techniques.
Binary semaphores
- Binary semaphores can take only 2 values (0/1). They are used to acquire locks. When a resource is
available, the process in charge set the semaphore to 1 else 0.
- Counting Semaphore may have value to be greater than one, typically used to allocate resources
from a pool of identical resources
Struct semaphore
{
Int count;
queueType queue;
};
Void semWait(semaphore s)
{
s.count--;
if(s.count<0)
{
//place this process in s.queue
//block this process
}
}
Void semSignal(semaphore s)
{
s.count++;
if(s.count<=0)
{
//remove a process from s.queue
//place the process on ready list
}
}
Void Init(semaphore s, int v)
{
s.count=v;
}
Struct binary_semaphore
{
Enum{zero, one} value;
queueType queue;
};
Void semWaitB(binary_semaphore s)
{
If(s.value==one)
s.value=zero
else
{
//place this process in s.queue
//block this process
}
}
Void semSignalB(binary_semaphore s)
{
If(s.queue is empty())
s.value=1;
else
{
//remove a process from s.queue
//place process on ready list
}
Void main()
{
Parbegin (p(1),p(2),…..p(n));
}
It is a concept related to binary semaphore. The key difference between binary semaphore and
mutex is; in mutex, the process that locks(sets value to 0) the mutex must be the one to
unlock(sets the value to 1) it. Where as in binary semaphore, it is possible for one process to lock
and another process the unlock the semaphore value.
A queue is used in every semaphore to hold the waiting processes. When a signal() operation is
performed, a blocked/waiting process which is waiting in the queue removed based FIFO policy.
The semaphore whose definition includes this kind of policy is called as strong semaphore.
Semaphores that does not specify the order in which the processes are removed from the queue is
a weak semaphore.
Producer and Consumer Problem
The problem describes two processes, the producer and the consumer, who share a
common, buffer used as a queue. The producer's job is to generate data, put it into the buffer, and
start again. At the same time, the consumer is consuming the data (i.e., removing it from the
buffer), one piece at a time. The problem is to make sure that the producer won't try to add data
into the buffer if it's full and that the consumer won't try to remove data from an empty buffer.
Producer Consumer
Buffer
1. If there is no space to add items(i.e Buffer is full) then producer will blocked
2. If there is a space to add item, producer is unblocked
3. If there is no item in buffer, consumer blocked
4. If there is a item, consumer unblocked.
1. Infinite Buffer
In this, the buffer size is not fixed. Following are the definitions of producer and
consumer
Producer:
while(true)
{
//produce item v
buffer[in]=v
in++
}
Consumer:
while(true)
{
while(in<=out)
//do nothing
w=buffer[out];
out++;
//consume item w
}
N=0 S=1
1 0 producer
1
_________________________________
0 0 consumer
1
__________________________________
1 0 producer
1
__________________________________
2 0 producer
1
___________________________________
1 0 consumer
1
___________________________________
0 0 consumer
1
___________________________________
2. Bounded Buffer:
Here the buffer size is fixed. The buffer treated as circular storage.
Producer:
while(true)
{
//produce an item v
while((in+1)%e==out)
//do nothing
b[in]=v;
in =(in+1)%e;
}
Consumer:
while(true)
{
while(in==out)
//do nothing
w=b[out];
out=(out+1)%e;
//consume item w;
}
Solution to the bounded buffer producer and consumer problem using semaphore
semaphore s=1,n=0,e=buffersize;
void producer()
{
while(true)
{
producer();
semwait(e);
semwait(s);
append();
semsignal(s);
semsignal(n);
}
}
void consumer()
{
while(true)
{
semwait(n);
semwait(s);
take();
semsignal(s);
semsignal(e);
consume();
}
}
void main()
{
parbegin(producer, consumer);
}
Monitors
Characteristics of Monitors
1. The local data variables are accessible only by the monitor’s procedures and
not by any external procedure
2. A process enters the monitor by invoking one of its procedures.
3. Only one process may be executing in the monitor at a time; any other processes
that have invoked the monitor are blocked, waiting for the monitor to become
available.
Structure of Monitor
Monitor boundedbuffer;
Char buffer[n];
Int nextin=0,nextout=0,count=0;
Cond notFull, notEmpty;
Void append(char x)
{
If(count==n)
Cwait(notFull)
Buffer[nextin]=x;
Count++;
Csignal(nonempty);
}
Void take(char x)
{
If(count==0)
Cwait(notEmpty);
X=buffer[nextout];
Count--;
Csignal(notfull);
}
Void producer()
{
Char x;
While(true)
{
Produce(x);
Append(x);
}
}
Void consumer()
{
Char x;
While(true)
{
Take(x)/remove(x);
Consume(x);
}
}
Void main()
{
Parbegin(producer, consumer);
}
A producer can add characters to the buffer only by using the procedure append inside the monitor; the
producer does not have direct access to buffer. The procedure first checks the condition notfull to
determine if there is space available in the buffer. If not, the process executing the monitor is blocked on
that condition.
Similarly, a consumer can take a character from the buffer using the procedure . Consumer first checks
the condition notempty to determine if there is a character available in the buffer. If not, the process is
blocked on that condition.
Message Passing
Both send and receive primitives have blocking and nonblocking states. There three main combinations
are there on these states.
1. Blocking send, blocking receive: Here, both sender and receiver are blocked until the message is
delivered. This combination allows tight synchronization between processes.
2. Nonblocking send, blocking receive: Here, the receiver is blocked until the message is
delivered, the sender may continue its execution after send performing send primitive. It allows a
process to send one or more messages to a variety of destinations.
3. Nonblocking send, nonblocking receive: Here, neither sender or receiver is required to wait.
Addressing
Addressing refers to specifying the destination and sources addresses in the send and receive primitives.
There are two types of addressing, direct and indirect addressing.
Direct Addressing:
In this the processes must know addresses of source and destination ahead. Sender must specify the
destination address in the send primitive, the receiver must specify the source address in the receive
primitive.
Indirect Addressing:
In this, messages are not sent directly from sender to receiver but rather they are sent to a mailbox. A
mailbox is a shared data structure which can hold messages. When two processes communicate, one
process sends a message to the appropriate mailbox and the other process pricks up the message from the
same mail box.
The relationship between the sender and receiver can be one-to-one, many-to-one,one-to-many or many-
to-many.
Many-to-one relationship: it is useful for client server interaction; one process provides service to a
number of other processes. In this case, mailbox is often referred as a port.
One-to-many relationship: it allows for on sender and multiple receivers; it is useful for applications
where a message or some information is to be broadcast to set of processes.
Many-to-many relationship: it allows multiple server processes to provide concurrent service to multiple
clients.
Mailboxes Types:
Static mailbox: It is defined only for one send and one receiver.
Dynamic mailbox: Here, there are many senders and many receivers.
Ownership of the mailbox:
Message Format:
It is divided into two parts: a header and a body. Header contains information about the message like
message type, destination id and source id. It may also contain some control information. Body contains
the actual contents of the message.
Queuing Discipline:
It specifies the order in which the messages have to deliver. It follows FIFO manner, but it may not be
sufficient if some messages are more urgent than others. In this case, we may specify the message
priority. Priority may be given based on message type or destination by the sender.
In this, there will be one mailbox “box”, which can be used by all processes to send and receive messages.
The mailbox is initialized with null message. If any process wants enter critical section first attempts to
receive a message. If the mail box is empty then the process is blocked. Once a process has acquired the
message, it performs its critical section and then places the message back to the mailbox.
Here, there are two mailboxes produce and consume. When a producer generates data, it is sent as
messages to the mailbox consume. As long as there is at least one message in that mail box, the consumer
can consume. consume mailbox serves as a buffer. The size of the buffer is determined by the global
variable capacity. The mailbox produce is filled with number of null messages equal to the capacity of the
buffer. The number of messages in produce decreases with each production and increases with each
consumption.
Readers/Writers Problem:
int readcount = 0;
semaphore wsem = 1; //
semaphore x = 1; //
void main(){
int p = fork();
if(p) reader; // assume multiple instances
else writer; // assume multiple instances
}
void reader(){
while(1){
wait(x);
readcount++;
if (readcount==1)
wait(wsem);
signal(x);
doReading();
wait(x);
readcount--;
if (readcount==0)
signal(wsem);
signal(x);
}
}
void writer(){
while(1){
wait(wsem)
doWriting();
signal(wsem)
}
}
void reader(){
while(1){
wait(z);
wait(rsem);
wait(x);
readcount++;
if (readcount==1)
wait(wsem);
signal(x);
signal(rsem);
signal(z);
doReading();
wait(x);
readcount--;
if (readcount==0)
signal(wsem);
signal(x);
}
}
void writer(){
while(1){
wait(y);
writecount++;
if (writecount==1)
wait(rsem);
signal(y);
wait(wsem);
doWriting();
signal(wsem);
wait(y);
writecount--;
if (writecount==0)
signal(rsem);
signal(y);
}
}
An alternative solution, which gives writers priority and which is implemented using message passing. In
this case, there is a controller process that has access to the shared data area. Other processes wishing to
access the data area send a request message to the controller, are granted access with an “OK” reply
message, and indicate completion of access with a “finished” message. The controller is equipped with
three mailboxes, one for each type of message that it may receive.
The controller process services write request messages before read request messages to give writers
priority. In addition, mutual exclusion must be enforced.
To do this the variable count is used, which is initialized to some number greater than the maximum
possible number of readers. In this example, we use a value of 100.The action of the controller can be
summarized as follows:
• If count _ 0, then no writer is waiting and there may or may not be readers active. Service all “finished”
messages first to clear active readers. Then service write requests and then read requests.
• If count _ 0, then the only request outstanding is a write request. Allow the writer to proceed and wait
for a “finished” message.
• If count _ 0, then a writer has made a request and is being made to wait to clear all active readers.
Therefore, only “finished” messages should be serviced.
DeadLock:
Deadlock is a situation which occurs when a waiting process requests a resource, which is held by another
waiting process. If deadlock occurs, a set of processes may permanently blocked.
1. Mutual Exclusion: At least one resource must be held in a non-sharable mode; that is, only one
process at a time can use the resource. If another process requests that resource, the requesting
process must be delayed until the resource has been released.
2. Hold and Wait: A process must be holding at least one resource and waiting to acquire additional
resources that are currently being held by other processes.
3. No Preemption: Resources cannot be preempted; that is, a resource can be released only voluntarily
by the process holding it, after that process has completed its task.
4. Circular Wait: A set {P0, P1, ..., Pn) of waiting processes must exist such that Po is waiting for a
resource that is held by PI, PI is waiting for a resource that is held by P2, ..., Pn-1 is waiting for a
resource that is held by Pn and Pn is waiting for a resource that is held by P0.
Resources:
There are two types of resources, usable resources and consumable resources.
Usable resources:
Usable resource is one that can be used by one process at a time. These can not be created or destroyed. These
are fixed in size. A resource can be reused when it released by the process.
Ex: memory, secondary memory, files, data structures.
Ex: Two processes P and Q are trying to access the resources R1 and R2. Following are the sequence
operation instructions performed by P and Q process.
P0: Request (R1) Q0: Request (R2)
P1: Lock(R1) Q0: Lock(R2)
P2: Request (R2) Q2: Request (R1)
P3: Lock(R2) Q3: Lock(R1)
P4: Perform operatons Q4: Perform operatons
P5: Unlock(R1) Q5: Unlock(R2)
P6: Unlock(R2) Q6: Unlock(R1)
Deadlock will occur if the instructions are executed in the following order
P0,P1,Q0,Q1,P2,Q2
Consumable Resources
Consumable resource is one that can be created and destroyed. There is no limit on the number of consumable
resources. Ex. Interrupts, signals, messages.
A pair of processes P1 and P2, each process attempts to receive a message from another process and then send
message to the other process.
P1 P2
-- --
receive(P2) receive(P1)
-- --
send(P2,M1) send(P1,M2)
Deadlock will occur if the receiving process is blocked until the message is received.
A resource allocation graph is directed graph, which specifies which resource is held by which process and
which process requests what resource.
A directed edge (Request Edge) from a process to resource represents, process is requesting for the resource.
A directed edge (Assignment Edge) from a resource to process represents, resource is allotted to the process.
A dot in the resource represents an instance.
Deadlock Preemption
We can preempt occurrence of a deadlock by ensuring that at least one of the deadlock occurrence conditions
can not hold.
Mutual Exclusion: Sharable resources do not require mutual exclusive access and does not involved in
deadlocks. Only non sharable resources require mutual exclusive access. Deadlocks can be preempted by
denying the mutual exclusive condition.
Hold and Wait: To ensure hold and wait condition never occurs in the system, we must guarantee that
whenever a process requests for a resource, it does not hold any resource. All requested resources must allocate
to process before it begins execution. It has two disadvantages; one is low resource utilization and starvation.
No Preemption: If a process that is holding some resources and requesting another resource that can not be
immediately granted until currently allocated resources are preempted. The preempted resources are added to
the list of resources for which the process is waiting. Process will be restarted only when it regain its all
resources (old and new).
Circular Wait: One way to ensure that this condition never holds is to impose a total ordering of all resource
types, and to require that each process requests resources in an increasing order of enumeration.
Deadlock Avoidance:
The deadlock avoidance algorithm dynamically examines the resource allocation state to ensure that
there can never be a circular wait condition. The resource-allocation state is defined by the number of available
and allocated resources, and the maximum demands of the processes.
If process Pi requested resources are not immediately available, then Pi can wait until all Pj have finished.
When Pj is finished, Pi can obtain requested resources, execute, return allocated resources, and terminate.
When Pi terminates, Pi+1 can obtain its needed resources, and so on….
A safe state is not a deadlock state. Conversely, a deadlock state is an unsafe state. Not all unsafe states are
deadlocks. An unsafe state may lead to a deadlock. As long as the state is safe, the operating system can avoid
deadlock.
When process Pi requests resource Rj, the claim edge PiRj is converted to a request edge. Similarly,
when a resource Rj is released by Pi,th e assignment edge RjPi is reconverted to a claim edge PiRj.
If no cycle exists, then the allocation of the resource will leave the system in a safe state. If a cycle is found,
then the allocation will put the system in an unsafe state.
The resource-allocation graph algorithm is not applicable to a resource allocation system with multiple
instances of each resource type. In this case banker’s algorithm will be used.
When a new process enters the system, it must declare the maximum number of instances of each resource
type that it may need.
This number may not exceed the total number of resources in the system.
When a user requests a set of resources, the system must determine whether the allocation of these resources
will leave the system in a safe state. If it will, the resources are allocated; otherwise, the process must wait until
some other process releases enough resources.
Available: A vector of length m indicates the number of available resources of each type. If Available[j] = k,
there are k instances of resource type Rj available.
Max: A nXm matrix defines the maximum demand of each process. If Max[i,j] = k, then process Pi may
request at most k instances of resource type Ri.
Allocation: An nXm matrix defines the number of resources of each type currently allocated to each process.
If Allocation[i,j] = k, then process Pi is currently allocated k instances of resource type Rj.
Need: An n x m matrix indicates the remaining resource need of each process. If Need[i,j] = k, then process
Pi may need k more instances of resource type Ri to complete its task.
Note that Need[i,j] = Max[i,j ] - Allocafion[i,j].
Safety Algorithm
a. Finish[i] =false
b. Needi <=Work.
Let Requesti be the request vector for process Pi. If Requesti[j] = k, then process Pi wants k instances of
resource type Rj. When a request for resources is made by process Pi, the following actions are taken
1. If Requesti <=Needi, go to step 2. Otherwise, raise an error condition, since the process has exceeded
its maximum claim.
2. If Requesti <=Available, go to step 3. Otherwise, Pi must wait, since the resources are not available.
3. Have the system pretend to have allocated the requested resources to process Pi by modifying the
state as follows
If the resulting resource-allocation state is safe, the transaction is completed and process Pi is allocated its
resources. However, if the new state is unsafe, then Pi must wait for Requesti and the old resource-allocation
state is restored.
Deadlock Detection
If a system does not include deadlock preemption or deadlock avoidance algorithm, then a deadlock situation
may occur. At the stage, the system must provide two algorithms; one is to examine the state of the system
whether a deadlock has occurred, second is to recover from the deadlock
If all resources have only a single instance, then we can define a deadlock detection algorithm using wait-for
graph. We obtain wait-for graph from the resource-allocation graph by removing the resource nodes and their
respective edges.
An edge from Pi to Pj in a wait-for graph implies that process Pi is waiting for process Pj to release a resource
that Pi needs. An edge Pi to Pj exists in a wait-for graph if and only if the corresponding resource allocation
graph contains two edges Pi to Rq and Rq to Pj for some resource Rq
If there is a cycle in the wait-for graph then deadlock occurs. To detect deadlock the system needs to maintain
the wait-for graph and periodically invoke an algorithm that searches for a cycle in the graph. This algorithm
needs O(n2) operations, where n is number of vertices in the graph.
Several Instances of a Resource Type
The wait-for graph technique is not applicable to resource allocation system with multiple instances of each
resource type. This deadlock detection algorithm includes three data structures.
Available: A vector of length m indicates the number of available resources of each type.
Allocation: An n x m matrix defines the number of resources of each type currently allocated to each process.
Request: An n x m matrix indicates the current request of each process. If Request[i,j] = k, then process Pi is
requesting k more instances of resource type Ri.
There are two ways to recover from the deadlock state. One is to simply terminate one or more processes to
break the circular wait. Second is to preempt some resources from one or more deadlocked processes.
Process Termination
1. Terminate all deadlocked processes: This method will break the deadlock cycle by terminating all
deadlocked processes. The partial results of these processes must be discarded.
2. Terminate one process at a time until the deadlock cycle is eliminated: In this method, processes
will be terminated one at a time, to eliminate the deadlock. When each process terminated, the
deadlock detection algorithm must be invoked to determine whether any processes are still
deadlocked.
Resource preemption
We can eliminate deadlocks by using resource preemption method. In this we preempt some resources from
process and give these resources to other processes until deadlock cycle is broken.
There are three issues while dealing deadlock with resource preemption method
1. Selecting a victim: Which resources are to be preempted in order to break the cycle. We must
determine the order of preemption to minimize the cost.
2. Rollback: If we preempt a resource from a process, it can not continue with its normal execution
because it is missing some needed resources. We must restart the process in safe state, but it is
difficult to determine a safe state, so the process must rollback.
3. Starvation: while selecting a victim, there is a possibility of same process is always picked as victim.
This results that the process never completes it task, this leads to a starvation.
Memory Management
Memory management is a task of dividing the main memory dynamically to accommodate multiple processes.
This task is performed by operating system. The primary operation of memory management is to bring the
process into the memory for execution.
1. Relocation
2. Protection
3. Sharing
4. Logical organization
5. Physical organization
Relocation:
In multiprogramming, the main memory is shared among the number of processes. We have to swap some
active processes in and out of main memory to maximize the processor utilization. Once a process is swapped
out to disk, it must be swapped back in to same memory region as before. But sometimes we may need to
relocate the process to a different memory area. OS is responsible for bringing the processes into main
memory.
Protection:
Each process should be protected against the unwanted interference by other processes. Programs in one
process should not be able to access reference memory location of another process for reading or writing
purpose without permission. Relocation requirement increases the difficulty of satisfying protection
requirement. Protection requirement must be satisfied by the processor rather than the operating system.
Sharing:
The memory management system must provide a control access to the shared areas of memory without
compromising essential protection. The protection mechanism must have the flexibility to allow several
processes to access the same portion of main memory. For example, if a number of processes are executing the
same program, it is advantageous to allow each process to access the same copy of the program rather than
having its own separate copy.
Logical Organization:
The main memory is organized as a linear or one-dimensional manner. Secondary memory is also similarly
organized. Most programs are organized into modules, some of them are modifiable and some are
unmodifiable. Following are the advantages of using modules
a. Modules can be written and compiled independently.
b. Different degrees of protection can be given to different modules
c. We can share the some desirable modules among the processes.
Physical organization:
Physical organization refers to how data and programs are stored in memories and how the flow of information
between main and secondary memory happening.
The computer memory is organized into two levels, main memory and secondary memory. Main memory
provides fast access at high cost. It is a volatile and it does not provide permanent storage. It can store
programs and data that currently in use. Secondary memory is slower and cheaper than main memory and it is
non volatile memory. It can store programs and data permanently.
Memory Partitioning
There are two different techniques are used for main memory partitioning.
1. Fixed partitioning
2. Dynamic partitioning
1. Fixed Partitioning
In fixed partitioning, the available main memory is divided into regions with fixed boundaries. It is two types
a. Equal size fixed partitioning
b. Unequal size fixed partitioning
Placement algorithm
It is very easy is to place a process in main memory using equal size partition. As long as there is an available
partition, a process can loaded into that partition. Because all partitions are with equal size, it does not matter
which partition is used. If all partitions are occupied with processes then one those processes must be swapped
out to make a free space for new process.
With the unequal size partitions, there are two possible methods to place a process in memory. One method is
to assign each process to the smallest partition where it will fit. In this case a scheduling queue is needed for
each partition to hold swapped out processes.
Second method is, maintain a single queue for all processes. When it is time to load a process into main
memory, then choose a partition which can accommodate the process. If all partitions are occupied then
swapping must made.
2. Dynamic partitioning
In dynamic partitioning, the partitions are of variable length and number. When a process brought into the
main memory, it is allocated exactly as much memory as it required.
Assume the main memory size is 64MB. Initially it is loaded with OS. Three different processes are
loaded in, and occupy enough space for each process. This leaves a small “hole”( hole is small memory
block that is not sufficient to accommodate a process) at the end of the memory. At some time a new
process process4 with size 8MB has arrived. The OS swaps out the process2, which leaves sufficient space
to load the new process. Because the process4 is smaller than the process2, another small hole is created.
When the process2 swapped back into the main memory, if there is no sufficient memory for process2; the
OS swaps out the process1. This procedure leads to a situation in which there are a lot of small holes in
memory. This is referred as external fragmentation.
One technique that overcomes the external fragmentation is compaction. In this, the free memory (holes) are
combined to form single block of memory that may accommodate a new process. Compaction is a time
consuming procedure and it needs a dynamic relocation capability.
Placement algorithms
When a process loaded into main memory, if there are more than one free block memory of sufficient size are
available, then the OS must decide which free block is to allocate.
There are three placement algorithms that may used to place the processes in memory.
a. Best-fit
b. First-fit
c. Next-fit
Best –fit chooses the block that is closest in size to process request. First-fit begins to scan memory from the
beginning and chooses the first available block that is large enough to accommodate the process. Next-fit
begins scan from the location of the last placement, and choose the next available block that is large enough to
accommodate the process.
Swapping:
Swapping is a mechanism in which a process can be swapped temporarily out of main memory (or
move) to secondary storage (disk) and make that memory available to other processes. At some later time, the
system swaps back the process from the secondary storage to main memory.
The total time taken by swapping process includes the time it takes to move the entire process to a
secondary disk and then to copy the process back to memory, as well as the time the process takes to regain
main memory.
Paging
Paging is a memory management scheme that permits the physical address of a process/program to be non-
contiguous. In paging, the process/program is divided into blocks; each block is loaded into non contiguous
blocks of the main memory. Paging avoids fragmentation problems. Following diagram illustrates paging
model.
Page0 Frame0
P F
A Page1 Frame1
G R
Page2 Frame2
E
A
S Page3 Frame3
Page4 M
Frame4
Frame5 E
Program/Process Page0 F5
Page1 F7
Page2 F0
Page3 F6
Page4 F1
Physical memory is broken into fixed sized blocks called as frames. Logical memory is also broken
into same sized blocks called as pages. When a process is to be executed, its pages are loaded into any
available memory frames. Page table specifies which page is loaded in which frame.
An address generated by the CPU is commonly referred to as a logical address, whereas an address
seen by the memory unit-that is, the one loaded into the memory-address register of the memory-is commonly
referred to as a physical address.
Every logical address is divided into two parts; a page number (p) and page offset (d). page number is used as
an index in page table to represent the frame number. This frame number and offset defines the physical
address of the page in the main memory.
The size of the page and number of pages are represented in power of 2. Similarly size of frame and number
frames is represented in power of 2. Look at the following example
In the above example,
The size of the page 4 bytes, we can represent 4 as 2 2 . So 2 bits are sufficient to represent 4 in binary format.
Total number of pages is 4, we can represent 4 as 22 . here also 2 bits are sufficient to represent 4 in binary
format.
Total number of bits required to represent a logical address is 4bits
The size of the frame is 4, so it needs 2 bits to represent in binary format
Total number of frames is 8, so it needs 3 bits to represent in binary format
Total number of bits required to represent a physical address is 5bits
Now see how a logical address is mapped into physical address space. Lets consider first byte in 2 nd page (i.e.
1000 logical address). In “1000”, the first two bits represent the page number and next two bits represent offset
(represent which byte).
The TLB is associative, high speed memory. The TLB is used in the page tables. Each entry in TLB consists of
two parts a key and a value. TLB contains only a few of the page table entries. When a logical address is
generated by the CPU, its page number is presented to the TLB. If the page number is found( it is also known
as TLB hit), its frame number is immediately available and is used to access memory.
If the page number is not in the TLB (known as a TLB miss), a memory reference to the page table must be
made. When the frame number is obtained, we can use it to access memory.
The percentage of times that a particular page number is found in the TLB is called the hit ratio.
1. Hierarchical paging
2. Hashed page tables
3. Inverted page tables
Hierarchical paging:
If there is a large logical address space then it is difficult maintain all entries in a single page table. Suppose if
there is a 32bit logical address space and if the page size is 4KB then the page table may consists of one
million entries. In this case, we can use hierarchical paging technique.
Assume it is 32bit system; the logical address consists of 32 bits. A logical address is divided into 20bit page
number and 12 bit offset. As it is hierarchical paging, the page number further divided into 10bit page number
and 10 bit offset
P1 is an index in the outer page table and p2 is an index in the inner page table.
The address translation works from the outer page table to inner page table, so it is known as forward mapped
page table.
The page number in the logical address is hashed into the hash table. The page number is compared with the
virtual page number of the first element in the linked list. If there is a match the corresponding frame number is
used to form the physical address. If there is no match, match with next entries in the list.
In inverted page table, each entry consists virtual address of the page and information about the process of the
page. The logical contains pid, page number and offset. Inverted page tables uses address space identifier(i).
This ensures the mapping of a logical page for a particular process to the corresponding physical page frame.
Segmentation
In paging, user’s view of logical memory is different from physical memory. There is a separation of user’s
view of logical memory and the actual physical memory. But segmentation supports user’s view of memory.
The logical address space is a collection of segments. Each segment has a number and length. Each segment is
of different sizes. Each logical address consists of two fields, segment number and offset with in the segment.
<segment-number,offset>
Address Translation:
1. Fetch the base address of the segment in the segmentation table by using segment number
2. Compare the offset value with the segment length, where 0<=offset<length
3. Add the offsest to the base address to get the physical address
Example:
Assume the logical address is <1,2>, so segment number is 1 and offset value 2
Demand paging:
Demand paging is a technique in which pages are brought into the main memory on demand
of the process. Demand paging is combination of both paging and swapping. When a process is ready for the
execution, instead of moving all its pages into main memory, only few pages which are necessary for the
execution are brought into the main memory to execute the process. It is difficult to implement demand paging.
Demand paging is used to implement virtual memory. Virtual memory is a space in the disk, which acts as a
main memory temporarily.
In demand paging, we use a pager. When a process swapped in for execution, instead of
swapping in a whole process, the pager brings only those necessary pages into main memory.
When CPU is trying to access a page from main memory, if that page was not found then it is known as page
fault. The missing page will bring from the backing store to continue the process execution.
Page replacement algorithm is a technique, which decides which page has to replace with new page. There
are three different page replacement algorithms
It is the simplest page replacement algorithm. In FIFO replacement algorithm, each page is associated with a
time value that indicates when that page was brought into the main memory. In FIFO algorithm, the oldest
page is replaced with a new page.
Example:
Number of frames: 3
If we increase the number of frames then number of page fault will decrease.
Reference string 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
7 7 7 7 7 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2
frames 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 4 7 7 7
1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1
y y y y n y n y n n y n n y y n n y n n
Page fault
Number of page faults is 10
Belady’s Anomaly : In some replacement algorithms, the page fault rate may increase as the number of
frames increases.
Number of frames 3
Reference String 1 2 3 4 1 2 5 1 2 3 4 5
1 1 1 4 4 4 5 5 5 5 5 5
Frames 2 2 2 1 1 1 1 1 3 3 3
3 3 3 2 2 2 2 2 4 4
Page fault y y y y y y y n n y y n
Reference string
1 2 3 4 1 2 5 1 2 3 4 5
Frames 1 1 1 1 1 1 5 5 5 5 4 4
2 2 2 2 2 2 1 1 1 1 5
3 3 3 3 3 3 2 2 2 2
4 4 4 4 4 4 3 3 3
Page fault y y y y n n y y y y y y
Optimal page replacement algorithm has the lowest page fault rate of all algorithms and it is never suffers from
belady's anomaly. In optimal page replacement, page that will not be used for the longest period of time is
replaced with new page. It guarantees the lowest page fault rate for the fixed number of frames. It is difficult to
implement optimal page replacement algorithm because user has to know future data in advance.
Example:
Number of frames: 4
Reference string 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
7 7 7 7 7 3 3 3 3 3 3 3 3 1 1 1 1 1 1 1
frames 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 4 4 4 4 4 4 4 4 4 4 7 7 7
Page fault 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
y y y y n y n y n n n n n y n n n y n n
Page fault rate is 8
In LRU algorithm, each page is associated with a time value that represents page’s last use. In LRU, the page
that has not been used for the longest period of time is replaced with a new page. In LRU, the strategy is
looking backward to find a victim page.
Example 1
Number of frames 3
Page fault rate is 12
Example 2
Number of frames 4
Reference string
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
Frames 7 7 7 7 7 3 3 3 3 3 3 3 3 3 3 3 3 7 7 7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 4 4 4 4 4 4 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Page fault y y y y n y n y n n n n n y n n n y n n
I/O Management:
Users/programmers can interact with computer by providing information through IO devices. Management of
these devices may affect the throughput o the system. Devices communicate with computer through bit or byte
streams using a data bus or device controller. Following are some situations where IO devices are required.
a. User may give input to computer and get output from the computer
b. Device may give input to computer and get output from the computer
c. Computers to communicate over networks
The I/O function includes a control and timing requirement to co-ordinate the flow of traffic between internal
resources and external devices. For example, the control of the transfer of data from an external device to the
processor might involve the following sequence of steps
a. The processor interacts with the I/O module to check the status of the attached device.
b. The I/O module returns the device status.
c. If the device is operational and ready to transmit, the processor requests the transfer of data, by means of a
command to the I/O module.
d. The I/O module obtains a unit of data from external device.
e. The data are transferred from the I/O module to the processor.
During IO operation, the IO module must communicate with the processor and with the external device.
Processor communication involves the following
Command decoding:
The I/O module accepts command from the processor, typically sent as signals on control bus.
Data:
Data are exchanged between the processor and the I/O module over the data bus.
Status Reporting:
Because peripherals are so slow, it is important to know the status of the I/O module. For example, if
an I/O module is asked to send data to the processor(read), it may not be ready to do so because it is still
working on the previous I/O command. This fact can be reported with a status signal. Common status signals
are BUSY and READY.
Address Recognition:
Just as each word of memory has an address, so thus each of the I/O devices. Thus an I/O module
must recognize one unique address for each peripheral it controls.
Error Detection:
Another task of I/O module is error detection and for subsequently reporting error to the processor.
Block diagram of IO Module
Programmed I/O
In programmed I/O, the data transfer between CPU and I/O device is carried out with the help of a
software routine. When a processor is executing a program and encounters an instruction relating to I/O, it
executes that I/O instruction by issuing a command to the appropriate I/O module.
The I/O module will perform the requested action and then set the appropriate bits in the I/O status
register. The I/O module takes no further action to alert the processor. It is the responsibility of the processor to
check periodically the status of the I/O module until it finds that the operation is complete. In programmed I/O,
when the processor issues a command to a I/O module, it must wait until the I/O operation is complete.
Generally, the I/O devices are slower than the processor, so in this scheme CPU time is wasted. CPU
is checking the status of the I/O module periodically without doing any other work.
To execute an I/O-related instruction, the processor issues an address, specifying the particular I/O
module and external device, and an I/O command. There are four types of I/O commands that an I/O module
will receive when it is addressed by a processor
Control: Used to activate a peripheral device and instruct it what to do. For example, a magnetic tape unit may
be instructed to rewind or to move forward one record. These commands are specific to a particular type of
peripheral device.
Test: Used to test various status conditions associated with an I/O module and its peripherals. The processor
will want to know if the most recent I/O operation is completed or any error has occurred.
Read: Causes the I/O module to obtain an item of data from the peripheral and place it in the internal buffer.
Write: Causes the I/O module to take an item of data ( byte or word ) from the data bus and subsequently
transmit the data item to the peripheral.
Interrupt Driven IO
The problem with programmed I/O is that the processor has to wait a long time for the I/O module of
concern to be ready for either reception or transmission of data. The processor, while waiting, must repeatedly
interrogate the status of the I/O module.
The solution to this problem is to provide an interrupt mechanism. In this approach the processor
issues an I/O command to a module and then go on to do some other useful work. The I/O module then
interrupts the processor to request service when it is ready to exchange data with the processor. The processor
then executes the data transfer. Once the data transfer is over, the processor then resumes its former
processing.
The occurrence of an interrupt triggers a number of events, both in the processor hardware and in software.
When an I/O device completes an I/O operation, the following sequences of hardware events occurs:
Programmed I/O and Interrupt Driven I/O methods require the active intervention of the processor to
transfer data between memory and the I/O module, and any data transfer must transverse a path through the
processor. Thus both these forms of I/O suffer from two inherent drawbacks.
1. The I/O transfer rate is limited by the speed with which the processor can test and service a device.
2. The processor is tied up in managing an I/O transfer; a number of instructions must be executed for
each I/O transfer.
DMA: It is an approach that transfers large block of data at high speed between external devices and memory
directly with out continuous intervention by the processor.
DMA transfers are performed by a control circuit associated with the I/O device and this circuit is referred as
DMA controller. The DMA controller allows direct data transfer between the device and the main memory
without involving the processor. To transfer data between memory and I/O devices, DMA controller takes over
the control of the system from the processor and transfer of data take place over the system bus. For this
purpose, the DMA controller must use the bus only when the processor does not need it, or it must force the
processor to suspend operation temporarily.
Cycle Stealing: it is a method used by the DMA control over the system bus to transfer data between external
devices and memory. After data transfer completion it returns control back to CPU.
The processor then continues with other works. It has delegated this I/O operation to the DMA module.
The DMA module checks the status of the I/O devise whose address is communicated to DMA controller by
the processor. If the specified I/O devise is ready for data transfer, then DMA module generates the DMA
request to the processor. Then the processor indicates the release of the system bus through DMA
acknowledge. When the transfer is completed, the DMA module sends an interrupt signal to the processor.
After receiving the interrupt signal, processor takes over the system bus. Thus the processor is involved only at
the beginning and end of the transfer.
The DMA mechanism can be configured in following three ways
In this, all modules share the same system bus. The DMA module here acts as an alternative
processor. This method uses programmed I/O to exchange data between memory and an I/O module through
the DMA module. For each transfer it uses the bus twice. The first one is when transferring the data between
I/O and DMA and the second one is when transferring the data between DMA and memory. Since the bus is
used twice while transferring data, so the bus will be suspended twice. The transfer consumes two bus cycles.
Number of required bus cycles can be reduced in this method. DMA module and one or more I/O modules are
integrated together in such a way that the system bus is not involved. The DMA module, processor and the
memory module are connected through the system bus. In this configuration each transfer will use the system
bus only once and so the processor is suspended only once. The system bus is not involved when transferring
data between DMA and I/O device, so processor is not suspended.Processor is suspended when data is
transferred between DMA and memory.
Using separate I/O Bus:
In this configuration the I/O modules are connected to the DMA through another I/O bus. In this case
the DMA module is reduced to one. Transfer of data between I/O module and DMA module is carried out
through this I/O bus. In this transfer, system bus is not in use and so it is not needed to suspend the processor.
There is another transfer phase between DMA module and memory. In this time system bus is needed for
transfer and processor will be suspended for one bus cycle.
Disk Organization
A disk is a circular platter constructed of metal or of plastic coated with a magnetizable material.
Data is recorded on and later retrieved from the disk via a conducting coil named the head. During a read or
write operation, the head is stationary while the platter rotates beneath it.
The write mechanism is based on the fact that electricity flowing through a coil produces a magnetic
field. Pulses are sent to the head, and magnetic patterns are recorded on the surface below.
The read mechanism is based on the fact that a magnetic field moving relative to a coil produces on
electric current in the coil. When the surface of the disk passes under the head, it generates a current of the
same polarity as the one already recorded.
The data on the disk are organized in a concentric set of rings, called track. Each track has the same
width as the head. Adjacent tracks are separated by gaps. This prevents error due to misalignment of the head
or interference of magnetic fields.
Same number of bits is stored in each track, so inner most track has more density than the outermost
track. Data are transferred to and from the disk in blocks. Usually, the block is smaller than the capacity of the
track. Accordingly, data are stored in block-size regions known as sector.
Physical characteristics of Disk
1. The head may be either fixed or movable with respect to the radial direction of the platter.
2. In a fixed-head disk, there is one read-write head per track. All of the heads are mounted on a rigid
arm that extends across all tracks.
3. In a movable-head disk, there is only one read-write head. Again the head is mounted on an arm.
Because the head must be able to be positioned above any track, the arm can be extended for this
purpose.
4. The disk itself is mounted in a disk drive, which consists of the arm.
5. A disk can be a removable or non removable. A non removable disk is permanently mounted on the
disk drive. A removable disk can be removed and replaced with another disk.
6. For most disks, the magnetizable coating is applied to both sides of the platters, which is then referred
to as double sided disk. If the magnetizable coating is applied to one side only, then it is termed as
single sided disk.
Some disk drives accommodate multiple platters stacked vertically above one another. Multiple arms are
provided for read write head.
Suppose that the disk system has 8 data recording surfaces with 4096 track per surface. Tracks are
divided into 256 sectors. Then the format of disk address word is:
Suppose each sector of a track contains 512 bytes of disk recorded serially, then the total capacity of
the disk is:
When a disk drive is operating, the disk is rotating at constant speed. To read or write, the head must be
positioned at the desired tack and at the beginning of the desired sector on the track. Track selection involves
moving the head.
Seek Time:
Seek time is the time required to move the read/write head to the proper track.
Transfer Time:
The transfer time to or from the disk depends on the rotational speed of the disk and it is estimated as
The disk access time is sum of seek time and rotational delay. The disk access time is relatively higher
than the time required to access data from main memory and performs CPU operation. Also the disk drive
contains some mechanical parts and it involves mechanical movement, so the failure rate is also high.
A disk array is an arrangement of several disk, organized to increase performance and improve
reliability of the resulting storage system. Performance is increased through data striping. Reliability is
improved through redundancy.
Disk arrays that implement a combination of data striping and redundancy are called Redundant
Arrays of Independent Disks (RAID).
Data stripping:
In data striping, the data is segmented in equal-size partitions distributed over multiple disks. The size of the
partition is called the striping unit. The partitions are usually distributed using a round-robin algorithm. If the
disk array consists of D disks, then partition i is written in to disk ( i mod D ).
Redundancy:
Having more disks increases storage system performance, it also lowers overall storage system reliability,
because the probability of failure of a disk in disk array is increasing. Reliability of a disk array can be
increased by storing redundant information. If a disk fails, the redundant information is used to reconstruct the
data on the failed disk.
Disk scheduling is is done by operating systems to schedule I/O requests arriving for disk. Disk scheduling is
also known as I/O scheduling.
Disk scheduling is important because:
Multiple I/O requests may arrive by different processes and only one I/O request can be served at a
time by disk controller. Thus other I/O requests need to wait in waiting queue and need to be
scheduled.
Two or more request may be far from each other so can result in greater disk arm movement.
Hard drives are one of the slowest parts of computer system and thus need to be accessed in an
efficient manner.
1. FCFS:
FCFS is the simplest of all the Disk Scheduling Algorithms. In FCFS, the requests are addressed in the
order they arrive in the disk queue. In this approach, every request gets a fair chance and no indefinite
postponement. All incoming requests are placed at the end of the queue. Whatever number that is
next in the queue will be the next number served. Using this algorithm doesn't provide the best results.
To determine the number of head movements you would simply find the number of tracks it took to
move from one request to the next. It does not try to give optimize seek time and performance may be
poor.
Ex 1: Given the following queue -- 95, 180, 34, 119, 11, 123, 62, 64 with the Read-write head initially
at the track 50 and the tail track being at 199
Ex 2:
Queue with I/O requests 23, 89, 132, 42, 187, head initial position is 100
Ex 2:
5. Look:
It is similar to the SCAN disk scheduling algorithm except the difference that the disk arm in spite of
going to the end of the disk goes only to the last request to be serviced in front of the head and then
reverses its direction from there only. Thus it prevents the extra delay which occurred due to
unnecessary traversal to the end of the disk.
6. C-Look:
As LOOK is similar to SCAN algorithm, in similar way, CLOOK is similar to CSCAN disk scheduling
algorithm. In CLOOK, the disk arm inspite of going to the end goes only to the last request to be
serviced in front of the head and then from there goes to the other end’s last request. Thus, it also
prevents the extra delay which occurred due to unnecessary traversal to the end of the disk.
RAID Levels
RAID stands for redundant array of independent disks. Today the term has been updated to
redundant array of independent disks. RAID is a way of grouping individual physical drives together
to form one bigger drive called a RAID set. RAID can make many smaller disks appear as one large
disk to a server. The RAID set represents all the smaller physical drives as one logical disk to your
server. The logical disk is called a LUN or logical unit number. Using RAID has two main advantages.
Better performance and higher availability, which means it goes faster and breaks down less often.
Performance is increased because the server has more spindles to read from or write to
when data is accessed from a drive. Availability is increased because the RAID controller can re-
create lost data from parity information. Parity is basically a checksum of the data that was written
to the disks, which gets written along with the original data. The controller re-creates the data that
was lost when the drive went bad by using the parity information stored on the surviving disks in the
RAID set.
There are a number of different ways drives can be grouped together to form RAID sets.
The different methods used to group drives are called RAID types. RAID types are numbered from 0
to 5. The numbers represent the level of RAID being used. RAID levels 0, 1 and 5 are the most
common. Combinations of RAID types may be used together. For example, you can create RAID 10
sets, by combine the RAID 0 sets into a RAID 1 set. This will essentially give you the performance
benefits of RAID 0, with the availability benefits of RAID 1.
The RAID type you should use depends on the type of application you are running on your
server. RAID 0 is the fastest. RAID 1 is the most reliable and RAID 5 is a good combination of both.
RAID 0:
RAID 0 is called disk striping. All the data is spread out in chunks across all the disks in the RAID set.
RAID 0 has great performance because you spread the load of storing data onto more physical drives. There
is no parity generated for RAID 0. Therefore there is no overhead to write data to RAID 0 disks. RAID 0 is only
good for better performance, and not for high availability, since parity is not generated for RAID 0 disks.
RAID 0 requires at least two physical disks.
RAID 1:
RAID 1 is called disk mirroring. All the data is written to at least two separate physical disks. The
disks are essentially mirror images of each other. If one of the disks fails, the other can be used to retrieve
data. Disk mirroring is good for very fast read operations. It's slower when writing to the disks, since the data
needs to be written twice. RAID 1 requires at least two physical disks
RAID 1+0:
RAID 1+0, which is also called RAID 10, uses a combination of disk mirroring and disk striping. The
data is normally mirrored first and then striped. Mirroring striped sets accomplishes the same task, but is less
fault tolerant than striping mirror sets. If you lose a drive in a stripe set, all access to data must be from the
other stripe set, because stripe sets have no parity. RAID 1+0 requires a minimum of four physical disks.
RAID 2:
RAID 2 is a technique that stripes data at the bit level using a Hamming code to detect errors. You need
two groups of disks. One group of disks is used to write the data, another group is used to write the error
correction codes. This uses Hamming error correction code (ECC), and stores this information in the
redundancy disks. When data is written to the disks, it calculates the ECC code for the data on the fly, and
stripes the data bits to the data-disks, and writes the ECC code to the redundancy disks. When data is read
from the disks, it also reads the corresponding ECC code from the redundancy disks, and checks whether the
data is consistent. If required, it makes appropriate corrections on the fly. This uses lot of disks and can be
configured in different disk configuration.
This is not used anymore. This is expensive and implementing it in a RAID controller is complex, and ECC
is redundant now-a-days, as the hard disk themselves can do this.
RAID 3:
RAID 3 uses something called a parity disk to store the parity information generated by the RAID
controller on a separate disk from the actual data disks, instead of striping. This RAID type is not currently
used very often because it performs poorly when there are a lot of little requests for data, as in a database.
This type performs well under applications that just want one long sequential data transfer. Applications like
video servers work well with this RAID type. RAID 3 requires a minimum of three physical disks.
RAID 4:
This uses block level striping. It uses multiple data disks, and a dedicated disk to store parity. It needs
minimum of 3 disks (2 disks for data and 1 for parity). It provides good random reads, as the data blocks are
striped. This is just like RAID 3 in having the dedicated parity disk, but this stripes blocks. This is just like RAID
5 in striping the blocks across the data disks, but this has only one parity disk. This is not commonly used.
RAID 5:
RAID 5 uses disk striping with parity. The data is striped across all the disks in the RAID set, along
with the parity information needed to reconstruct the data in case of disk failure. RAID 5 is the most common
method used, since it achieves a good balance between performance and availability. RAID 5 requires at least
three physical disks.
RAID 6:
RAID 6 increases reliability by utilizing two parity stripes, which allows for two disk failures within
the RAID set before data is lost. RAID 6 is seen in SATA environments, and solutions that require long data
retention periods, such as data archiving or disk-based backup.
File Concepts
The file system consists of two distinct parts: a collection of files, each storing related data, and a
directory structure, which organizes and provides information about all the files in the system.
Computers can store information on several different storage media, such as magnetic disks,
magnetic tapes, and optical disks in the form of files. Files are mapped, by the operating system, onto
physical devices. These storage devices are usually nonvolatile, so the contents are persistent through power
failures and system reboots. A file is a named collection of related information that is recorded on secondary
storage. Data cannot be written to secondary storage unless they are within a file. The file structure depends
on the type of the file. A text file is a sequence of characters organized into lines. A source file is a sequence
of subroutines and functions. An object file is a sequence of bytes organized into blocks.
File Attributes:
Name: The symbolic file name is the only information kept in human readable form.
Identifier: This unique tag, usually a number, identifies the file within the file system; it is the non-human-
readable name for the file.
Type: This information is needed for those systems that support different types.
Location: This information is a pointer to a device and to the location of the file on that device.
Size: The current size of the file (in bytes, words, or blocks), and possibly the maximum allowed size are
included in this attribute.
Protection: Access-control information determines who can do reading, writing, executing, and so on.
Time, date, and user identification: This information may be kept for creation, last modification, and last use.
These data can be useful for protection, security, and usage monitoring.
The information about all files is kept in the directory structure that also resides on secondary storage.
File Operations
1. Creating a file
2. Writing a file
3. Reading a file
4. Repositioning within a file
5. Deleting a file
6. Truncating a file.
Most OSes require that files be opened before access and closed after all access is complete. Normally the
programmer must open and close files explicitly, but some rare systems open the file automatically at first
access. Information about currently open files is stored in an open file table, contains
>File pointer - records the current position in the file, for the next read or write access.
>File-open count - How many times has the current file been opened and not yet closed? When this counter
reaches zero the file can be removed from the table.
>Disk location of the file.
>Access rights
Access Methods
The information in the file can be accessed in several ways. Some systems provide only one access
method for files and other systems provide many methods.
Sequential Access:
The simplest access method is sequential access. Information in the file is processed in order, one
record after the other. This mode of access is by far the most common; for example, editors and compilers
usually access files in this fashion.
Direct Access:
Random access file organization provides, accessing the records directly. Each record has its own
address on the file with by the help of which it can be directly accessed for reading or writing. The records
need not be in any sequence within the file and they need not be in adjacent locations on the storage
medium.
Directory Structure
Systems can store millions of files on the disk. To manage all these data, we need to organize them.
This organization is usually done in two parts. First, disks are split into partitions, also known as mini disks.
Sometimes, partitions are used to provide several separate areas within one disk, each treated as a separate
storage device. Partitions can also store multiple operating systems, allowing a system to boot and run more
than one. Second, each partition contains information about files within it. This information is kept in entries
in a device directory or volume table of contents. The device directory (more commonly known simply as a
directory) records information-such as name, location, size, and type-for all files on that partition.
Operations that are performed on Directory:
Directory Structures:
1. Single Level Directory:
The simplest directory structure is the single-level directory. All files are contained in the same
directory, which is easy to support and understand. A single-level directory has significant limitations,
however, when the number of files increases or when the system has more than one user. Since all files are in
the same directory, they must have unique names. If two users call their data file test, then the unique-name
rule is violated.
Even a single user on a single-level directory may find it difficult to remember the names of all the
files as the number of files increases.
A single-level directory often leads to confusion of file names among different users. The standard
solution is to create a separate directory for each user.
In the two-level directory structure, each user has his own The UFDs have similar structures, but each
lists only the files of a single user. W11en a user job starts or a user logs in, the system's is searched. The MFD
is indexed by user name or account number, and each entry points to the UFD for that user.
When a user refers to a particular file, only his own UFD is searched. Thus, different users may have
files with the same name, as long as all the file names within each UFD are unique. To create a file for a user,
the operating system searches only that user's UFD to ascertain whether another file of that name exists. To
delete a file, the operating system confines its search to the local UFD; thus, it cannot accidentally delete
another user's file that has the same name.
Although the two-level directory structure solves the name-collision problem, it still has
disadvantages. This structure effectively isolates one user from another. Isolation is an advantage when the
users are completely independent but is a disadvantage when the users want to cooperate on some task and to
access one another's files. Some systems simply do not allow local user files to be accessed by other users.
A two-level directory can be thought of as a tree, or an inverted tree, of height 2. The root of the tree is
the MFD. Its direct descendants are the UFDs.
3. Tree Structured Directories:
It is an extension to the two-tiered directory structure. A tree is the most common directory structure.
The tree has a root directory, and every file in the system has a unique path name.
When the same files need to be accessed in more than one place in the directory structure
( e.g. because they are being shared by more than one user / process ), it can be useful to provide an
acyclic-graph structure. These shared files or sub directories can be implemented by using a new
directory entry called a link. A link a pointer to another file or a subdirectory.
A hard link ( usually just called a link ) involves multiple directory entries that both refer to
the same file. Hard links are only valid for ordinary files in the same file system.
A symbolic link, that involves a special file, containing information about where to find the
linked file. Symbolic links may be used to link directories and/or files in other file systems, as well as
ordinary files in the current file system.
Hard links require a reference count, or link count for each file, keeping track of how many
directory entries are currently referring to this file. Whenever one of the references is removed the link
count is reduced, and when it reaches zero, the disk space can be reclaimed.
For symbolic links there are some issues , what to do with the symbolic links when the
original file is moved or deleted:
One option is to find all the symbolic links and adjust them also.
Another is to leave the symbolic links dangling, and discover that they are no longer valid the
next time they are used.
What if the original file is removed, and replaced with another file having the same name before
the symbolic link is next used?
If cycles are allowed in the graphs, then several problems can arise:
i. Search algorithms can go into infinite loops. One solution is to not follow links in search
algorithms.
ii. Sub trees can become disconnected from the rest of the tree and still not have their reference
counts reduced to zero. Periodic garbage collection is required to detect and resolve this problem.
File systems provide efficient and convenient access to the disk by allowing data to be stored, located, and
retrieved easily. The file system itself is generally composed of many different levels. Each level in the design
uses the features of lower levels to create new features for use by higher levels. File systems organize storage
on disk drives, and can be viewed as a layered design
At the lowest layer are the physical devices, consisting of the magnetic media, motors & controls, and
the electronics connected to them and controlling them. Modern disk put more and more of the electronic
controls directly on the disk drive itself, leaving relatively little work for the disk controller card to perform.
I/O Control consists of device drivers, special software programs ( often written in assembly ) which
communicate with the devices by reading and writing special codes directly to and from memory addresses
corresponding to the controller card's registers. Each controller card ( device ) on a system has a different set of
addresses that it listens to, and a unique set of command codes and results codes
that it understands.
The basic file system level works directly with the device drivers in terms of retrieving and storing raw
blocks of data, without any consideration for what is in each block. Depending on the system, blocks may be
referred to with a single block number, ( e.g. block # 234234 ), or with head sector cylinder combinations.
The file organization module knows about files and their logical blocks, and how they map to physical
blocks on the disk. In addition to translating from logical to physical blocks, the file organization module also
maintains the list of free blocks, and allocates free blocks to files as needed.
The logical file system deals with all of the meta data associated with a file ( UID, GID, mode, dates,
etc ), i.e. everything about the file except the data itself. This level manages the directory structure and the
mapping of file names to file control blocks, FCBs, which contain all of the meta data as well as block number
information for finding the data on the disk.
Common file systems in use include the UNIX file system, UFS, the Berkeley Fast File System, FFS,
Windows systems FAT, FAT32, NTFS, CDROM systems ISO 9660, and for Linux the extended file systems
ext2 and ext3
Directory Implementation
The selection of directory-allocation and directory-management algorithms significantly affects the efficiency,
performance, and reliability of the file system. Directories need to be fast to search, insert, and delete, with a
minimum of wasted disk space. Directories can be implemented by using two different data structures, Linear
list and hashed tables.
Linear List:
The simplest method of implementing a directory is to use a linear list of file names with pointers to
the data blocks. This method is simple to program but time-consuming to execute. To create a new file, we
must first search the directory to be sure that no existing file has the same name. Then, we add a new entry at
the end of the directory. To delete a file, we search the directory for the named file and then release the space
allocated to it.
To reuse the space after deleting a file, we can do it by using one of the following ways,
i. Mark the entry as unused by assigning special name or indicator or a flag value
ii. Attach this free space to list of free directory entries.
iii. Copy the last entry in the directory into the freed location
The real disadvantage of a linear list of directory entries is that finding a file requires a linear search.
Hash Table
Another data structure used for a file directory is a hash table. With this method, a linear list stores the
directory entries, but a hash data structure is also used. The hash table takes a value computed from the file
name and returns a pointer to the file name in the linear list. Therefore, it can greatly decrease the directory
search time. Insertion and deletion are also fairly straightforward, although some provision must be made for
collisions-situations in which two file names hash to the same location. The problem with hash tales is size,
here size is fixed and the hash function works based on size of the hash table.
Allocation methods:
Allocation methods specify how space is allocated for the files in the disk. There are three major allocation
methods, contiguous, linked and indexed.
Contiguous Allocation:
Contiguous Allocation requires that all blocks of a file be kept together contiguously. Performance is
very fast, because reading successive blocks of the same file generally requires no movement of the disk
heads. Contiguous allocation of a file is defined by the disk address and length of the first block. If the file is n
blocks long and starts at location b, then it occupies blocks b, b + 1, b + 2, ... , b + n - 1.
Accessing a file that has been allocated contiguously is easy. For sequential access, the file system
remembers the disk address of the last block referenced and, when necessary, reads the next block. For direct
access to block i of a file that starts at block b, we can immediately access block b + i. Thus, both sequential
and direct access can be supported by contiguous allocation.
The problem with contiguous allocation is determining how much space is needed for a file. When the
file is created, the total amount of space it will need must be found and allocated. Problems can arise when
files grow, or if the exact size of a file is unknown at creation time: Overestimation of the file's final size
increases external fragmentation and wastes disk space. Underestimation may require that a file be moved or a
process aborted if the file grows beyond its originally allocated space. If a file grows slowly over a long time
period and the total final space must be allocated initially, then a lot of space becomes unusable before the file
fills the space.
To minimize these drawbacks, some operating systems use a modified contiguous-allocation scheme.
Here, a contiguous chunk of space is allocated initially; then, if that amount proves not to be large enough,
another chunk of contiguous space, known as an is added. The location of a file's blocks is then recorded as a
location and a block count, plus a link to the first block of the next extent.
Linked Allocation:
Linked allocation solves all problems of contiguous allocation. With linked allocation, each file is a
linked list of disk blocks; the disk blocks may be scattered anywhere on the disk. The directory contains a
pointer to the first and last blocks of the file. Each block contains a pointer to the next block. These pointers
are not made available to the user.
To create a new file, we simply create a new entry ile the directory. With linked allocation, each
directory entry has a pointer to the first disk block of the file. This pointer is initialized to nil, to signify an
empty file. Linked allocation involves no external fragmentation, does not require pre known file sizes, and
allows files to grow dynamically at any time.
The major problem is that it can be used effectively only for sequential-access files. To filed the
ith block of a file, we must start at the beginning of that file and follow the pointers until we get to the ith
block. Each access to a pointer requires a disk read, and some require a disk seek. Consequently, it is
inefficient to support a direct-access capability for linked-allocation files. Another big problem with linked
allocation is reliability if a pointer is lost or damaged. Doubly linked lists provide some protection, at the cost
of additional overhead and wasted space.
An important variation on linked allocation is the use of a file allocation table (FAT). This simple but
efficient method of disk-space allocation is used by the MS-DOS and OS/2 operating systems.
A section of disk at the beginning of each volume is set aside to contain the table. The table has one
entry for each disk block and is indexed by block number. The FAT is used in much the same way as a linked
list. The directory entry contains the block number of the first block of the file. The table entry indexed by that
block number contains the block number of the next block in the file. This chain continues until it reaches the
last block, which has a special end-of-file value as the table entry. An unused block is indicated by a table
value of 0. Allocating a new block to a file is a simple matter of finding the first 0-valued table entry and
replacing the previous end-of-file value with the address of the new block. The 0 is then replaced with the end-
of-file value.
Indexed Allocation:
Indexed allocation supports direct access, without suffering from external fragmentation, because any
free block on the disk can satisfy a request for more space. Indexed allocation does suffer from wasted space,
however. The pointer overhead of the index block is generally greater than the pointer overhead of linked
allocation. Consider a common case in which we have a file of only one or two blocks. With linked allocation,
we lose the space of only one pointer per block. With indexed allocation, an entire index block must be
allocated, even if only one or two pointers will be non-nil.
Some disk space is wasted ( relative to linked lists or FAT tables ) because an entire index block must
be allocated for each file, regardless of how many data blocks the file contains. This leads to questions of how
big the index block should be, and how it should be implemented. There are several approaches:
Linked Scheme An index block is one disk block, which can be read and written in a single disk operation.
The first index block contains some header information, the first N block addresses, and if necessary a pointer
to additional linked index blocks.
MultiLevel Index The first index block contains a set of pointers to secondary index blocks, which in turn
contain pointers to the actual data blocks.
Combined Scheme This is the scheme used in UNIX inodes, in which the first 12 or so data block pointers are
stored directly in the inode, and then singly, doubly, and triply indirect pointers provide access to more data
blocks as needed. ( See below. ) The advantage of this scheme is that for small files ( which many are ), the
data blocks are readily accessible ( up to 48K with 4K block sizes ); files up to about 4144K ( using 4K blocks
) are accessible with only a single indirect block ( which can be cached ), and huge files are still accessible
using a relatively small number of disk accesses ( larger in theory than can be addressed by a 32bit address,
which is why some systems have moved to 64bit file pointers. )
Since disk space is limited, we need to reuse the space from deleted files for new files, if possible.
(Write-once optical disks only allow one write to any given sector, and thus such reuse is not physically
possible.) To keep track of free disk space, the system maintains a free space list. The free-space list records all
free disk blocks-those not allocated to some file or directory. To create a file, we search the free-space list for
the required amount of space and allocate that space to the new file. This space is then removed from the free-
space list. When a file is deleted, its disk space is added to the free-space list.
Bit Vector:
The free-space list is implemented as a bitmap or bit vector. Each block is represented by 1 bit. If the block is
free, the bit is 1; if the block is allocated, the bit is 0. For example, consider a disk where blocks 2, 3, 4, 5, 8, 9,
10, 11, 12, 13, 17, 18, 25, 26, and 27 are free and the rest of the blocks are allocated. The free-space bit map
would be
001111001111110001100000011100000
The main advantage of this approach is its relative simplicity and its efficiency in finding the first free block or
n consecutive free blocks on the disk.
Linked List:
Another approach to free-space management is to link together all the free disk blocks, keeping a
pointer to the first free block in a special location on the disk and caching it in memory. This first block
contains a pointer to the next free disk block, and so on.
In the above example, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 17, 18, 25, 26, and 27 were free and the rest of the blocks
were allocated. In this situation, we would keep a pointer to block 2 as the first free block. Block 2 would
contain a pointer to block 3, which would point to block 4, which would point to block 5, which would point to
block 8, and so on. This scheme is not efficient; to traverse the list, we must read each block, which requires
substantial I/0 time.
Counting:
Another approach takes advantage of the fact that, generally, several contiguous blocks may be
allocated or freed simultaneously, particularly when space is allocated with the contiguous-allocation
algorithm or through clustering. Thus, rather than keeping a list of n free disk addresses, we can keep the
address of the first free block and the number (n) of free contiguous blocks that follow the first block. Each
entry in the free-space list then consists of a disk address and a count.
Protection refers to a mechanism for controlling the access of programs, processes, or users to the
resources defined by a computer system. The processes in an operating system must be protected from one
another's activities. To provide such protection, we can use various mechanisms to ensure that only processes
that have gained proper authorization from the operating system can operate on the files, memory segments,
CPU, and other resources of a system.
Goals of Protection:
Principles of Protection:
The principle of least privilege dictates that programs, users, and systems be given just enough privileges
to perform their tasks. This ensures that failures do the least amount of harm. Typically each user is given
their own account, and has only enough privilege to modify their own files. The root account should not
be used for normal day to day activities. The System Administrator should also have an ordinary account,
and reserve use of the root account for only those tasks which need the root privileges
Domain of Protection:
A computer system is a collection of processes and objects. By objects, we mean both (such as
the CPU, memory segments, printers, disks, and tape drives) and (such as files, programs, and
semaphores). Each object has a unique name that differentiates it from all other objects in the system, and
each can be accessed only through well-defined and meaningful operations. The operations that are
possible may depend on the object. For example, on a CPU, we can only execute. Memory segments can be
read and written, Data files can be created, opened, read, written, closed, and deleted; program files can be
read, written, executed, and deleted. A process should be allowed to access only those resources for which it
has authorization. Furthermore, at any time, a process should be able to access only those reso1Jrces that it
currently requires to complete its task.
Domain structure:
A domain is a set of objects and respective operations. A process operates within a protection domain, which
specifies the resources that the process may access. The ability to execute an operation on an object is an
access right. So domain is a collection of access rights, each of which is an ordered pair < object name,
access right set>
Ex: if domain D is defined as <File F, {read,write}> then a process executing in domain D can both read and
write file F but it can not perform any other operation.
A domain may be static or dynamic. In static domain, the set of resources available to the process are fixed;
Domain Switching: It enables process to switch from one domain to another domain.
Access Matrix:
The domain of protection can be view as a matrix called access matrix. The rows of the access matrix represent
domains, and the columns represent objects. Each entry in the matrix consists of a set of access rights.
There are four domains and four objects-three files (F1, F2, F3) and one laser printer. A process executing in
domain 0 1 can read files F1 and F3 . A process executing in domain 0 4 has the same privileges as one
executing in domain 0 1; but in addition, it can also write onto files F1 and F3 . Note that the laser printer can
be accessed only by a process executing in domain D2.
The access-matrix scheme provides us with the mechanism for specifying a variety of policies.
we must ensure that a process executing in domain Di can access only those objects specified in row ( and then
only as allowed by the access-matrix entries.
The access matrix provides an appropriate mechanism for defining and implementing strict control for both the
static and dynamic association between processes and domains. They are,
Switching
Copy
Owner
Control
Switching:
When we switch a process from one domain to another, we are executing an operation (switch) on an
object. Processes should be able to switch from one domain to another. Switching from domain Di to domain
Dj is allowed if and only if the access right “switch” is placed at access(i,j) index. In the following table, a
process executing in domain D2 can switch to domain D3 or to domain D4 . A process in domain D4 can
switch to D1, and one in domain D1 can switch to D2.
Copy:
The ability to copy an access right from one domain (or row) of the access matrix to another is
denoted by an asterisk (*) appended to the access right. The copy right allows the access right to be copied
only within the column. (that is, for the object) for which the right is defined.
In the following figure (a), a process executing in domain D 2 can copy the read operation into any
entry associated with file F2 . Hence, the access matrix of Figure (a) can be modified to the access matrix
shown in Figure (b ).
A system may select only one of these three copy rights, or it may provide all three by identifying
them as separate rights: copy, transfer, and limited copy.
Owner:
We also need a mechanism to allow addition of new rights and removal of some rights. The owner
right controls these operations. If access(i, j) includes the owner right, then a process executing in domain Di
can add and remove any right in any entry in column j.
In the following figure, domain D1 is the owner of F1 and thus can add and delete any valid right in column F1.
Similarly, domain D2 is the owner of F2 and F3 and thus can add and remove any valid right within these two
columns. Thus, the access matrix of Figure (a) can be modified to the access matrix shown in Figure (b).
Control:
The copy and owner rights allow a process to change the entries in a column. A mechanism is also
needed to change the entries in a row. The control right is applicable only to domain objects. If access(i, j)
includes the control right, then a process executing in domain Di can remove any access right from row j.
For example, suppose that, in Figure (a), we include the control right in access(D2, D4). Then, a
process executil1.g in domain D2 could modify domain D4, as shown in Figure (b).
Figure (a)
Figure (b)
Implementation of Access Matrix
Global Table:
The simplest approach is one big global table with < domain, object, rights > entries.
Unfortunately this table is very large and so cannot be kept in memory ( without invoking virtual memory
techniques). There is also no good way to specify groupings If everyone has access to some resource, then
it still needs a separate entry for every domain.
Each resource has a list of unique bit patterns, termed locks. Each domain has its own list of
unique bit patterns, termed keys. Access is granted if one of the domain's keys fits one of the resource's
locks. Again, a process is not allowed to modify its own keys.
Comparison:
Each of the methods here has certain advantages or disadvantages, depending on the particular
situation and task at hand. Many systems employ some combination of the listed methods.
Real Time Operating Systems are very fast and quick respondent systems. Real time applications
used this RTOS. A real time application is an application program that functions within a time frame.
Real time processing requires quick transaction and characterized by supplying immediate response. For
example, a measurement from a petroleum refinery indicating that temperature is getting too high and
might demand for immediate attention to avoid an explosion. RTOS is a real time OS working with real
time constraints as power, time and efficient usage of memory. Most of the embedded systems are bound
to real time constraints and it is achieved using real time system. The main concern of RTOS is it
produces an accurate output within the deadline or time.
Examples of real time applications include:
Videoconference applications
VoIP (voice over Internet Protocol)
Online gaming
Community storage solutions
Some e-commerce transactions
Chatting
IM (instant messaging)
Examples of RTOS
VxWorks
QNX
eCos
RTLinux
An example is form your PC if you copy some data from one device to another device it may take several
minutes or more, we cannot predict responsiveness of the system of course, due to the tasks running
parallel at that time.
But, a real time embedded system can give an accurate output at right time that means, it is time critical
no delay is encouraged for real time systems and if any delay occurs it may lead to catastrophic effects.
For example Airbag control system in a car. If you drive a car at a high speed accidents may happen, in
such case airbag opens and saves your life.
Types of RTOS
Soft RTOS:
Soft real time OS is a type of OS where certain deadlines may be missed, they will respond at a time
t=0+. Soft real time systems are not constrained to extreme rules. The critical time of the soft real time
may be delayed to some extent. The expected latency between the tasks and time constraints may be
deviated. The preemption period for a soft real time task is about few milliseconds.
Ex: Digital camera, mobile phones, online data base etc.
Hard RTOS
Hard real time OS is a type of OS we can predict the deadline, they will respond at a time t=0. Hard real
time systems are constrained to predicted time constraints, deadlines and latency.
Ex: Air bag control in cars, anti-lock brake, engine control system etc.
Micro Kernels:
A core feature of any operating system, the kernel manages communication between hardware and
software. The kernel is responsible for managing memory, and I/O to memory, cache, the hard drive, and
other devices. It also handles device signals, task scheduling, and other essential duties. The kernel is one
of the first components loaded into memory during the boot process, and remains active as long as the
computer is operational. Kernels vary widely in function and scope, but always greatly affect their
operating system's capabilities. For this reason, particularly in Unix, administrators tweak the kernels to
best suit their requirements.
Compared to a typical kernel, a microkernel is compact, performing only the basic functions universal to
all computers. Designed to be integrated into different operating systems, a microkernel works with OS-
specific servers that provide higher level functions. This component-based structure improves a system's
portability, but potentially at the expense of performance. Mac OS and WinNT are two examples on
microkernel OS architecture.
Here some advantages to the microkernel OS architecture…
1. Service separation has the advantage that if one service (called a server) fails others can still work
so reliability is the primary feature. For example if a device driver crashes does not cause the
entire system to crash. Only that driver need to be restarted rather than having the entire system
die. This means more persistence as one server can be substituted with another. It also means
maintenance is easier.
2. Different services are built into special modules which can be loaded or unloaded when needed.
Patches can be tested separately then swapped to take over on a production instance.
3. Message passing allows independent communication and allows extensibility
4. The fact that there is no need to reboot the kernel implies rapid test and development.
5. Easy and faster integration with 3d party modules.
Here are some disadvantages to the microkernel approach…
1. Memory foot print is large
2. Potential performance loss (more software interfaces due to message passing)
3. Message passing bugs are not easy to fix
4. Process management is complex