os lab pdf
-
Upload
vipinkaushal -
Category
Documents
-
view
64 -
download
0
Transcript of os lab pdf
REPORT
ON
OPERATING SYSTEM LAB
Presented by
Rohit Kanaujiya
Course: M.Tech. (CSDP)
Roll no: 13MA60R01
Department of Mathematics
Indian Institute of Technology
Kharagpur
2014
Abstract
In this report I had given an overview of parallel computing, available within a short time
frame. The information about each topic is kept as compact as possible. Moreover, I went brief
explanation about Amdahl’s, in addition to Flynn’s taxonomy. In this few hardware concepts
processor architecture and memory organization are conceal but used further.
An Attempt is made to list all machines. The machines are described according to their macro
architectural class. Shared and distributed-memory SIMD an MIMD machines are discerned.
In order to go further, algorithm concepts dependencies, race conditions, mutual exclusion,
synchronization, parallel slowdown are also discussed briefly. Continuation to this parallel
programming models are also included, in addition to recent science and technology applications.
Some conclusions are also defined.
List of Problems
Abstract
1. Introduction
1. Error handler program
1.1. Statement and algorithm
1.2. Program implementation
2. Terminal Handler program
2.1. Statement and algorithm
2.2. Program implementation
3. Banker’s algorithm
3.1. Statement and algorithm
3.2. Program implementation
4. Sleeping barber program
4.1. Statement and algorithm
4.2. Program implementation
5. Dining Philosophers problem
5.1. Statement and algorithm
5.2. Program implementation
4
1. Error Handler Problem
1.1 Statement and algorithm
Five silent philosophers sit at a table around a bowl of food. A fork is placed between each pair
of adjacent philosophers. Each philosopher must alternately think and eat. However, a
philosopher can only eat food when he has both left and right forks. Each fork can be held by
only one philosopher and so a philosopher can use the fork only if it's not being used by another
philosopher. After he finishes eating, he needs to put down both forks so they become available
to others. A philosopher can grab the fork on his right or the one on his left as they become
available, but can't start eating before getting both of them.
Eating is not limited by the amount of food left: assume an infinite supply.
The problem is how to design a discipline of behavior such that each philosopher won't
starve; i.e., can forever continue to alternate between eating and thinking assuming that any
philosopher cannot know when others may want to eat or think.
1.2. Program implementation
#include"types.h"
#include "defs.h"
#include"param.h"
#include"memlayout.h"
#include"mmu.h"
#include"proc.h"
#include"x86.h"
#include"traps.h"
#include"spinlock.h"
void idtinit(void);
extern uint ticks;
void tvinit(void);
extern struct spinlock tickslock;
// Interrupt descriptor table (shared by all CPUs).
struct gatedesc idt[256];
5
extern uint vectors[]; // in vectors.S: array of 256 entry pointers
struct spinlock tickslock;
uint ticks;
void tvinit(void)
{
int i;
for(i = 0; i < 256; i++)
SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL],
DPL_USER);
initlock(&tickslock, "time");
}
void idtinit(void)
{
lidt(idt, sizeof(idt));
}
void trap(struct trapframe *tf)
{
if(tf−>trapno == T_SYSCALL){
if(proc−>killed)
exit();
proc−>tf = tf;
syscall();
if(proc−>killed)
exit();
return; }
switch(tf−>trapno){
case T_IRQ0 + IRQ_TIMER:
if(cpu−>id == 0){
acquire(&tickslock);
6
ticks++;
wakeup(&ticks);
release(&tickslock);
}
lapiceoi();
break;
case T_IRQ0 + IRQ_IDE:
ideintr();
lapiceoi();
break;
case T_IRQ0 + IRQ_IDE+1:
// Bochs generates spurious IDE1 interrupts.
break;
case T_IRQ0 + IRQ_KBD:
kbdintr();
lapiceoi();
break;
case T_IRQ0 + IRQ_COM1:
uartintr();
lapiceoi();
break;
case T_IRQ0 + 7:
case T_IRQ0 + IRQ_SPURIOUS:
cprintf("cpu%d: spurious interrupt at %x:%x\n",
cpu−>id, tf−>cs, tf−>eip);
lapiceoi();
break;
default:
if(proc == 0 || (tf−>cs&3) == 0){
// In kernel, it must be our mistake.
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
tf−>trapno, cpu−>id, tf−>eip, rcr2());
panic("trap");
}
// In user space, assume process misbehaved.
7
cprintf("pid %d %s: trap %d err %d on cpu %d "
"eip 0x%x addr 0x%x−−kill proc\n",
proc−>pid, proc−>name, tf−>trapno, tf−>err, cpu−>id, tf−>eip,
rcr2());
proc−>killed = 1;
}
// Force process exit if it has been killed and is in user space.
// (If it is still executing in the kernel, let it keep running
// until it gets to the regular system call return.)
if(proc && proc−>killed && (tf−>cs&3) == DPL_USER)
exit();
// Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock.
if(proc && proc−>state == RUNNING && tf−>trapno == T_IRQ0+IRQ_TIMER)
yield();
// Check if the process has been killed since we yielded
if(proc && proc−>killed && (tf−>cs&3) == DPL_USER)
exit();
}
8
2. Terminal Handler
Terminals support the standard system I/O operations, as well as a collection of terminal-
specific operations to control input-character editing and output delays. At the lowest level
are the terminal device drivers that control the hardware terminal ports. Terminal input is
handled according to the underlying communication characteristics, such as baud rate, and
according to a set of software-controllable parameters, such as parity checking.
Layered above the terminal device drivers are line disciplines that provide various degrees of
character processing.
The default line discipline is selected when a port is being used for an interactive login. The
line discipline is run in canonical mode; input is processed to provide standard line-oriented
editing functions, and input is presented to a process on a line-by-line basis.
Screen editors and programs that communicate with other computers generally run in non-
canonical mode (also commonly referred to as raw mode or character-at-a-time mode). In
this mode, input is passed through to the reading process immediately and without interpreta-
tion. All special-character input processing is disabled, no erase or other line editing pro-
cessing is done, and all characters are passed to the program that is reading from the terminal.
It is possible to configure the terminal in thousands of combinations between these two ex-
tremes. For example, a screen editor that wanted to receive user interrupts asynchronously
might enable the special characters that generate signals and enable output flow control, but
otherwise run in non-canonical mode; all other characters would be passed through to the
process uninterrupted.
On output, the terminal handler provides simple formatting services, including
• Converting the line-feed character to the two-character carriage-return-line-feed
sequence
• Inserting delays after certain standard control characters
• Expanding tabs
• Displaying echoed nongraphic ASCII characters as a two-character sequence of the
form “^C” (i.e., the ASCII caret character followed by the ASCII character that is the
character’s value offset from the ASCII “@” character).
Each of these formatting services can be disabled individually by a process through
control requests.
9
#include<stdio.h>
void save_context_switch();
void cpu(int v[]);
void pic();
void k_i_h();
int charout=0;
char key;
main()
{ char a;
int n=1,i;
printf("process going on\n");
while(n!=5)
{
if(n!=4)
sleep(1);
else
scanf("%c",&a);
key=a;
charout++;
n++;
}
printf("key is pressed\n");
sleep(1);
sleep(1);
printf("signal is passed to IRQ1\n");
for(i=0;i<2;i++)
sleep(1);
printf("INTERRUPT SENT TO PIC\n\n ");
pic();
}
void pic()
{ char a;
int v[2];
sleep(1);
printf("status of E-FLAG register before receiving the interrupt\n\n");
printf("31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5
4 3 2 1 0 \n");
printf("-----------------------------------------------------------------------------------------------
-\n");
printf(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vm rf 0 nt io of if df tf sf zf 0 af 0 pf
1 cf\n");
printf(" pl\n ");
printf(" ----------------------------------------------------------------------------------------------
--\n");
//scanf("%c",&a);
sleep(1);
printf("bit 9 of E-FLAG register is set 1\n\n");
printf("after receiving the interrupt\n\n");
printf("31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5
4 3 2 1 0 \n");
10
printf("-----------------------------------------------------------------------------------------------
-\n");
printf(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vm rf 0 nt io of 1 df tf sf zf 0 af 0 pf 1
cf\n");
printf(" pl\n ");
printf(" ----------------------------------------------------------------------------------------------
--\n");
sleep(1);
//scanf("%c",&a);
printf("\nPIC traslateS interrupt into the interrupt vector v\n\n");
sleep(1);
printf("\n Interrupt flag masked\n");
sleep(1);
sleep(1);
printf("31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5
4 3 2 1 0 \n");
printf("-----------------------------------------------------------------------------------------------
-\n");
printf(" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 vm rf 0 nt io of 0 df tf sf zf 0 af 0 pf 1
cf\n");
printf(" pl\n ");
printf(" ----------------------------------------------------------------------------------------------
--\n");
v[0]=1;
v[1]=54;
sleep(1);
printf("\nPIC sends the interrupt vector to the CPU\n\n ");
cpu(v);
}
void cpu(int v[])
{ printf("CPU accepts the interrupt vector\n");
int a[8][2]={{50,0},{51,1},{52,2},{53,3},{54,4},{55,5},{56,6},{57,7}};
int i,c;
for(i=0;i<8;i++)
if(v[1]==a[i][0])
c=a[i][1];
switch(c)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4: printf("keyboard interrupt handler selected\n");
sleep(1);
save_context_switch();
k_i_h();
11
printf("restore context\n");
sleep(1);
printf("CPU sends an aknowledgment\n");
break;
case 5:
break;
case 6:
break;
case 7:
printf("");
}
}
void save_context_switch()
{
sleep(1);
printf("\nUser mode to kernal mode:\n");
sleep(1);
printf("Switch to kernel stacks\n\n");
sleep(1);
printf("Save E-FLAGES \n");
sleep(1);
printf("\nproceess state\n");
sleep(1);
printf("program counter\n");
sleep(1);
printf("\nStack Pointer\n");
sleep(1);
printf("\nmemory allocation in PCB\n");
}
void k_i_h()
{
char x;
sleep(1);
printf("\nBuffer Variable incremented\n\n");
sleep(1);
fflush(stdout);
scanf("%c",&x);
scanf("%c",&x);
printf("\n Interrupt masked\n\n");
if(charout>0)
{
printf("display process called\n\n");
sleep(1);
printf("%c\n\n",key);
charout--;
printf("\n buffer variable decremented\n");
}
sleep(1);
printf("\nkeyboard interrupt handler sends end of interrupt to cpu\n\n");
}
12
3. Banker’s algorithm
Originally, The Banker’s algorithm is a resource allocation and deadlock avoidance
algorithm developed by Edsger Dijkstra that tests for safety by simulating the allocation of pre-
determined maximum possible amounts of all resources, and then makes a ”safe-state” check
to test for possible deadlock conditions for all other pending activities, before deciding whether
allocation should be allowed to continue. The Banker’s algorithm is run by the operating
system whenever a process requests resources. The algorithm prevents deadlock by denying or
postponing the request if it determines that accepting the request could put the system in an
unsafe state (one where deadlock could occur).
3.1 Statement and algorithm
Sources
For the Banker’s algorithm to work, it needs to know three things:
1. How much of each resource each process could possibly request
2. How much of each resource each process is currently holding
3. How much of each resource the system has available
Safe and Unsafe States
A state is considered safe if it is possible for all processes to finish executing (terminate).
Since the system cannot know when a process will terminate, or how many resources it will
have requested by then, the system assumes that all processes will eventually attempt to
acquire their stated maximum resources and terminate soon afterward. This is a reasonable
assumption in most cases since the system is not particularly concerned with how long each
process runs (at least not from a deadlock avoidance perspective). Also, if a process
terminates without acquiring its maximum resources, it only makes it easier on the system.
Given that assumption, the algorithm determines if a state is safe by trying to find a
hypothetical set of requests by the processes that would allow each to acquire (one-by-one)
its maximum resources and then terminate (returning its resources to the system). Any state
where no such set exists is an unsafe state. In a safe state, at least one process should be able
to acquire its maximum possible set of resources, and proceed to termination.
The simplified algorithm when the system receives a request for resources, it runs the
Banker’s algorithm to determine if it is safe to grant the request. The algorithm is fairly
straight forward once the distinction between safe and unsafe states is understood.
13
1. Can the request be granted?
• If not, the request is impossible and must either be denied or put on a waiting list
2. Assume that the request is granted
3. Is the new state safe?
• If so grant the request
• If not, either deny the request or put it on a waiting list Whether the system denies or
postpones an impossible or unsafe request is a decision specific to the operating system.
3.2 Program implementation
#include<iostream>
#include<conio.h>
#define MAX 20
using std::cin;
using std::cout;
using std::endl;
class bankers
{ private:
int al[MAX][MAX],m[MAX][MAX],n[MAX][MAX],avail[MAX];
int nop,nor,k,result[MAX],pnum,work[MAX],finish[MAX];
public:
bankers();
void input();
void method();
int search(int);
void display();
};
bankers::bankers()
{ k=0;
14
for(int i=0;i<MAX;i++)
{
for(int j=0;j<MAX;j++)
{
al[i][j]=0; m[i][j]=0; n[i][j]=0;
}
avail[i]=0;
result[i]=0;
finish[i]=0;
}
}
void bankers::input()
{ int i,j;
cout<<"Enter the number of processes:";
cin>>nop;
cout<<"Enter the number of resources:";
cin>>nor;
cout<<"Enter the allocated resources for each process: "<<endl;
for(i=0;i<nop;i++)
{ cout<<"\nProcess "<<i;
for(j=0;j<nor;j++)
{ cout<<"\nResource "<<j<<":";
cin>>al[i][j];
}
}
cout<<"Enter the maximum resources that are needed for each process: "<<endl;
for(i=0;i<nop;i++)
{ cout<<"\nProcess"<<i;
for(j=0;j<nor;j++)
{ cout<<"\nResouce"<<j<<":";
cin>>m[i][j];
n[i][j]=m[i][j]-al[i][j];
}
}
15
cout<<"Enter the currently available resources in the system: ";
for(j=0;j<nor;j++)
{ cout<<"Resource "<<j<<":";
cin>>avail[j];
work[j]=-1;
}
for(i=0;i<nop;i++)
finish[i]=0;
}
void bankers::method()
{ int i=0,j,flag;
while(1)
{ if(finish[i]==0)
{ pnum =search(i);
if(pnum!=-1)
{ result[k++]=i;
finish[i]=1;
for(j=0;j<nor;j++)
{ avail[j]=avail[j]+al[i][j];
}
}
}
i++;
if(i==nop)
{ flag=0;
for(j=0;j<nor;j++)
if(avail[j]!=work[j])
flag=1;
for(j=0;j<nor;j++)
work[j]=avail[j];
if(flag==0)
break;
else
i=0;
}
16
}
}
int bankers::search(int i)
{ int j;
for(j=0;j<nor;j++)
if(n[i][j]>avail[j])
return -1;
return 0;
}
void bankers::display()
{ int i,j;
cout<<endl<<"OUTPUT:";
cout<<endl<<"========\n";
cout<<endl<<"PROCESS\t ALLOTED\t MAXIMUM\t NEED";
for(i=0;i<nop;i++)
{ cout<<"\nP"<<i+1<<"\t ";
for(j=0;j<nor;j++)
{ cout<<al[i][j]<<" ";
}
cout<<"\t ";
for (j=0;j<nor;j++)
{ cout<<m[i][j]<<" ";
}
cout<<"\t ";
for(j=0;j<nor;j++ )
{ cout<<n[i][j]<<" ";
}
}
cout<<"\n\nThe sequence of the safe processes are: \n\n";
for(i=0;i<k;i++)
{ int temp = result[i]+1 ;
cout<<"P"<<temp<<" ";
}
cout<<"\n\nThe sequence of unsafe processes are: \n\n";
int flg=0;
17
for (i=0;i<nop;i++)
{ if(finish[i]==0)
{ flg=1;
}
cout<<"P"<<i<<" ";
}
cout<<endl<<"\n\nRESULT:";
cout<<endl<<"=======\n";
if(flg==1)
cout<<endl<<"The system is not in safe state and deadlock may occur!!";
else
cout<<endl<<"The system is in safe state and deadlock will not occur!!";
}
main()
{ cout<<"BANKER's ALGORITHM\n"<<endl;
bankers B;
B.input ( );
B.method ( );
B.display ( );
getch();
}
18
4. Sleeping Barber Problem
4.1 Statement and algorithm
The barber shop has one barber, one barber chair, and n chairs for waiting customers, if any, to
sit on. If there are no customers present, the barber sits down in the barber chair and falls asleep.
When a customer arrives, he has to wake up the sleeping barber. If additional customers arrive
while the barber is cutting a customer's hair, they either sit down (if there are empty chairs) or
leave the shop (if all chairs are full).
4.2. Program implementation
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define CUSTOMERS 0
#define BARBERS 1
#define MUTEX 2
#define CHAIRS 5
void up(int sem_id,int sem_num,struct sembuf *semaphore) {
semaphore->sem_num=sem_num;
semaphore->sem_op=1;
semaphore->sem_flg=0;
semop(sem_id,semaphore,1);
}
void down(int sem_id,int sem_num,struct sembuf *semaphore) {
semaphore->sem_num=sem_num;
semaphore->sem_op=-1;
semaphore->sem_flg=0;
semop(sem_id,semaphore,1);
}
void initSem(int sem_id,int sem_num,int val) {
union semnum {
int val;
struct semid_ds *buf;
unsigned short *array;
}
argument;
argument.val=val;
semctl(sem_id,sem_num,SETVAL,argument);
}
int main() {
int sem_key=1111,shm_key=2222;
int sem_id,shm_id;
19
int *waiting;
struct sembuf semaphore;
int count=1;
shm_id=shmget(shm_key,sizeof(int),IPC_CREAT|0666);
sem_id=semget(sem_key,3,IPC_CREAT|0666);
waiting=shmat(shm_id,NULL,0);
*waiting=0;
initSem(sem_id,CUSTOMERS,0);
initSem(sem_id,BARBERS,0);
initSem(sem_id,MUTEX,1);
printf("There are %d chairs.\n",CHAIRS);
if(fork()) {
/* The barber part. */
while(1) {
down(sem_id,CUSTOMERS,&semaphore);
down(sem_id,MUTEX,&semaphore);
*waiting=*waiting-1;
up(sem_id,BARBERS,&semaphore);
up(sem_id,MUTEX,&semaphore);
printf("The barber is now cutting hair.\n");
sleep(6); /* Slowly cut the hair */
}
}
else {
/* The customer part. */
while(1) {
sleep(1); /* Customers come in fast */
down(sem_id,MUTEX,&semaphore);
if(*waiting < CHAIRS) {
printf("Customer %d is seated.\n",count++);
*waiting=*waiting+1;
up(sem_id,CUSTOMERS,&semaphore);
up(sem_id,MUTEX,&semaphore);
}
else
{
printf("Customer %d left the shop.\n",count++);
up(sem_id,MUTEX,&semaphore);
}
}
}
}
20
5. Dining Philospher Problem
5.1 Statement and algorithm
Five silent philosophers sit at a table around a bowl of food. A fork is placed between each pair
of adjacent philosophers. Each philosopher must alternately think and eat. However, a
philosopher can only eat food when he has both left and right forks. Each fork can be held by
only one philosopher and so a philosopher can use the fork only if it's not being used by another
philosopher. After he finishes eating, he needs to put down both forks so they become available
to others. A philosopher can grab the fork on his right or the one on his left as they become
available, but can't start eating before getting both of them.
Eating is not limited by the amount of food left: assume an infinite supply.
The problem is how to design a discipline of behavior such that each philosopher won't
starve; i.e., can forever continue to alternate between eating and thinking assuming that any
philosopher cannot know when others may want to eat or think.
5.2. Program implementation
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define cls() printf("33[H33[J]]")
#define EATINGTIME 1
void * philosopher1();
void * philosopher2();
void * philosopher3();
void * philosopher4();
void * philosopher5();
int end=0;
int main()
{
char a[2];
pthread_t t1,t2,t3,t4,t5;
pthread_attr_t at1;
pthread_attr_init(&at1);
pthread_attr_setdetachstate(&at1,PTHREAD_CREATE_DETACHED);
sem_init(&sem15,0,1);
sem_init(&sem12,0,1);
sem_init(&sem23,0,1);
sem_init(&sem34,0,1);
sem_init(&sem45,0,1);
cls();
21
printf("\n\n\n\n\n\n");
printf("____________________________________________________________________________
_________");
printf("\n\n\n\t\t\tDINNING PHILOSOPHER PROBLEM.");
printf("\n\t\t\t____________________________");
printf("\n\n\t\tNO. OF PHILOSOPHERS :5");
printf("\n\n\t\tNO. OF FORKS(SPOONS):5\n");
printf("____________________________________________________________________________
_________");
printf("\n\n\n\t\tPRESS ENTER TO CONTINUE…………………");
fgets(a,2,stdin);
cls();
pthread_create(&t1,&at1,philosopher1,NULL);
pthread_create(&t2,&at1,philosopher2,NULL);
pthread_create(&t3,&at1,philosopher3,NULL);
pthread_create(&t4,&at1,philosopher4,NULL);
pthread_create(&t5,&at1,philosopher5,NULL);
while(end!=5)
{
}
}
void * philosopher1()
{
int i=0;
printf("\n\t\tPHILOSOPHER-1 THINKING.\n");
while(i<EATINGTIME)
{
sleep(1);
sem_wait(&sem15);
sem_wait(&sem12);
printf("\n\t\t\t* PHILOSOPHER-1 EATING.\n");
sleep(1);
sem_post(&sem15);
sem_post(&sem12);
printf("\n\t\tPHILOSOPHER-1 THINKING.\n");
i++;
}
end++;
}
void * philosopher2()
{
int i=0;
printf("\n\t\tPHILOSOPHER-2 THINKING.\n");
while(i<EATINGTIME)
{
sleep(1);
sem_wait(&sem12);
sem_wait(&sem23);
printf("\n\t\t\t* PHILOSOPHER-2 EATING.*\n");
sleep(1);
22
sem_post(&sem12);
sem_post(&sem23);
printf("\n\t\tPHILOSOPHER-2 THINKING.\n");
i++;
}
end++;
}
void * philosopher3()
{
int i=0;
printf("\n\t\tPHILOSOPHER-3 THINKING.\n");
while(i<EATINGTIME)
{
sleep(1);
sem_wait(&sem23);
sem_wait(&sem34);
printf("\n\t\t\t* PHILOSOPHER-3 EATING.*\n");
sleep(1);
sem_post(&sem23);
sem_post(&sem34);
printf("\n\t\tPHILOSOPHER-3 THINKING.\n");
i++;
}
end++;
}
void * philosopher4()
{
int i=0;
printf("\n\t\tPHILOSOPHER-4 THINKING.\n");
while(i<EATINGTIME)
{
sleep(1);
sem_wait(&sem34);
sem_wait(&sem45);
printf("\n\t\t\t* PHILOSOPHER-4 EATING.*\n");
sleep(1);
sem_post(&sem34);
sem_post(&sem45);
printf("\n\t\tPHILOSOPHER-4 THINKING.\n");
i++;
}
end++;
}
void * philosopher5()
{
int i=0;
printf("\n\t\tPHILOSOPHER-5 THINKING.\n");
while(i<EATINGTIME)
{
23
sleep(1);
sem_wait(&sem45);
sem_wait(&sem15);
printf("\n\t\t\t* PHILOSOPHER-5 EATING.*\n");
sleep(1);
sem_post(&sem45);
sem_post(&sem15);
printf("\n\t\tPHILOSOPHER-5 THINKING.\n");
i++;
}
end++;
}