0% found this document useful (0 votes)
47 views

OS Lab Manual Programs

The document discusses basic Linux commands for listing, viewing, editing, moving, copying, deleting and compressing files. It also covers commands for finding files, checking who is logged in, changing permissions and connecting to remote systems.

Uploaded by

siva nesh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
47 views

OS Lab Manual Programs

The document discusses basic Linux commands for listing, viewing, editing, moving, copying, deleting and compressing files. It also covers commands for finding files, checking who is logged in, changing permissions and connecting to remote systems.

Uploaded by

siva nesh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 94

1

Ex.No:1 Basic Command in Linux

Aim:
To Study the basic commands in Linux.
Files
• ls ---lists your files
ls -l --- lists your files in 'long format', which contains lots of useful information, e.g.
the exact size of the file, who owns the file and who has the right to look at it, and
when it was last modified.
ls -a --- lists all files, including the ones whose filenames begin in a dot, which you do
not always want to see.
There are many more options, for example to list files by size, by date, recursively etc.
• more filename --- shows the first part of a file, just as much as will fit on one screen.
Just hit the space bar to see more or q to quit. You can use /pattern to search for a
pattern.
• emacs filename --- is an editor that lets you create and edit a file. mv filename1
filename2 --- moves a file (i.e. gives it a different name, or moves it into a different
directory (see below)
• cp filename1 filename2 --- copies a file
• rm filename --- removes a file. It is wise to use the option rm -i, which will ask you
for confirmation before actually deleting anything.
• diff filename1 filename2 --- compares files, and shows where they differ
• wc filename --- tells you how many lines, words, and characters there are in a file
• chmod options filename --- lets you change the read, write, and execute permissions
on your files. The default is that only you can look at them and change them, but you
may sometimes want to change these permissions. For example, chmod
o+r filename will make the file readable for everyone, and chmod o-r filename will
make it unreadable for others again. Note that for someone to be able to actually look
at the file the directories it is in need to be at least executable
• File Compression
o gzip filename --- compresses files, so that they take up much less space.
Usually text files compress to about half their original size, but it depends very
much on the size of the file and the nature of the contents. There are other
tools for this purpose, too (e.g. compress), but gzip usually gives the highest
compression rate. Gzip produces files with the ending '.gz' appended to the
original filename.
o gunzip filename --- uncompresses files compressed by gzip.
o gzcat filename --- lets you look at a gzipped file without actually having to
gunzip it (same as gunzip -c). You can even print it directly,
using gzcat filename | lpr
• printing
o lpr filename --- print. Use the -P option to specify the printer name if you
want to use a printer other than your default printer. For example, if you want
to print double-sided, use 'lpr -Pvalkyr-d', or if you're at CSLI, you may want
to use 'lpr -Pcord115-d'. See 'help printers' for more information about printers
and their locations.
o lpq --- check out the printer queue, e.g. to get the number needed for removal,
or to see how many other files will be printed before yours will come out
o lprm jobnumber --- remove something from the printer queue. You can find
the job number by using lpq. Theoretically you also have to specify a printer
2

name, but this isn't necessary as long as you use your default printer in the
department.
Directories
Directories, like folders on a Macintosh, are used to group files together in a hierarchical
structure.
• mkdir dirname --- make a new directory
• cd dirname --- change directory. You basically 'go' to another directory, and you will
see the files in that directory when you do 'ls'. You always start out in your 'home
directory', and you can get back there by typing 'cd' without arguments. 'cd ..' will get
you one level up from your current position
• pwd --- tells you where you currently are.
Finding things
• ff --- find files anywhere on the system. This can be extremely useful if you've
forgotten in which directory you put a file, but do remember the name. In fact, if you
use ff -p you don't even need the full name, just the beginning. This can also be useful
for finding other things on the system, e.g. documentation.
• grep string filename(s) --- looks for the string in the files. This can be useful a lot of
purposes, e.g. finding the right file among many, figuring out which is the right
version of something, and even doing serious corpus work. grep comes in several
varieties (grep, egrep, and fgrep) and has a lot of very flexible options. Check out the
man pages if this sounds good to you.
About other people
• w --- tells you who's logged in, and what they're doing. Especially useful: the 'idle'
part. This allows you to see whether they're actually sitting there typing away at their
keyboards right at the moment.
• who --- tells you who's logged on, and where they're coming from. Useful if you're
looking for someone who's actually physically in the same building as you, or in some
other particular location.
• finger username --- gives you lots of information about that user, e.g. when they last
read their mail and whether they're logged in. Often people put other practical
information, such as phone numbers and addresses, in a file called .plan. This
information is also displayed by 'finger'.
• last -1 username --- tells you when the user last logged on and off and from where.
Without any options, last will give you a list of everyone's logins.
• talk username --- lets you have a (typed) conversation with another user
• write username --- lets you exchange one-line messages with another user
About your (electronic) self
• whoami --- returns your username. Sounds useless, but isn't. You may need to find out
who it is who forgot to log out somewhere, and make sure *you* have logged out.
• finger & .plan files
of course you can finger yourself, too. That can be useful e.g. as a quick check
whether you got new mail. Try to create a useful .plan file soon. Look at other
people's .plan files for ideas. The file needs to be readable for everyone in order to be
visible through 'finger'. Do 'chmod a+r .plan' if necessary. You should realize that this
information is accessible from anywhere in the world, not just to other people on
turing.
• passwd --- lets you change your password, which you should do regularly (at least
once a year).
• ps -u yourusername --- lists your processes. Contains lots of information about them,
including the process ID, which you need if you have to kill a process. Normally,
when you have been kicked out of a dialin session or have otherwise managed to get
3

yourself disconnected abruptly, this list will contain the processes you need to kill.
Those may include the shell (tcsh or whatever you're using), and anything you were
running, for example emacs or elm. Be careful not to kill your current shell - the one
with the number closer to the one of the ps command you're currently running. But if
it happens, don't panic. Just try again :) If you're using an X-display you may have to
kill some X processes before you can start them again. These will show only when
you use ps -efl, because they're root processes.
• kill PID --- kills (ends) the processes with the ID you gave. This works only for your
own processes, of course. Get the ID by using ps. If the process doesn't 'die' properly,
use the option -9. But attempt without that option first, because it doesn't give the
process a chance to finish possibly important business before dying. You may need to
kill processes for example if your modem connection was interrupted and you didn't
get logged out properly, which sometimes happens.
• du filename --- shows the disk usage of the files and directories in filename (without
argument the current directory is used). du -s gives only a total.
• last yourusername --- lists your last logins. Can be a useful memory aid for when you
were where, how long you've been working for, and keeping track of your phonebill if
you're making a non-local phonecall for dialling in.
Connecting to the outside world
• nn --- allows you to read news. It will first let you read the news local to turing, and
then the remote news. If you want to read only the local or remote news, you can
use nnl or nnr, respectively. To learn more about nn type nn, then \tty{:man}, then
\tty{=.*}, then \tty{Z}, then hit the space bar to step through the manual.
rlogin hostname --- lets you connect to a remote host
• telnet hostname --- also lets you connect to a remote host. Use rlogin whenever
possible.
• ftp hostname --- lets you download files from a remote host which is set up as an
ftp-server. This is a common method for exchanging academic papers and drafts. If
you need to make a paper of yours available in this way, you can (temporarily) put a
copy in /user/ftp/pub/TMP. For more permanent solutions, ask Emma. The most
important commands within ftp are get for getting files from the remote machine,
and put for putting them there (mget and mput let you specify more than one file at
once). Sounds straightforward, but be sure not to confuse the two, especially when
your physical location doesn't correspond to the direction of the ftp connection you're
making. ftp just overwrites files with the same filename. If you're transferring
anything other than ASCII text, use binary mode.
• lynx --- lets you browse the web from an ordinary terminal. Of course you can see
only the text, not the pictures. You can type any URL as an argument to
the G command. When you're doing this from any Stanford host you can leave out
the .stanford.edu part of the URL when connecting to Stanford URLs. Type H at any
time to learn more about lynx, and Q to exit.

Shell Programming

Ex.No.2a Even Or Odd

Aim:

To write a program to find whether a number is even or odd.


4

Algorithm:

STEP 1: Read the input number.

STEP 2: Perform modular division on input number by 2.

STEP 3: If remainder is 0 print the number is even.

STEP 4: Else print number is odd.

STEP 5: Stop the program.


Program

echo "enter the number"

read num

echo "enter the number"

read num

if [ `expr $num % 2` -eq

0] then

echo "number is even"

else

echo "number isodd"

fi

Output:

enter the number: 5

The number is odd

Result:

Thus the program has been executed successfully.

Ex.No.2b Biggest Of Two Numbers

Aim :

To write a program to find biggest in two numbers.


5

Algorithm :

STEP 1: Read The Two Numbers.

STEP 2: If Value Of A Is Greater Than B Is Big.

STEP 3: Else Print B Is Big.

STEP 4: Stop The Program.

Program:

echo "enter the number"

read a b

if [ $a -gt $b]

then

echo "A is

big" else

echo "B is

big" fi

Output:

Enter The Two Numbers:

23 67

B is Big.

Result:

Thus the program has been executed successfully.

11
6

Ex.No.2c Biggest Of Three Numbers

Aim:

To write a program to find biggest of three numbers.


Algorithm:

STEP 1: Read The Three Numbers.

STEP 2: If A Is Greater Than B And A Is Greater Than C Then Print A Is Big.

STEP 3: Else If B is greater Than C Then C Is Big.

STEP 4: Else Print C Is Big.

STEP 5: Stop The Program.


Program:

echo "enter three numbers"

read a b c

if [ $a -gt $b ] && [ $a -gt

$c] then

echo "A is big"

else if [ $b -gt

$c ] then

echo "B is

big" else

echo "C is

big" fi

fi
Output:

ENTER THREE

NUMBERS: 23 54 78

C IS BIG.
Result:

Thus the program has been executed successfully.


7

Ex.No.2d Factorial of Number

Aim:

To find a factorial of a number using shell script.


Algorithm:

Step 1: read a number.

Step 2: Initialize fact as 1

Step 3: Initialize I as 1.

Step 4: While I is lesser than or equal to no.

Step 5: Multiply the value of I and fact and assign to fact increment the value of I by 1.

Step 6: print the result.

Step 7: Stop the program.


Program:

echo "enter the number"

read n

fact=1

i=1

while [ $i -le

$n ] do

fact=`expr $i \*

$fact` i=`expr $i + 1`

done

echo "the fcatorial number of $ni is $fact


Output:
Enter the number 4

The factorial of 4 is 24.


Result:

Thus the program has been executed successfully.


8

Ex.No.2e Fibonacci Series

Aim :

To write a program to display the Fibonacci series.

Algorithm:

Step 1: Initialize n1& n2 as 0 & 1.

Step 2: enter the limit for Fibonacci.

Step 3: initialize variable as 0

Step 4: Print the Fibonacci series n1 and n2.

Step 5: While the var number is lesser than lim-2

Step 6: Calculate n3=n1+n2.

Step 7: Set n1=n2 and n2=n3

Step 8: Increment var by 1 and print n2

Step 9: stop the program.

Program:

echo " ENTER THE LIMIT FOR FIBONNACI

SERIES" read lim

n1=0

n2=1

var=0

echo "FIBONACCI SERIES IS

" echo "$n1"

echo "$n2"

while [ $var -lt `expr $lim - 2`

] do

n3=`expr $n1 + $n2 `

n1=`expr $n2 `
9

n2=`expr $n3 `

var=`expr $var + 1 `

echo "$n2"

done

Output:

Enter the limit for

Fibonacci: 5

The Fibonacci series is:

01123

Result:

Thus the program has been executed successfully.


10

PROCESS SCHEDULING

CPU scheduling is used in multiprogrammed operating systems.


o By switching CPU among processes, efficiency of the system can be
improved. Some scheduling algorithms are FCFS, SJF, Priority,
Round-Robin, etc.
o Gantt chart provides a way of visualizing CPU scheduling and enables to
understand better.

First Come First Serve (FCFS)


o Process that comes first is processed first FCFS scheduling is
non-preemptive
o Not efficient as it results in long average waiting time.
o Can result in starvation, if processes at beginning of the queue have long
bursts.

Shortest Job First (SJF)


o Process that requires smallest burst time is processed first. SJF can be
preemptive or non–preemptive
o When two processes require same amount of CPU utilization, FCFS is
used to break the tie.
o Generally efficient as it results in minimal average waiting time.
o Can result in starvation, since long critical processes may not be
processed.

Priority
o Process that has higher priority is processed first. Prioirty can be
preemptive or non–preemptive
o When two processes have same priority, FCFS is used to break the tie.
o Can result in starvation, since low priority processes may not be
processed.

Round Robin
o All processes are processed one by one as they have arrived, but in
rounds. Each process cannot take more than the time slice per round.
o Round robin is a fair preemptive scheduling algorithm.
o A process that is yet to complete in a round is preempted after the time
slice and put at the end of the queue.
o When a process is completely processed, it is removed from the queue.
11

Exp# 3a FCFS Scheduling

Aim
To schedule snapshot of processes queued according to FCFS (First Come First
Serve) scheduling.

Algorithm

1. Define an array of structure process with members pid, btime, wtime & ttime.
2. Get length of the ready queue, i.e., number of process (say n)
3. Obtain btime for each process.
4. The wtime for first process is 0.
5. Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei
1 Compute average waiting time awat and average turnaround time atur
2 Display the btime, ttime and wtime for each process.
3 Display GANTT chart for the above scheduling
4 Display awat time and atur
5 Stop

Program
/* FCFS Scheduling - fcfs.c */

#include <stdio.h>

struct process
{
int pid; int
btime; int
wtime; int
ttime;
} p[10];
main()
{
int i,j,k,n,ttur,twat; float
awat,atur;
printf("Enter no. of process : "); scanf("%d",
&n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ",(i+1)); scanf("%d",
&p[i].btime);
p[i].pid = i+1;
12

}
p[0].wtime = 0; for(i=0;
i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime; p[i].ttime =
p[i].wtime + p[i].btime;
}
ttur = twat = 0; for(i=0;
i<n; i++)
{
ttur += p[i].ttime; twat +=
p[i].wtime;
}
awat = (float)twat / n; atur =
(float)ttur / n;
printf("\nFCFS Scheduling\n\n");
for(i=0; i<28; i++)
printf("-");
printf("\nProcess B-Time T-Time W-Time\n"); for(i=0;
i<28; i++)
printf("-"); for(i=0;
i<n; i++)
printf("\nP%d\t%4d\t%3d\t%2d",p[i].pid,p[i].btime,p[i].ttime,p[i].wtime);
printf("\n"); for(i=0; i<28; i++)
printf("-");
printf("\n\nGANTT Chart\n"); printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n");
printf("|"); for(i=0; i<n; i++)
{
k = p[i].btime/2; for(j=0;
j<k; j++) printf(" ");
printf("P%d",p[i].pid);
for(j=k+1; j<p[i].btime; j++)
printf(" ");
printf("|");
}
printf("\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n");
printf("0"); for(i=0; i<n;
i++)
{
for(j=0; j<p[i].btime; j++) printf(" ");
printf("%2d",p[i].ttime);
}
printf("\n\nAverage waiting time : %5.2fms", awat);
13

printf("\nAverage turn around time : %5.2fms\n", atur);}

Output
$ gcc fcfs.c

$./a.out
Enter no. of process: 4
Burst time for process P1 (in ms) : 10 Burst time for
process P2 (in ms) : 4 Burst time for process P3 (in
ms) : 11 Burst time for process P4 (in ms) : 6
FCFS Scheduling

----------------------------
Process B-Time T-Time W-Time
----------------------------
P1 10 10 0
P2 4 14 10
P3 11 25 14
P4 6 31 25
----------------------------
GANTT Chart
--------------------------------------------------------------

| P1 | P2 | P3 | P4 |
--------------------------------------------------------------
0 10 14 25 31
Average waiting time : 12.25ms
Average turn around time : 20.00ms

Result :
Thus waiting time & turnaround time for processes based on FCFS scheduling was
computed and the average waiting time was determined.

Exp# 3b SJF Scheduling


14

Aim
To schedule snapshot of processes queued according to SJF (Shortest Job First)
scheduling.

Algorithm

1. Define an array of structure process with members pid, btime, wtime & ttime.
2. Get length of the ready queue, i.e., number of process (say n)
3. Obtain btime for each process.
4. Sort the processes according to their btime in ascending order.
a. If two process have same btime, then FCFS is used to resolve the tie.
5. The wtime for first process is 0.
6. Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei
7. Compute average waiting time awat and average turn around time atur.
8. Display btime, ttime and wtime for each process.
9. Display GANTT chart for the above scheduling
10. Display awat and atur
11. Stop

Program
/* SJF Scheduling – sjf.c */

#include <stdio.h>

struct process
{
int pid; int
btime; int
wtime; int
ttime;
} p[10], temp;
main()
{
int i,j,k,n,ttur,twat; float
awat,atur;
printf("Enter no. of process : "); scanf("%d",
&n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ",(i+1)); scanf("%d",
&p[i].btime);
p[i].pid = i+1;
15

}
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if((p[i].btime > p[j].btime) ||
(p[i].btime == p[j].btime && p[i].pid > p[j].pid))
{
temp = p[i]; p[i]
= p[j]; p[j] =
temp;
}}}
p[0].wtime = 0; for(i=0;
i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime; p[i].ttime =
p[i].wtime + p[i].btime;
}
ttur = twat = 0;
for(i=0; i<n; i++)
{
ttur += p[i].ttime; twat +=
p[i].wtime;
}
awat = (float)twat / n; atur =
(float)ttur / n;
printf("\n SJF Scheduling\n\n"); for(i=0; i<28; i++)
printf("-");
printf("\nProcess B-Time T-Time W-Time\n"); for(i=0;
i<28; i++)
printf("-"); for(i=0;
i<n; i++)
printf("\n P%-4d\t%4d\t%3d\t%2d",
p[i].pid,p[i].btime,p[i].ttime,p[i].wtime);
printf("\n"); for(i=0; i<28;
i++)
printf("-");
printf("\n\nGANTT Chart\n");
printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n|"); for(i=0;
i<n; i++)
{
k = p[i].btime/2; for(j=0;
j<k; j++) printf(" ");
printf("P%d",p[i].pid); for(j=k+1;
j<p[i].btime; j++)
printf(" ");
16

printf("|");
}
printf("\n-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n0"); for(i=0;
i<n; i++)
{
for(j=0; j<p[i].btime; j++) printf(" ");
printf("%2d",p[i].ttime);
}
printf("\n\nAverage waiting time : %5.2fms", awat);
printf("\nAverage turn around time : %5.2fms\n", atur);
}
Output
$ gcc sjf.c
$./a.out
Enter no. of process : 5
Burst time for process P1 (in ms) : 10 Burst time for
process P2 (in ms) : 6 Burst time for process P3 (in
ms) : 5 Burst time for process P4 (in ms) : 6 Burst
time for process P5 (in ms) : 9
SJF Scheduling

----------------------------
Process B-Time T-Time W-Time
----------------------------
P3 5 5 0
P2 6 11 5
P4 6 17 11
P5 9 26 17
P1 10 36 26
----------------------------
GANTT Chart
-------------------------------------------------------------------------------
| P3 | P2 | P4 | P5 | P1 |
-------------------------------------------------------------------------------
0 5 11 17 26 36
Average waiting time : 11.80ms
Average turn around time : 19.00ms

Result

Thus waiting time & turnaround time for processes based on SJF scheduling was
computed and the average waiting time was determined.
Exp# 3c Priority Scheduling

Aim
To schedule snapshot of processes queued according to Priority scheduling.

Algorithm

1. Define an array of structure process with members pid, btime, pri, wtime &
ttime.
2. Get length of the ready queue, i.e., number of process (say n)
3. Obtain btime and pri for each process.
4. Sort the processes according to their pri in ascending order.
a. If two process have same pri, then FCFS is used to resolve the tie.
5. The wtime for first process is 0.
6. Compute wtime and ttime for each process as:
a. wtimei+1 = wtimei + btimei
b. ttimei = wtimei + btimei

7. Compute average waiting time awat and average turn around time atur
8. Display the btime, pri, ttime and wtime for each process.
9. Display GANTT chart for the above scheduling
10. Display awat and atur
11. Stop

Program
/* Priority Scheduling - pri.c */

#include <stdio.h>

struct process
{
int pid; int
btime; int pri;
int wtime; int
ttime;
} p[10], temp;
main()
{
int i,j,k,n,ttur,twat;
float awat,atur;
printf("Enter no. of process : "); scanf("%d", &n);
for(i=0; i<n; i++)
{
printf("Burst time for process P%d (in ms) : ", (i+1));
scanf("%d", &p[i].btime);
printf("Priority for process P%d : ", (i+1));
scanf("%d", &p[i].pri);
p[i].pid = i+1;
}
for(i=0; i<n-1; i++)
{
for(j=i+1; j<n; j++)
{
if((p[i].pri > p[j].pri) ||
(p[i].pri == p[j].pri && p[i].pid > p[j].pid) )
{
temp = p[i]; p[i]
= p[j]; p[j] =
temp;
}}}
p[0].wtime = 0; for(i=0;
i<n; i++)
{
p[i+1].wtime = p[i].wtime + p[i].btime; p[i].ttime =
p[i].wtime + p[i].btime;
}
ttur = twat = 0; for(i=0;
i<n; i++)
{
ttur += p[i].ttime; twat +=
p[i].wtime;
}
awat = (float)twat / n; atur = (float)ttur / n;
printf("\n\t Priority Scheduling\n\n"); for(i=0; i<38; i++)
printf("-");
printf("\nProcess B-Time Priority T-Time W-Time\n"); for(i=0; i<38; i++)
printf("-");
for (i=0; i<n; i++)
printf("\nP%-4d\t%4d\t%3d\t%4d\t
%4d",p[i].pid,p[i].btime,p[i].pri,p[i].ttime,p[i].wtime);
printf("\n"); for(i=0; i<38; i++)
printf("-");
printf("\n\nGANTT Chart\n"); printf("-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n|"); for(i=0; i<n; i++)
{
k = p[i].btime/2; for(j=0;
j<k;j++) printf(" ");
printf("P%d",p[i].pid);
for(j=k+1; j<p[i].btime; j++)
printf(" ");
printf("|");
}
printf("\n-");
for(i=0; i<(p[n-1].ttime + 2*n); i++) printf("-");
printf("\n0"); for(i=0; i<n; i++)
{
for(j=0; j<p[i].btime; j++) printf(" ");
printf("%2d",p[i].ttime);
}
printf("\n\nAverage waiting time : %5.2fms", awat);
printf("\nAverage turn around time : %5.2fms\n", atur);}

OUTPUT :
$ gcc pri.c

$ ./a.out
Enter no. of process : 5
Burst time for process P1 (in ms) : 10
Priority for process P1 : 3
Burst time for process P2 (in ms) : 7
Priority for process P2 : 1
Burst time for process P3 (in ms) : 6
Priority for process P3 : 3
Burst time for process P4 (in ms) : 13
Priority for process P4 : 4
Burst time for process P5 (in ms) : 5
Priority for process P5 : 2

Priority Scheduling
---------------------------------------------------------------------
Process B-Time Priority T-Time W-Time
-----------------------------------------------------------------------
P2 7 1 7 0
P5 5 2 12 7
P1 10 3 22 12
P3 6 3 28 22
P4 13 4 41 28
----------------------------------------------------------------------------
GANTT Chart
---------------------------------------------------------------------------------------
| P2 | P5 | P1 | P3 | P4 |
---------------------------------------------------------------------------------------
0 7 12 22 28 41

Average waiting time : 13.80ms


Average turn around time : 22.00ms

Result
Thus waiting time & turnaround time for processes based on Priority scheduling
was computed and the average waiting time was determined.
Ex.No:3d Round Robin Scheduling Algorithm

Aim:

To write a program to implement the Round Robin CPU scheduling Algorithm

Algorithm:

1.START the program

2.Get the number of processors

3.Get the Burst time(BT) of each processors

4.Get the Quantum time(QT)

5.Execute each processor until reach the QT or BT

6.Time of reaching processor’s BT is it’s Turn Around Time(TAT)

7.Time waits to start the execution, is the waiting time(WT) of each processor

8.Calculation of Turn Around Time and Waiting Time

m) tot_TAT = tot_TAT + cur_TAT

n) avg_TAT = tot_TAT/num_of_proc

o) tot_WT = tot_WT + cur_WT

p) avg_WT = tot_WT/num_of_proc

9. Display the result

10. STOP the program

Program: (Round Robin Algorithm)

#include<stdio.h>

#include<conio.>

int TRUE = 0;

int FALSE = -1;

int tbt[30],bt[30],tat[30],n=0,wt[30],qt=0,tqt=0,time=0,lmore,t_tat=0,t_wt=0; void main()

{
int i,j; clrscr();

printf("\nEnter no. of processors:"); scanf("%d",&n);


printf("\nEnterQuantum Time:"); scanf("%d",&qt);

for(i=0;i<n;i++)

printf("\nEnter Burst Time of Processor[%d]:",i+1); scanf("%d",&bt[i]);

tbt[i] = bt[i];

wt[i] = tat[i] = 0;

lmore = TRUE;

while(lmore== TRUE)

lmore= FALSE;

for(i=0;i<n;i++)

if(bt[i] != 0)
wt[i] = wt[i] + (time - tat[i]);

tqt = 1;

while(tqt <= qt && bt[i] !=0)

lmore = TRUE;

bt[i] = bt[i]

-1; tqt++;

time++;

tat[i] = time;

}}}

printf("\nProcessorID\tBurstTime\tTurnAroundTime\tWaitingTime\);

for(i=0;i<n;i++)

printf("Processor%d\t\t%d\t\t%d\t\t%d\n",i+1,tbt[i],tat[i],wt[i]);
t_tat = t_tat + tat[i]; t_wt = t_wt + wt[i];

printf("\nTotal Turn Around Time:%d",t_tat); printf("\nAverage Turn

AroundTime:%d",t_tat/n);

printf("\nTotal Waiting Time:%d",t_wt);

printf("\nAverage Waiting Time:%d",t_wt/n);

getch();

Output: (Round Robin Scheduling Algorithm)

Enter the no of processors : 5

Enter the Quantum time : 6

Enter the Burst time of processor [1]: 21

Enter the Burst time of processor [2]: 18

Enter the Burst time of processor [3]: 12

Enter the Burst time of processor [4]: 30

Enter the Burst time of processor [5]: 15

Processor ID Burst time Turn around time Waiting time

1 21 84 63

2 18 72 54

3 12 48 36

4 30 96 66

5 15 81 66

Result:

Thus the program to implement the Round Robin CPU scheduling Algorithm was

written, executed and the output was verified successfully.


File Allocation Strategies

a) Sequential
b) Indexed
c) Linked

Theory:
Files are normally stored on the disks. So the main problem is how to allocate space
to those files. So that disk space is utilized effectively and files can be accessed quickly.
Three major strategies of allocating disc space are in wide use. Sequential, indexed and
linked.

a Sequential allocation :
In this allocation strategy, each file occupies a set of
contiguously blocks on the disk. This strategy is best suited. For
sequential files. The file allocation table consists of a single entry for
each file. It shows the filenames, staring block of the file and size of
the file. The main problem of this strategy is, it is difficult to find the
contiguous free blocks in the disk and some free blocks could happen
between two files.
b Indexed allocation :
Indexed allocation supports both sequential and direct access
files. Te file indexes are not physically stored as a part of the file
allocation table. Whenever the file size increases, we can easily add
some more blocks to the index. In this strategy, the file allocation table
contains a single entry for each file. The entry consisting of one index
block, the index blocks having the pointers to the other blocks. No
external fragmentation.
c Linked allocation :
It is easy to allocate the files, because allocation is on an
individual block basis. Each block contains a pointer to the next free
block in the chain. Here also the file allocation table consisting of a
single entry for each file. Using this strategy any free block can be
added to a chain very easily. There is a link between one block to
another block, that’s why it is said to be linked allocation. We can
avoid the external fragmentation.
EX.No:4a Sequential File allocation

Aim:
To write a program to implement the sequential file allocation

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. Get the option from the user.
4. For the option1. Do the following.
4.1 Get the file to be created.
4.2 Allocate the continuous memeory for the file
4.3 Display the message that file has been allocated.
4.4 Go to step 3
5. For the option 2. Do the following
5.1 Get the file to be deleted.
5.2 Free up the memory space allocated to the file
5.3 Display the message.
5.4 Go to step 3
6. For the option 3. Do the following
6.1 Display the files that have been allocated.
6.2 Goto step 3
7. For the option 4. Do the following
7.1 Stop the program.

Program:
#include<stdio.h>
#include<conio.h>
#include<process.h>
struct sequence
{
char n[20];
int i;

}s[20];
int create(int);
int del(int);
void display(int);
void main()
{
int x=0,j=0;
clrscr();
while(1)
{
printf("1.creation\n2.delete\n3.display\n4.exit");
printf("\nenter one option");
scanf("%d",&x);
switch(x)
{
case 1: j=create(j);
break;
case 2: j=del(j);
break;
case 3: display(j);
break;
case 4: exit(1);
default : printf("wrong option");
} }}
int create(int j)
{
int m,v;
j++;
w:printf("\nenter the file name:");
scanf("%s",&s[j].n);
m=1;
while(m<j)
{
v=strcmp(s[j].n,s[m].n);
if(v==0)
{
printf("file is already exist\nplease enter another name");
goto w;
}
m++;
}
printf("\nenter field:");
scanf("%d",&s[j].i);
return(j);
}
int del(int j)
{
j--;
return(j);
}
void display(int j)
{
int l;
printf("filename\tfield");
for(l=1;l<=j;l++)
printf("\n%s\t\t%d\n",s[l].n,s[l].i);
}

Output:
1.creation
2.delete
3.display
4.exit
enter one option1
enter the file name:1.c
enter field:1
1.creation
2.delete
3.display
4.exit
enter one option1

enter the file name:2.c

enter field:2
1.creation
2.delete
3.display
4.exit
enter one option3
filename field
1.c 1

2.c 2
1.creation
2.delete
3.display
4.exit
enter one option4

Result :
Thus a program to implement sequential file allocation is implemented and verified using
sample inputs

EX.No:4b Indexed File Allocation


Aim :
To write a program to implement the indexed file allocation.

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. Get the option from the user.
4. For the option1. Do the following.
4.1 Get the file to be created.
4.2 Allocate the avaliable memeory for the file and one the index to all other
indexes is maintained for the file
4.3 Display the message that file has been allocated.
4.4 Go to step 3
5. For the option 2. Do the following
5.1 Get the file to be deleted.
5.2 Free up the memory space allocated to the file
5.3 Display the message.
5.4 Go to step 3
6. For the option 3. Do the following
6.1 Display the files that have been allocated.
6.2 Goto step 3
7. For the option 4. Do the following
7.1 Stop the program.

Source code:
#include<stdio.h>
#include<conio.h>
#include<string.h>
struct file
{
char n[20];
int fld,ind;
}s[20];
int no,i=-1,a,b,f,j=-1,fe,t;
char tem[20];
void create();
void display();
void del();
void main()
{
clrscr();
while(1)
{
printf("\n\nmenu");
printf("\n1.create\n2.display\n3.delete\n4.exit");
printf("enter ur choice:");
scanf("%d",&no);
switch(no)
{
case 1: create();
break;
case 2: display();
break;
case 3: del();
break;
case 4: exit(0);
default: printf("wrong choice");
}
}
}
void create()
{
i++;
printf("\nenter the name of the recoed:");
scanf("%s",&s[i].n);
printf("\nenter the index no:");
scanf("%d",&s[i].ind);
printf("\nenter the field no:");
scanf("%d",&s[i].fld);
j++;
}
void display()
{
for(a=0;a<i;a++)
{
for(b=0;b<i;b++)
{
if(s[b].ind>s[b+1].ind)
{
t=s[b].ind;
s[b].ind=s[b+1].ind;
s[b+1].ind=t;
strcpy(tem,s[b].n);
strcpy(s[b].n,s[b+1].n);
strcpy(s[b+1].n,tem);
t=s[b].fld;
s[b].fld=s[b+1].fld;
s[b+1].fld=t;
}
else
continue;
}
}
printf("\n ---------------------------------");
printf("\n\t Index Recordname FieldNo");
for(i=0;i<=j;i++)
{
printf("\n\t%d\t",s[i].ind);
printf("\t%s",s[i].n);
printf("\t%d",s[i].fld);
}
i--;
printf("\n -----------------------------------\n");
}
void del()
{
int de,index=-1,k=0,l;
if(i!=-1)
{
printf("enter index no to be deleted");
scanf("%d",&de);
index=de;
while(s[k].ind!=de)
{
k++;
printf("\n\t\t\t%d",k);
}
for(l=k;l<=j;l++)
s[l]=s[l+1];
i--;
j--;
printf("\nindex no %d file is deleted",index);
}
}
Output:
menu
1.create
2.display
3.delete
4.exitenter ur choice:1

enter the name of the recoed:a.java

enter the index no:0

enter the field no:1


menu
1.create
2.display
3.delete
4.exitenter ur choice:1

enter the name of the recoed:b.c

enter the index no:1

enter the field no:2

menu
1.create
2.display
3.delete
4.exitenter ur choice:2

---------------------------------
Index Recordname FieldNo
0 a.java 1
1 b.c 2
-----------------------------------

menu
1.create
2.display
3.delete
4.exitenter ur choice:4

Result :
Thus a program to implement indexed file allocation is implemented and verified using
sample inputs
Ex.No:4c
Linked File Allocation

Aim:
To write a program to implement the Linked file allocation.

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. Get the option from the user.
4. For the option1. Do the following.
4.1 Get the file to be created.
4.2 Allocate the avaliable memeory for the file and the pointer of one block is
given to the pointer of the previous blocks.
4.3 Display the message that file has been allocated.
4.4 Go to step 3
5. For the option 2. Do the following
5.1 Get the file to be deleted.
5.2 Free up the memory space allocated to the file
5.3 Display the message.
5.4 Go to step 3
6. For the option 3. Do the following
6.1 Display the files that have been allocated.
6.2 Goto step 3
7. For the option 4. Do the following
7.1 Stop the program.

Source code:
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int bno,flag,next;
}block;
block b[200],b1;
void main()
{
int rnum();
int i,n,s,s1,p[30],r,k[20];
clrscr();
printf("\nEnter number of programs:");
scanf("%d",&n);
printf("\nEnter the memory block request");
for(i=1;i<=n;i++)
{
printf("\nEnter program requirement");
scanf("%d",&p[i]);
}
for(i=1;i<=n;i++)
{
s=rnum();
b[s].bno=0;
b[s].flag=1;
k[i]=0;
r=p[i]-1;
while(r!=0)
{
s1=rnum();
b[s].next=s1;
b[s1].flag=1;
b[s1].bno=0;
s=s1;
r=r-1;
}
b[s1].next=NULL;
}
printf("\n Starting blocks for program");
for(i=1;i<=n;i++)
printf("\n%5d%5d",i,k[i]);
printf("\n allocated blocks");
for(i=1;i<=200;i++)
{
if(b[i].flag==1)
printf("\n%5d%5d",b[i].bno,b[i].next);
}
}
int rnum()
{
int k,i;
for(i=1;i<=200;i++)
{
k=rand()%200;
if(b[i].flag!=1)
break;
}

return k;
}

Output:
Enter number of programs:2

Enter the memory block request


Enter program requirement3

Enter program requirement4

Starting blocks for program


1 0
2 0
allocated blocks
0 117
0 56
0 195
0 182
0 130
0 0
0 0

Result :
Thus a program to implement Linked file allocation is implemented and verified using
sample inputs
Ex.No:5 Producer-Consumer problems Using Semaphores

Aim
To synchronize producer and consumer processes using semaphore.

Algorithm
1. Create a shared memory segment BUFSIZE of size 1 and attach it.
2. Obtain semaphore id for variables empty, mutex and full using semget function.
3. Create semaphore for empty, mutex and full as follows:
a. Declare semun, a union of specific commands.
b. The initial values are: 1 for mutex, N for empty and 0 for full
c. Use semctl function with SETVAL command
4. Create a child process using fork system call.
a. Make the parent process to be the producer
b. Make the child process to the consumer
5. The producer produces 5 items as follows:
a. Call wait operation on semaphores empty and mutex using semop function.
b. Gain access to buffer and produce data for consumption
c. Call signal operation on semaphores mutex and full using semop function.
6. The consumer consumes 5 items as follows:
a. Call wait operation on semaphores full and mutex using semop function.
b. Gain access to buffer and consume the available data.
c. Call signal operation on semaphores mutex and empty using semop function.
7. Remove shared memory from the system using shmctl with IPC_RMID argument
8. Stop

Program
/* Producer-Consumer problem using semaphore – pcsem.c */

#include <stdio.h> #include


<stdlib.h> #include <sys/types.h>
#include <sys/ipc.h> #include
<sys/shm.h> #include <sys/sem.h>
#define N 5 #define BUFSIZE
1 #define PERMS 0666
int *buffer;
int nextp = 0, nextc = 0;
int mutex, full, empty; /* semaphore variables */
void producer()
{
int data; if(nextp == N)
nextp = 0;
printf("Enter data for producer to produce : "); scanf("%d",(buffer +
nextp));
nextp++;
}
void consumer()
{
int g; if(nextc == N)
nextc = 0;
g = *(buffer + nextc++); printf("\nConsumer consumes data
%d", g);
}
void sem_op(int id, int value)
{
struct sembuf op; int v;
op.sem_num = 0; op.sem_op =
value; op.sem_flg = SEM_UNDO;
if((v = semop(id, &op, 1)) < 0)
printf("\nError executing semop instruction");
}
void sem_create(int semid, int initval)
{
int semval; union
semun
{
int val;
struct semid_ds *buf; unsigned short
*array;
} s;
s.val = initval;
if((semval = semctl(semid, 0, SETVAL, s)) < 0) printf("\nError in
executing semctl");
}
void sem_wait(int id)
{
int value = -1; sem_op(id,
value);
}
void sem_signal(int id)
{
int value = 1; sem_op(id,
value);
}
main()
{
int shmid, i; pid_t pid;
if((shmid = shmget(1000, BUFSIZE, IPC_CREAT|PERMS)) < 0)
{
printf("\nUnable to create shared memory"); return;
}
if((buffer = (int*)shmat(shmid, (char*)0, 0)) == (int*)-1)
{
printf("\nShared memory allocation error\n"); exit(1);
}
if((mutex = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create mutex semaphore"); exit(1);
}
if((empty = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create empty semaphore"); exit(1);
}
if((full = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
printf("\nCan't create full semaphore"); exit(1);
}
sem_create(mutex, 1);
sem_create(empty, N);
sem_create(full, 0);
if((pid = fork()) < 0)
{
printf("\nError in process creation"); exit(1);
}
else if(pid > 0)
{
for(i=0; i<N; i++)
{
sem_wait(empty);
sem_wait(mutex); producer();
sem_signal(mutex);
sem_signal(full);
}
}
else if(pid == 0)
{
for(i=0; i<N; i++)
{
sem_wait(full);
sem_wait(mutex); consumer();
sem_signal(mutex);
sem_signal(empty);
}
printf("\n");
}
}

Output
$ gcc pcsem.c

$ ./a.out
Enter data for producer to produce : 5
Enter data for producer to produce : 8
Consumer consumes data 5
Enter data for producer to produce : 4
Consumer consumes data 8
Enter data for producer to produce : 2
Consumer consumes data 4
Enter data for producer to produce : 9
Consumer consumes data 2
Consumer consumes data 9

Result
Thus synchronization between producer and consumer process for access to a shared
memory segment is implemented.

18
Ex.No:6 File Organization Techniques

Theory:
The directory contains information about the files, including attributes, location and
ownership. Sometimes the directories consisting of subdirectories also. The directory is itself a file,
owned by the o.s and accessible by various file management routines.

a)Single Level Directories: It is the simplest of all directory structures, in this the directory system
having only one directory, it consisting of the all files. Sometimes it is said to be root directory. The
following dig. Shows single level directory that contains four files (A, B, C, D).

Root
Directory

A B C D

It has the simplicity and ability to locate files quickly. it is not used in the multi-user system, it is used
on small embedded system.

b) Two Level Directory: The problem in single level directory is different users may be accidentally
using the same names for their files. To avoid this problem, each user need a private directory. In this
way names chosen by one user don’t interface with names chosen by a different user. The following
dig 2-level directory

Root
Directory

User User User


1 2 3
Here root directory is the first level directory it consisting of entries of user directory. User1, User2,
User3 are the user levels of directories. A, B, C are the files

c) Hierarchical Directory: The two level directories eliminate name conflicts among users but it is
not satisfactory for users but it is not satisfactory for users with a large no of files. To avoid this, create
the subdirectory and load the same type of the files into the subdirectory. So, in this method each can
have as many directories are needed.
Root
Directory

User 1 User 2 User 3

Sub Directory A B Sub Directory

Sub –sub Sub-sub Sub –sub Sub –sub


Directory Directory Directory Directory

A B C D
This directory structure looks like tree, that’s why it is also said to be tree-level directory
structure

d) General graph Directory: When we add links to an existing tree structured directory, the
tree structure is destroyed, resulting in a simple graph structure. This structure is used to
traversing is easy and file sharing also possible.

Root
Directory

User 1 User 2 User 3

Sub Directory A B Sub Directory

Sub –sub Sub-sub Sub –sub Sub –sub


Directory Directory Directory Directory

A B C D
Ex.No:6a Single Level Directory

Aim:
To write a program to implement a single level directory structure.

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. All the users share the same root directory.
4. Get the number of files from the user.
5. Append all the files under the root directory.
6. Diplay the tree structure showing the root as Directory and all files as its children
7. Stop the program

Source Code:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<graphics.h>
void main()
{
int gd=DETECT,gm,count,i,j,mid,cir_x;
char fname[10][20];
clrscr();
initgraph(&gd,&gm,"c:\\tc\\bgi");
cleardevice();
setbkcolor(GREEN);
puts("Enter no of files do u have?");
scanf("%d",&count);
for(i=0;i<count;i++)
{
cleardevice();
setbkcolor(GREEN);
printf("Enter file %d name",i+1);
scanf("%s",fname[i]);
setfillstyle(1,MAGENTA);
mid=640/count;
cir_x=mid/3;
bar3d(270,100,370,150,0,0);
settextstyle(2,0,4);
settextjustify(1,1);
outtextxy(320,125,"Root Directory");
setcolor(BLUE);
for(j=0;j<=i;j++,cir_x+=mid)
{
line(320,150,cir_x,250);
fillellipse(cir_x,250,30,30);
outtextxy(cir_x,250,fname[j]);
}
getch();
}}
Output:
Enter no of files do u have?
3

Enter file 1 name: 1.c

Root Directory

1.c

Enter File 2 name: 2.c

Root Directory

1.c
2.c

Enter File 3 name : 3.c

Root Directory

1.c 2.c 3.c

Result:
Thus a program to implement the single level directory is implemented, verified using
sample inputs
Ex.No:6b Two Level Directory

Aim:
To write a program to implement the two level directory structure

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. Users can have a directory for them.
4. Get the Directories and the files under each directory from the user.
5. Append all the Directories under the root directory.
6. Append files under each directory.
7. Display the tree structure with root as a main directory and sub directories as a
Children and the files as children for those sub directories.
8. Stop the program

File name: TLD.c


Source Code:
#include<stdio.h>
#include<graphics.h>
struct tree_element
{
char name[20];
int x,y,ftype,lx,rx,nc,level;
struct tree_element *link[5];
};
typedef struct tree_element node;
void main()
{
int gd=DETECT,gm;
node *root;
root=NULL;
clrscr();
create(&root,0,"null",0,639,320);
clrscr();
initgraph(&gd,&gm,"c:\\tc\\bgi");
display(root);
getch();
closegraph();
}
create(node **root,int lev,char *dname,int lx,int rx,int x)
{
int i,gap;
if(*root==NULL)
{
(*root)=(node*)malloc(sizeof(node));
printf("enter name of dir/file(under %s):",dname);
fflush(stdin);
gets((*root)->name);
if(lev==0||lev==1)
(*root)->ftype=1;
else
(*root)->ftype=2;
(*root)->level=lev;
(*root)->y=50+lev*50;
(*root)->x=x;
(*root)->lx=lx;
(*root)->rx=rx;
for(i=0;i<5;i++)
(*root)->link[i]=NULL;
if((*root)->ftype==1)
{
if(lev==0||lev==1)
{
if((*root)->level==0)
printf("How many users");
else
printf("hoe many files");
printf("(for%s):",(*root)->name);
scanf("%d",&(*root)->nc);
}
else
(*root)->nc=0;
if((*root)->nc==0)
gap=rx-lx;
else
gap=(rx-lx)/(*root)->nc;
for(i=0;i<(*root)->nc;i++)
create(&((*root)->link[i]),lev+1,
(*root)->name,lx+gap*i,lx+gap*i+gap,lx+gap*i+gap/2);
}
else
(*root)->nc=0;
}
}
display(node *root)
{
int i;
settextstyle(2,0,4);
settextjustify(1,1);
setfillstyle(1,BLUE);
setcolor(14);
if(root!=NULL)
{
for(i=0;i<root->nc;i++)
{
line(root->x,root->y,root->link[i]->x,root->link[i]->y);
}
if(root->ftype==1)
bar3d(root->x-20,root->y-10,root->x+20,root->y+10,0,0);
else
fillellipse(root->x,root->y,20,20);
outtextxy(root->x,root->y,root->name);
for(i=0;i<root->nc;i++)
{
display(root->link[i]);
}
} }
Output:
enter name of dir/file(under null):sld
How many users(forsld):2
enter name of dir/file(under sld):tld
hoe many files(fortld):2
enter name of dir/file(under tld):hir
enter name of dir/file(under tld):dag
enter name of dir/file(under sld):bin
hoe many files(forbin):2
enter name of dir/file(under bin):exe
enter name of dir/file(under bin):obj

SLD

Tld
bin

obj
hir dag exe

Result:
Thus a program to implement the two level directories is implemented, verified using
sample inputs
Ex.No:6c Hierarchical Directory

Aim:
To write a program to implement the single hierarchical directory

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. The user can have a Subdirectory for them
4. Get the Directories and the files under each directory from the user.
5. Append all the Directories under the root directory.
6. Append Sub Directories under each directory.
7. Append the files to the Directories.
8. Display the tree structure with root as a main directory and sub directories as a
Children and the files as children for those sub directories.
9. Stop the program

Source Code:
#include<stdio.h>
#include<graphics.h>
struct tree_element
{
char name[20];
int x,y,ftype,lx,rx,nc,level;
struct tree_element *link[5];
};
typedef struct tree_element node;
void main()
{
int gd=DETECT,gm;
node *root;
root=NULL;
clrscr();
create(&root,0,"root",0,639,320);
clrscr();
initgraph(&gd,&gm,"c:\\tc\\BGI");
display(root);
getch();
closegraph();
}
create(node **root,int lev,char *dname,int lx,int rx,int x)
{
int i,gap;
if(*root==NULL)
{
(*root)=(node *)malloc(sizeof(node));
printf("Enter name of dir/file(under %s) : ",dname);
fflush(stdin);
gets((*root)->name);
printf("enter 1 for Dir/2 for file :");
scanf("%d",&(*root)->ftype);
(*root)->level=lev;
(*root)->y=50+lev*50;
(*root)->x=x;
(*root)->lx=lx;
(*root)->rx=rx;
for(i=0;i<5;i++)
(*root)->link[i]=NULL;
if((*root)->ftype==1)
{
printf("No of sub directories/files(for %s):",(*root)->name);
scanf("%d",&(*root)->nc);
if((*root)->nc==0)
gap=rx-lx;
else
gap=(rx-lx)/(*root)->nc;
for(i=0;i<(*root)->nc;i++)
create(&((*root)->link[i]),lev+1,
(*root)->name,lx+gap*i,lx+gap*i+gap,lx+gap*i+gap/2);
}
else
(*root)->nc=0;
}
}
display(node *root)
{
int i;
settextstyle(2,0,4);
settextjustify(1,1);
setfillstyle(1,BLUE);
setcolor(14);
if(root !=NULL)
{
for(i=0;i<root->nc;i++)
{
line(root->x,root->y,root->link[i]->x,root->link[i]->y);
}
if(root->ftype==1)
bar3d(root->x-20,root->y-10,root->x+20,root->y+10,0,0);
else
fillellipse(root->x,root->y,20,20);
outtextxy(root->x,root->y,root->name);
for(i=0;i<root->nc;i++)
{
display(root->link[i]);
} } }

Output:
Enter Name of dir/file (under root): ROOT
Enter 1 for Dir / 2 For File : 1
No of subdirectories / files (for ROOT) :2
Enter Name of dir/file (under ROOT): USER 1
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for USER 1): 1
Enter Name of dir/file (under USER 1):SUBDIR
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for SUBDIR): 2
Enter Name of dir/file (under USER 1):JAVA
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for JAVA): 0
Enter Name of dir/file (under SUBDIR):VB
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for VB): 0
Enter Name of dir/file (under ROOT):USER2
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for USER2): 2
Enter Name of dir/file (under ROOT):A
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under USER2):SUBDIR 2
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for SUBDIR 2): 2
Enter Name of dir/file (under SUBDIR2):PPL
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for PPL): 2
Enter Name of dir/file (under PPL):B
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under PPL):C
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under SUBDIR):AI
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for AI): 2
Enter Name of dir/file (under AI):D
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under AI):E
Enter 1 for Dir /2 for file:2

Output: ROOT
USER 1 USER 2

SUBDIR1

A SUBDIR2

JAVA
VB

PPL AL

B C E
D

Result:
Thus a program to implement Hierarchical directory is implemented, verified using
sample inputs
Ex.No:6d DAG Directory

Aim:
To write a program to implement a DAG Directory structure

Algorithm:

1. Start the program


2. Initialize all the necessary variables.
3. The user can have a Subdirectory and that sub directory can be children for two
directory.
4. Get the Directories and the files under each directory from the user.
5. Append all the Directories under the root directory.
6. Append Sub Directories under each directory.
7. Append the files to the Directories.
8. Display the tree structure with root as a main directory and sub directories as a
Children and the files as children for those sub directories.
9. Stop the program

Source Code:
#include<stdio.h>
#include<conio.h>
#include<graphics.h>
#include<string.h>
struct tree_element
{
char name[20];
int x,y,ftype,lx,rx,nc,level;
struct tree_element *link[5];
};
typedef struct tree_element node;
typedef struct
{
char from[20];
char to[20];
}link;
link L[10];
int nofl;
node * root;
void main()
{
int gd=DETECT,gm;
root=NULL;
clrscr();
create(&root,0,"root",0,639,320);
read_links();
clrscr();
initgraph(&gd,&gm,"c:\\tc\\BGI");
draw_link_lines();
display(root);
getch();
closegraph();
}
read_links()
{
int i;
printf("how many links");
scanf("%d",&nofl);
for(i=0;i<nofl;i++)
{
printf("File/dir:");
fflush(stdin);
gets(L[i].from);
printf("user name:");
fflush(stdin);
gets(L[i].to);
}
}
draw_link_lines()
{
int i,x1,y1,x2,y2;
for(i=0;i<nofl;i++)
{
search(root,L[i].from,&x1,&y1);
search(root,L[i].to,&x2,&y2);
setcolor(LIGHTGREEN);
setlinestyle(3,0,1);
line(x1,y1,x2,y2);
setcolor(YELLOW);
setlinestyle(0,0,1);
}
}
search(node *root,char *s,int *x,int *y)
{
int i;
if(root!=NULL)
{
if(strcmpi(root->name,s)==0)
{
*x=root->x;
*y=root->y;
return;
}
else
{
for(i=0;i<root->nc;i++)
search(root->link[i],s,x,y);
}
}
}
create(node **root,int lev,char *dname,int lx,int rx,int x)
{
int i,gap;
if(*root==NULL)
{
(*root)=(node *)malloc(sizeof(node));
printf("enter name of dir/file(under %s):",dname);
fflush(stdin);
gets((*root)->name);
printf("enter 1 for dir/ 2 for file:");
scanf("%d",&(*root)->ftype);
(*root)->level=lev;
(*root)->y=50+lev*50;
(*root)->x=x;
(*root)->lx=lx;
(*root)->rx=rx;
for(i=0;i<5;i++)
(*root)->link[i]=NULL;
if((*root)->ftype==1)
{
printf("no of sub directories /files (for %s):",(*root)->name);
scanf("%d",&(*root)->nc);
if((*root)->nc==0)
gap=rx-lx;
else
gap=(rx-lx)/(*root)->nc;
for(i=0;i<(*root)->nc;i++)
create( & ( (*root)->link[i] ) , lev+1 ,
(*root)->name,lx+gap*i,lx+gap*i+gap,lx+gap*i+gap/2);
}
else
(*root)->nc=0;
}
}
/* displays the constructed tree in graphics mode */
display(node *root)
{
int i;
settextstyle(2,0,4);
settextjustify(1,1);
setfillstyle(1,BLUE);
setcolor(14);
if(root !=NULL)
{
for(i=0;i<root->nc;i++)
{
line(root->x,root->y,root->link[i]->x,root->link[i]->y);

}
if(root->ftype==1)
bar3d(root->x-20,root->y-10,root->x+20,root->y+10,0,0);
else
fillellipse(root->x,root->y,20,20);
outtextxy(root->x,root->y,root->name);
for(i=0;i<root->nc;i++)
{
display(root->link[i]);
}}}
Output:

Enter Name of dir/file (under root): ROOT


Enter 1 for Dir / 2 For File : 1
No of subdirectories / files (for ROOT) :2
Enter Name of dir/file (under ROOT): USER 1
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for USER 1): 2
Enter Name of dir/file (under USER1): VB
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for VB): 2
Enter Name of dir/file (under VB): A
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under VB): B
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under USER1): C
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under ROOT): USER2
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for USER2): 1
Enter Name of dir/file (under USER2):JAVA
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for JAVA):2
Enter Name of dir/file (under JAVA):D
Enter 1 for Dir /2 for file:2
Enter Name of dir/file (under JAVA):HTML
Enter 1 for Dir /2 for file:1
No of subdirectories /files (for HTML):0
How many links:2
File/Dir: B
User Name: USER 2
File/Dir: HTML
User Name: USER1

Result:
Thus a program to implement a DAG directory is implemented, and verified
using the sample inputs.

Ex.No:7 &8 Banker's Algorithm for Deadlock Detection and Avoidance

Aim:
To implement deadlock avoidance & Prevention by using Banker’s Algorithm.
Deadlock avoidance & Dead Lock Prevention

Banker’s Algorithm:
When a new process enters a system, it must declare the maximum number of
instances of each resource type it needed. This number may exceed the total number of
resources in the system. When the user request a set of resources, the system must
determine whether the allocation of each resources will leave the system in safe state. If
it will the resources are allocation; otherwise the process must wait until some other
process release the resources.

Data structures
• N-Number of process, m-number of resource types.
• Available: Available[j]=k, k – instance of resource type Rj is available.
• Max: If max[i, j]=k, Pi may request at most k instances resource Rj.
• Allocation: If Allocation [i, j]=k, Pi allocated to k instances of resource Rj
• Need: If Need[I, j]=k, Pi may need k more instances of resource type Rj,
Need[I, j]=Max[I, j]-Allocation[I, j];
Safety Algorithm
1. Work and Finish be the vector of length m and n respectively, Work=Available
and Finish[i] =False.
2. Find an i such that both
• Finish[i] =False
• Need<=Work
If no such I exists go to step 4.
3. work=work+Allocation, Finish[i] =True;
4. if Finish[1]=True for all I, then the system is in safe state.

Resource request algorithm

Let Request i be request vector for the process Pi, If request i=[j]=k, then
process Pi wants k instances of resource type Rj.
1. if Request<=Need I go to step 2. Otherwise raise an error condition.
2. if Request<=Available go to step 3. Otherwise Pi must since the resources are
available.
3. Have the system pretend to have allocated the requested resources to process Pi
by modifying the state as follows;
Available=Available-Request I;
Allocation I =Allocation+Request I;
Need i=Need i-Request I;
If the resulting resource allocation state is safe, the transaction is completed and process
Pi is allocated its resources. However if the state is unsafe, the Pi must wait for Request
i and the old resource-allocation state is restored.

ALGORITHM:
1. Start the program.
2. Get the values of resources and processes.
3. Get the avail value.
4. After allocation find the need value.
5. Check whether it’s possible to allocate.
6. If it is possible then the system is in safe state.
7. Else system is not in safety state.
8. If the new request comes then check that the system is in safety. or not if we
allow the request.
9. Stop the program.

* BANKER’S ALGORITHM */
#include<stdio.h>
#include<conio.h>
struct da
{
int max[10],a1[10],need[10],before[10],after[10];
}p[10];
void main()
{
int i,j,k,l,r,n,tot[10],av[10],cn=0,cz=0,temp=0,c=0;
clrscr();
printf("\n ENTER THE NO. OF PROCESSES:");
scanf("%d",&n);
printf("\n ENTER THE NO. OF RESOURCES:");
scanf("%d",&r);
for(i=0;i<n;i++)
{
printf("PROCESS %d \n",i+1);
for(j=0;j<r;j++)
{
printf("MAXIMUM VALUE FOR RESOURCE %d:",j+1);
scanf("%d",&p[i].max[j]);
}
for(j=0;j<r;j++)
{
printf("ALLOCATED FROM RESOURCE %d:",j+1);
scanf("%d",&p[i].a1[j]);
p[i].need[j]=p[i].max[j]-p[i].a1[j];
}
}
for(i=0;i<r;i++)
{
printf("ENTER TOTAL VALUE OF RESOURCE %d:",i+1);
scanf("%d",&tot[i]);
}
for(i=0;i<r;i++)
{
for(j=0;j<n;j++)
temp=temp+p[j].a1[i];
av[i]=tot[i]-temp;
temp=0;
}
printf("\n\t RESOURCES ALLOCATED NEEDED TOTAL AVAIL");
for(i=0;i<n;i++)
{
printf("\n P%d \t",i+1);
for(j=0;j<r;j++)
printf("%d",p[i].max[j]);
printf("\t");
for(j=0;j<r;j++)
printf("%d",p[i].a1[j]);
printf("\t");
for(j=0;j<r;j++)
printf("%d",p[i].need[j]);
printf("\t");
for(j=0;j<r;j++)
{
if(i==0)
printf("%d",tot[j]);
}
printf(" ");
for(j=0;j<r;j++)
{
if(i==0)
printf("%d",av[j]);
}
}
printf("\n\n\t AVAIL BEFORE\T AVAIL AFTER ");
for(l=0;l<n;l++)
{
for(i=0;i<n;i++)
{
for(j=0;j<r;j++)
{
if(p[i].need[j] >av[j])
cn++;
if(p[i].max[j]==0)
cz++;
}
if(cn==0 && cz!=r)
{
for(j=0;j<r;j++)
{
p[i].before[j]=av[j]-p[i].need[j];
p[i].after[j]=p[i].before[j]+p[i].max[j];
av[j]=p[i].after[j];
p[i].max[j]=0;
}
printf("\n P %d \t",i+1);
for(j=0;j<r;j++)
printf("%d",p[i].before[j]);
printf("\t");
for(j=0;j<r;j++)
printf("%d",p[i].after[j]);
cn=0;
cz=0;
c++;
break;
}
else
{
cn=0;cz=0;
}
}
}
if(c==n)
printf("\n THE ABOVE SEQUENCE IS A SAFE SEQUENCE");
else
printf("\n DEADLOCK OCCURED");
getch();
}

Output:

//TEST CASE 1:

ENTER THE NO. OF PROCESSES:4

ENTER THE NO. OF RESOURCES:3


PROCESS 1
MAXIMUM VALUE FOR RESOURCE 1:3
MAXIMUM VALUE FOR RESOURCE 2:2
MAXIMUM VALUE FOR RESOURCE 3:2
ALLOCATED FROM RESOURCE 1:1
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:0
PROCESS 2
MAXIMUM VALUE FOR RESOURCE 1:6
MAXIMUM VALUE FOR RESOURCE 2:1
MAXIMUM VALUE FOR RESOURCE 3:3
ALLOCATED FROM RESOURCE 1:5
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:1
PROCESS 3
MAXIMUM VALUE FOR RESOURCE 1:3
MAXIMUM VALUE FOR RESOURCE 2:1
MAXIMUM VALUE FOR RESOURCE 3:4
ALLOCATED FROM RESOURCE 1:2
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:1
PROCESS 4
MAXIMUM VALUE FOR RESOURCE 1:4
MAXIMUM VALUE FOR RESOURCE 2:2
MAXIMUM VALUE FOR RESOURCE 3:2
ALLOCATED FROM RESOURCE 1:0
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:2
ENTER TOTAL VALUE OF RESOURCE 1:9
ENTER TOTAL VALUE OF RESOURCE 2:3
ENTER TOTAL VALUE OF RESOURCE 3:6

RESOURCES ALLOCATED NEEDED TOTAL AVAIL


P1 322 100 222 936 112
P2 613 511 102
P3 314 211 103
P4 422 002 420
AVAIL BEFORE AVAIL AFTER
P2 010 623
P1 401 723
P3 620 934
P4 514 936

THE ABOVE SEQUENCE IS A SAFE SEQUENCE

//TEST CASE:2

ENTER THE NO. OF PROCESSES:4

ENTER THE NO. OF RESOURCES:3


PROCESS 1
MAXIMUM VALUE FOR RESOURCE 1:3
MAXIMUM VALUE FOR RESOURCE 2:2
MAXIMUM VALUE FOR RESOURCE 3:2
ALLOCATED FROM RESOURCE 1:1
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:1
PROCESS 2
MAXIMUM VALUE FOR RESOURCE 1:6
MAXIMUM VALUE FOR RESOURCE 2:1
MAXIMUM VALUE FOR RESOURCE 3:3
ALLOCATED FROM RESOURCE 1:5
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:1
PROCESS 3
MAXIMUM VALUE FOR RESOURCE 1:3
MAXIMUM VALUE FOR RESOURCE 2:1
MAXIMUM VALUE FOR RESOURCE 3:4
ALLOCATED FROM RESOURCE 1:2
ALLOCATED FROM RESOURCE 2:1
ALLOCATED FROM RESOURCE 3:2
PROCESS 4
MAXIMUM VALUE FOR RESOURCE 1:4
MAXIMUM VALUE FOR RESOURCE 2:2
MAXIMUM VALUE FOR RESOURCE 3:2
ALLOCATED FROM RESOURCE 1:0
ALLOCATED FROM RESOURCE 2:0
ALLOCATED FROM RESOURCE 3:2
ENTER TOTAL VALUE OF RESOURCE 1:9
ENTER TOTAL VALUE OF RESOURCE 2:3
ENTER TOTAL VALUE OF RESOURCE 3:6

RESOURCES ALLOCATED NEEDED TOTAL AVAIL


P1 322 101 221 936 110
P2 613 511 102
P3 314 212 102
P4 422 002 420

AVAIL BEFORE AVAIL AFTER


DEADLOCK OCCURED

Result:
Thus a program to implement the Banker’s algorithm for deadlock avoidance
and prevention is implemented and verified using sample inputs.

Ex.No:9a FIFO Page Replacement

Aim
To implement demand paging for a reference string using FIFO method.

Algorithm
1. Get length of the reference string, say l.
2. Get reference string and store it in an array, say rs.
3. Get number of frames, say nf.
4. Initalize frame array upto length nf to -1.
5. Initialize position of the oldest page, say j to 0.
6. Initialize no. of page faults, say count to 0.
7. For each page in reference string in the given order, examine:
a. Check whether page exist in the frame array
b. If it does not exist then
i. Replace page in position j.
ii. Compute page replacement position as (j+1) modulus nf.
iii. Increment count by 1.
iv. Display pages in frame array.
8. Print count.
9. Stop

Program
/* FIFO page replacement - fifopr.c */

#include <stdio.h>

main()
{
int i,j,l,rs[50],frame[10],nf,k,avail,count=0;
printf("Enter length of ref. string : "); scanf("%d", &l);
printf("Enter reference string :\n"); for(i=1; i<=l; i+
+)
scanf("%d", &rs[i]); printf("Enter number of
frames : "); scanf("%d", &nf);
for(i=0; i<nf; i++)
frame[i] = -1;
j = 0;
printf("\nRef. str Page frames"); for(i=1; i<=l;
i++)
{
printf("\n%4d\t", rs[i]); avail = 0;
for(k=0; k<nf; k++) if(frame[k]
== rs[i])
avail = 1;
if(avail == 0)
{
frame[j] = rs[i]; j =
(j+1) % nf; count++;
for(k=0; k<nf; k++) printf("%4d",
frame[k]);
}
}
printf("\n\nTotal no. of page faults : %d\n",count);
}

Output

$ gcc fifopr.c

$ ./a.out
Enter length of ref. string : 20 Enter
reference string :
1 2 3 4 2 1 5 6 2 1 2 3 7 6 3 2 1 2 3 6 Enter number of
frames : 5
Ref. str Page frames
1 1 -1 -1 -1 -1
2 1 2 -1 -1 -1
3 1 2 3 -1 -1
4 1 2 3 4 -1
2
1
5 1 2 3 4 5
6 6 2 3 4 5
2
1 6 1 3 4 5
2 6 1 2 4 5
3 6 1 2 3 5
7 6 1 2 3 7
6
3
2
1
2
3
6
Total no. of page faults: 10
Result
Thus page replacement was implemented using FIFO algorithm.

Exp# 9b LFU Page Replacement

Aim
To implement demand paging for a reference string using LFU method.

Algorithm
1. Get length of the reference string, say len.
2. Get reference string and store it in an array, say rs.
3. Get number of frames, say nf.
4. Create access array to store counter that indicates a measure of recent usage.
5. Create a function arrmin that returns position of minimum of the given array.
6. Initalize frame array upto length nf to -1.
7. Initialize position of the page replacement, say j to 0.
8. Initialize freq to 0 to track page frequency
9. Initialize no. of page faults, say count to 0.
10. For each page in reference string in the given order, examine:
a. Check whether page exist in the frame array.
b. If page exist in memory then
i. Store incremented freq for that page position in access array.
c. If page does not exist in memory then
i. Check for any empty frames.
ii. If there is an empty frame,
Assign that frame to the page
Store incremented freq for that page position in access
array. Increment count.
iii. If there is no free frame then
Determine page to be replaced using arrmin function.
Store incremented freq for that page position in access
array. Increment count.
iv. Display pages in frame array.
11. Print count.
12. Stop
Program
/* LFU page replacement - lfupr.c */

#include<stdio.h>
int arrmin(int[],int);

main()
{
int i,j,len,rs[50],frame[10],nf,k,avail,count=0;
int access[10],freq=0,dm;
printf("length of reference string:");
scanf("%d",&len);
printf("enter reference string:\n");
for(i=1;i<=len;i++)
scanf("%d",&rs[i]);
printf("enter no of frames:");
scanf("%d",&nf);
for(i=0;i<nf;i++)
frame[i]=-1;
j=0;
printf("\n ref.str page frames");
for(i=1;i<=len;i++)
{
printf("\n%4d\t",rs[i]);
avail=0;
for(k=0;k<nf;k++)
{
if(frame[k]==rs[i])
{
avail=1;
access[k]=++freq;
break;
}
}
if(avail==0)
{
dm=0;
for(k=0;k<nf;k++)
{
if(frame[k]==-1)
{
dm=k;
break;
}}
if(dm!=0)
{
k=dm;
frame[k]=rs[i];
access[k]=++freq;
count++;
}
else
{
j=arrmin(access,nf);
frame[j]=rs[i];
access[j]=++freq;
count++;
}
for(k=0;k<nf;k++)
printf("%4d",frame[k]);
}
}
printf("\n\n total no of page faults:%d\n",count);
}
int arrmin(int a[],int n)
{
int i,min=a[0];
for(i=1;i<n;i++)
if(min>a[i])
min=a[i];
for(i=0;i<n;i++)
if(min==a[i])
return i ;
}
Output
$ gcc lfupr.c

$ ./a.out
Length of Reference string : 20 Enter
reference string :
123421562123763 2 1 2 3 6 Enter no. of
frames : 5
Ref. str Page frames
1 1 -1 -1 -1 -1
2 1 2 -1 -1 -1
3 1 2 3 -1 -1
4 1 2 3 4 -1
2
1
5 1 2 3 4 5
6 1 2 6 4 5
2
1
2
3 1 2 6 3 5
7 1 2 6 3 7
6
3
2
1
2
3
6
Total no. of page faults : 8
Result
Thus page replacement was implemented using LFU algorithm.
Ex.No:9c LRU PAGE REPLACEMENT

Aim:
To write a program to implement a LRU page replacement
Algorithm:

1. Get length of the reference string, say len.


2. Get reference string and store it in an array, say rs.
3. Get number of frames, say nf.
4. Create access array to store order that indicates a measure of recent usage.
5. Initalize frame array upto length nf to -1.
6. Initialize position of the page replacement, say j to 0.
7. Initialize freq to 0 to track page frequency
8. Initialize no. of page faults, say count to 0.
9. For each page in reference string in the given order, examine:
a. Check whether page exist in the frame array.
b. If page exist in memory then
i. Store page number in access array.
c. If page does not exist in memory then
i. Check for any empty frames.
ii. If there is an empty frame,
Assign that frame to the page
Also include the page in the access array
iii. If there is no free frame then
Determine page is in the first position of the access array.
(i.e)page that is least recently used.
iv. Display pages in frame array.
10. Print count.
11. Stop

FileName: LRU.c
Source code:
#include<stdio.h>
main()
{
int q[20],p[50],c=0,c1,d,f,i,j,k=0,n,r,t,b[20],c2[20];
clrscr();
printf("Enter no of pages:");
scanf("%d",&n);
printf("Enter the reference string:");
for(i=0;i<n;i++) scanf("%d",&p[i]);
printf("Enter no of frames:");
scanf("%d",&f);
q[k]=p[k]; printf("\n\t%d\n",q[k]);
c++;
k++;
for(i=1;i<n;i++)
{
c1=0;
for(j=0;j<f;j++)
{
if(p[i]!=q[j])
c1++;
}
if(c1==f)
{
c++;
if(k<f)
{
q[k]=p[i];
k++;
for(j=0;j<k;j++)
printf("\t%d",q[j]);
printf("\n");
}
else
{
for(r=0;r<f;r++)
{
c2[r]=0;
for(j=i-1;j<n;j--)
{
if(q[r]!=p[j])
c2[r]++;
else
break;
}
}
for(r=0;r<f;r++)
b[r]=c2[r];
for(r=0;r<f;r++)
{
for(j=r;j<f;j++)
{
if(b[r]<b[j])
{
t=b[r];
b[r]=b[j];
b[j]=t;
}
}
}
for(r=0;r<f;r++)
{
if(c2[r]==b[0])
q[r]=p[i];
printf("\t%d",q[r]);
}
printf("\n");
}
}
} printf("\nThe no of page faults is %d",c);
getch(); return 0;
}

Output:

Result:
Thus a program to implement the LRU page replacement algorithm is
written,and verified using sample inputs.
INTERPROCESS COMMUNICATION

• Inter-Process communication (IPC), is the mechanism whereby one process can


communicate with another process, i.e exchange data.
• IPC in linux can be implemented using pipe, shared memory, message queue,
semaphore, signal or sockets.
Pipe
• Pipes are unidirectional byte streams which connect the standard output from
one process into the standard input of another process.
• A pipe is created using the system call pipe that returns a pair of file
descriptors. The descriptor pfd[0] is used for reading and pfd[1] is used for
writing.
• Can be used only between parent and child processes.

Shared memory
• Two or more processes share a single chunk of memory to communicate
randomly.
• Semaphores are generally used to avoid race condition amongst
processes. Fastest amongst all IPCs as it does not require any system call.
• It avoids copying data unnecessarily.

Message Queue
• A message queue is a linked list of messages stored within the
kernel A message queue is identified by a unique identifier
• Every message has a positive long integer type field, a non-negative length, and
the actual data bytes.
• The messages need not be fetched on FCFS basis. It could be based on type
field.
Semaphores
• A semaphore is a counter used to synchronize access to a shared data amongst
multiple processes.
• To obtain a shared resource, the process should:
• Test the semaphore that controls the resource.
• If value is positive, it gains access and decrements value of semaphore.
o If value is zero, the process goes to sleep and awakes when value is > 0.
• When a process relinquishes resource, it increments the value of semaphore by
1.

Producer-Consumer problem
• Producer process produces information to be consumed by a consumer process
A producer can produce one item while the consumer is consuming another one.
With bounded-buffer size, consumer must wait if buffer is empty, whereas
producer must wait if buffer is full.
• The buffer can be implemented using any IPC facility.
Exp#10a Fibonacci & Prime Number

Aim
To generate 25 fibonacci numbers and determine prime amongst them using pipe.

Algorithm

1. Declare a array to store fibonacci numbers


2. Decalre a array pfd with two elements for pipe descriptors.
3. Create pipe on pfd using pipe function call.
a. If return value is -1 then stop
4. Using fork system call, create a child process.
5. Let the child process generate 25 fibonacci numbers and store them in a array.
6. Write the array onto pipe using write system call.
7. Block the parent till child completes using wait system call.
8. Store fibonacci nos. written by child from the pipe in an array using read system
call
9. Inspect each element of the fibonacci array and check whether they are prime
a. If prime then print the fibonacci term.
10. Stop

Program
/* Fibonacci and Prime using pipe - fibprime.c */

#include <stdio.h> #include


<stdlib.h> #include <unistd.h>
#include <sys/types.h>
main()
{
pid_t pid; int
pfd[2];
int i,j,flg,f1,f2,f3;
static unsigned int ar[25],br[25];
if(pipe(pfd) == -1)
{
printf("Error in pipe"); exit(-1);
}
pid=fork(); if (pid
== 0)
{
printf("Child process generates Fibonacci series\n" ); f1 = -1;
f2 = 1;
for(i = 0;i < 25; i++)
{
f3 = f1 + f2;
printf("%d\t",f3); f1 = f2;
f2 = f3; ar[i] =
f3;
}
write(pfd[1],ar,25*sizeof(int));
}
else if (pid > 0)
{
wait(NULL);
read(pfd[0], br, 25*sizeof(int));
printf("\nParent prints Fibonacci that are Prime\n");
for(i = 0;i < 25; i++)
{
flg = 0;
if (br[i] <= 1) flg =
1;
for(j=2; j<=br[i]/2; j++)
{
if (br[i]%j == 0)
{
flg=1;
break;
}
}
if (flg == 0) printf("%d\t", br[i]);
}
printf("\n");}
else
{
printf("Process creation failed"); exit(-1);
}
}Output

$ gcc fibprime.c
$ ./a.out
Child process generates Fibonacci series
0 1 1 2 3 5 8 13
21 34 55 89 144 233 377 610
987 1597 2584 4181 6765 10946 17711 28657
46368
Parent prints Fibonacci that are Prime
2 3 5 13 89 233 1597 28657
Result
Thus fibonacci numbers that are prime is determined using IPC pipe.
Exp# 10b who | wc -l
Aim
To determine number of users logged in using pipe.
Algorithm
1. Decalre a array pfd with two elements for pipe descriptors.
2. Create pipe on pfd using pipe function
call. a. If return value is -1 then stop
3. Using fork system call, create a child process.
4. Free the standard output (1) using close system call to redirect the output to
pipe.
5. Make a copy of write end of the pipe using dup system call.
6. Execute who command using execlp system call.
7. Free the standard input (0) using close system call in the other process.
8. Make a close of read end of the pipe using dup system call.
9. Execute wc –l command using execlp system call.
10. Stop
Program
/* No. of users logged - cmdpipe.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pfds[2];
pipe(pfds);
if (!fork())
{
close(1);
dup(pfds[1]);
close(pfds[0]); execlp("who", "who",
NULL);
}
else
{
close(0);
dup(pfds[0]);
close(pfds[1]);
execlp("wc", "wc", "-l", NULL);
}
}
Output

$ gcc cmdpipe.c

$ ./a.out 15

Result
Thus standard output of who is connected to standard input of wc using pipe to
compute number of users logged in.
Exp# 10c Chat Messaging

Aim
To exchange message between server and client using message queue.

Algorithm
Server
1. Decalre a structure mesgq with type and text fields.
2. Initialize key to 2013 (some random value).
3. Create a message queue using msgget with key & IPC_CREAT as parameter.
a. If message queue cannot be created then stop.
4. Initialize the message type member of mesgq to 1.
5. Do the following until user types Ctrl+D
a. Get message from the user and store it in text member.
b. Delete the newline character in text member.
c. Place message on the queue using msgsend for the client to read.
d. Retrieve the response message from the client using msgrcv function
e. Display the text contents.
6. Remove message queue from the system using msgctl with IPC_RMID as
parameter.
7. Stop

Client
1. Decalre a structure mesgq with type and text fields.
2. Initialize key to 2013 (same value as in server).
3. Open the message queue using msgget with key as parameter.
a. If message queue cannot be opened then stop.
4. Do while the message queue exists
a.Retrieve the response message from the server using msgrcv function
b.Display the text contents.
c.Get message from the user and store it in text member.
d.Delete the newline character in text member.
e. Place message on the queue using msgsend for the server to read.
5. Print "Server Disconnected".
6. Stop

Program
Server

/* Server chat process - srvmsg.c */

#include <stdio.h> #include


<stdlib.h> #include <string.h>
#include <sys/types.h>
#include <sys/ipc.h> #include
<sys/msg.h>
struct mesgq
{
long type;
char text[200]; } mq;
main()
{
int msqid, len; key_t
key = 2013;
if((msqid = msgget(key, 0644|IPC_CREAT)) == -1)
{
perror("msgget");
exit(1);
}
printf("Enter text, ^D to quit:\n"); mq.type = 1;
while(fgets(mq.text, sizeof(mq.text), stdin) != NULL)
{
len = strlen(mq.text);
if (mq.text[len-1] == '\n')
mq.text[len-1] = '\0';
msgsnd(msqid, &mq, len+1, 0);
msgrcv(msqid, &mq, sizeof(mq.text), 0, 0); printf("From
Client: \"%s\"\n", mq.text);
}
msgctl(msqid, IPC_RMID, NULL);
}
Client
/* Client chat process - climsg.c */
#include <stdio.h> #include
<stdlib.h> #include <string.h>
#include <sys/types.h>
#include <sys/ipc.h> #include
<sys/msg.h>
struct mesgq
{
long type;
char text[200]; } mq;
main()
{
int msqid, len; key_t
key = 2013;
if ((msqid = msgget(key, 0644)) == -1)
{
printf("Server not active\n"); exit(1);
}
printf("Client ready :\n");
while (msgrcv(msqid, &mq, sizeof(mq.text), 0, 0) != -1)
{
printf("From Server: \"%s\"\n", mq.text);
fgets(mq.text, sizeof(mq.text), stdin); len =
strlen(mq.text);
if (mq.text[len-1] == '\n')
mq.text[len-1] = '\0';
msgsnd(msqid, &mq, len+1, 0);
}
printf("Server Disconnected\n");
}
Output
Server
$ gcc srvmsg.c -o srvmsg

$ ./srvmsg
Enter text, ^D to quit: hi
From Client: "hello" Where
r u?
From Client: "I'm where i am" bye
From Client: "ok" ^D
Client
$ gcc climsg.c -o climsg

$ ./climsg Client ready:


From Server: "hi" hello
From Server: "Where r u?" I'm
where i am
From Server: "bye" ok
Server Disconnected
Result
Thus chat session between client and server was done using message queue.
Exp# 10d Shared Memory

Aim
To demonstrate communication between process using shared memory.

Algorithm
Server
1. Initialize size of shared memory shmsize to 27.
2. Initialize key to 2013 (some random value).
3. Create a shared memory segment using shmget with key & IPC_CREAT as parameter.
a. If shared memory identifier shmid is -1, then stop.
4. Display shmid.
5. Attach server process to the shared memory using shmmat with shmid as parameter.
a. If pointer to the shared memory is not obtained, then stop.
6. Clear contents of the shared region using memset function.
7. Write a–z onto the shared memory.
8. Wait till client reads the shared memory contents
9. Detatch process from the shared memory using shmdt system call.
10. Remove shared memory from the system using shmctl with IPC_RMID argument
11. Stop

Client
1. Initialize size of shared memory shmsize to 27.
2. Initialize key to 2013 (same value as in server).
3. Obtain access to the same shared memory segment using same key.
a. If obtained then display the shmid else print "Server not started"
4. Attach client process to the shared memory using shmmat with shmid as parameter.
a. If pointer to the shared memory is not obtained, then stop.
5. Read contents of shared memory and print it.
6. After reading, modify the first character of shared memory to '*'
7. Stop

Program
Server
/* Shared memory server - shms.c */

#include <stdio.h> #include


<stdlib.h> #include <sys/un.h>
#include <sys/types.h> #include
<sys/ipc.h> #include <sys/shm.h>
#define shmsize 27
main()
{
char c; int shmid;
key_t key = 2013; char *shm,
*s;
if ((shmid = shmget(key, shmsize, IPC_CREAT|0666)) < 0)
{
perror("shmget");
exit(1);
}
printf("Shared memory id : %d\n", shmid);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{
perror("shmat");
exit(1);
}
memset(shm, 0, shmsize); s = shm;
printf("Writing (a-z) onto shared memory\n"); for (c = 'a'; c <= 'z'; c+
+)
*s++ = c; *s = '\0';
while (*shm != '*');
printf("Client finished reading\n");
if(shmdt(shm) != 0)
fprintf(stderr, "Could not close memory segment.\n");
shmctl(shmid, IPC_RMID, 0);
}

Client

/* Shared memory client - shmc.c */

#include <stdio.h> #include


<stdlib.h> #include <sys/types.h>
#include <sys/ipc.h> #include
<sys/shm.h>
#define shmsize 27

main()
{
int shmid;
key_t key = 2013; char *shm,
*s;
if ((shmid = shmget(key, shmsize, 0666)) < 0)
{
printf("Server not started\n"); exit(1);
}
else
printf("Accessing shared memory id : %d\n",shmid);
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
{
perror("shmat");
exit(1);
}
printf("Shared memory contents:\n"); for (s = shm; *s !
= '\0'; s++)
putchar(*s);
putchar('\n');
*shm = '*';
}
Output
Server
$ gcc shms.c -o shms

$ ./shms
Shared memory id : 196611 Writing (a-z) onto
shared memory Client finished reading

Client
$ gcc shmc.c -o shmc

$ ./shmc
Accessing shared memory id : 196611 Shared memory
contents: abcdefghijklmnopqrstuvwxyz

Result
Thus contents written onto shared memory by the server process is read by the client
process.

Ex.No: 11a Paging


Aim: To implement the Memory management policy- Paging.

Algorithm:

Step 1: Read all the necessary input from the keyboard.


Step 2: Pages - Logical memory is broken into fixed - sized blocks.
Step 3: Frames – Physical memory is broken into fixed – sized blocks.
Step 4: Calculate the physical address using the following
Physical address = ( Frame number * Frame size ) + offset
Step 5: Display the physical address.
Step 6: Stop the process.

Program:

/* Memory Allocation with Paging Technique */

#include <stdio.h>
#include <conio.h>
struct pstruct
{
int fno;
int pbit;
}ptable[10];

int pmsize,lmsize,psize,frame,page,ftable[20],frameno;

void info()
{
printf("\n\nMEMORY MANAGEMENT USING PAGING\n\n");
printf("\n\nEnter the Size of Physical memory: ");
scanf("%d",&pmsize);
printf("\n\nEnter the size of Logical memory: ");
scanf("%d",&lmsize);
printf("\n\nEnter the partition size: ");
scanf("%d",&psize);
frame = (int) pmsize/psize;
page = (int) lmsize/psize;
printf("\nThe physical memory is divided into %d no.of frames\n",frame);
printf("\nThe Logical memory is divided into %d no.of pages",page);
}

void assign()
{
int i;
for (i=0;i<page;i++)
{
ptable[i].fno = -1;
ptable[i].pbit= -1;
}
for(i=0; i<frame;i++)
ftable[i] = 32555;
for (i=0;i<page;i++)
{
printf("\n\nEnter the Frame number where page %d must be placed: ",i);
scanf("%d",&frameno);
ftable[frameno] = i;
if(ptable[i].pbit == -1)
{
ptable[i].fno = frameno;
ptable[i].pbit = 1;
}
}
getch();
// clrscr();
printf("\n\nPAGE TABLE\n\n");
printf("PageAddress FrameNo. PresenceBit\n\n");
for (i=0;i<page;i++)
printf("%d\t\t%d\t\t%d\n",i,ptable[i].fno,ptable[i].pbit);
printf("\n\n\n\tFRAME TABLE\n\n");
printf("FrameAddress PageNo\n\n");
for(i=0;i<frame;i++)
printf("%d\t\t%d\n",i,ftable[i]);
}
void cphyaddr()
{
int laddr,paddr,disp,phyaddr,baddr;
getch();
// clrscr();
printf("\n\n\n\tProcess to create the Physical Address\n\n");
printf("\nEnter the Base Address: ");
scanf("%d",&baddr);
printf("\nEnter theLogical Address: ");
scanf("%d",&laddr);

paddr = laddr / psize;


disp = laddr % psize;
if(ptable[paddr].pbit == 1 )
phyaddr = baddr + (ptable[paddr].fno*psize) + disp;
printf("\nThe Physical Address where the instruction present: %d",phyaddr);
}
void main()
{
clrscr();
info();
assign();
cphyaddr();
getch();
}

Output:
MEMORY MANAGEMENT USING PAGING
Enter the Size of Physical memory: 16

Enter the size of Logical memory: 8

Enter the partition size: 2

The physical memory is divided into 8 no.of frames

The Logical memory is divided into 4 no.of pages

Enter the Frame number where page 0 must be placed: 5

Enter the Frame number where page 1 must be placed: 6

Enter the Frame number where page 2 must be placed: 7

Enter the Frame number where page 3 must be placed: 2

PAGE TABLE

PageAddress FrameNo. PresenceBit

0 5 1
1 6 1
2 7 1
3 2 1

FRAME TABLE
FrameAddress PageNo

0 32555
1 32555
2 3
3 32555
4 32555
5 0
6 1
7 2
Process to create the Physical Address
Enter the Base Address: 1000
Enter theLogical Address: 3

The Physical Address where the instruction present: 1013

Result:
Thus a program to implement paging technique is written and verified using sample
inputs.

Ex.No:11b Segmentation

Aim:
To implement the memory management policy-segmentation.

Algorithm:

Step 1: Start the program.


Step 2: Get the number of segments.
Step 3: get the base address and length for each segment.
Step 4: Get the logical address.
Step 5: check whether the segment number is within the limit, if not display the error
message.
Step 6: Check whether the byte reference is within the limit, if not display the error
message.
Step 7: Calculate the physical memory and display it.
Step 8: Stop the program.

Program:
/*MEMORY SEGMENT TABLE*/

#include <stdio.h>
#include <conio.h>
#include <math.h>
int sost;
void gstinfo();
void ptladdr();

struct segtab
{
int sno;
int baddr;
int limit;
int val[10];
}st[10];

void gstinfo()
{
int i,j;
printf("\n\tEnter the size of the segment table: ");
scanf("%d",&sost);

for(i=1;i<=sost;i++)
{
printf("\n\tEnter the information about segment: %d",i);
st[i].sno = i;
printf("\n\tEnter the base Address: ");
scanf("%d",&st[i].baddr);
printf("\n\tEnter the Limit: ");
scanf("%d",&st[i].limit);
for(j=0;j<st[i].limit;j++)
{
printf("Enter the %d address Value: ",(st[i].baddr + j));
scanf("%d",&st[i].val[j]); }}}
void ptladdr()
{
int i,swd,d=0,n,s,disp,paddr;
clrscr();
printf("\n\n\t\t\t SEGMENT TABLE \n\n");
printf("\n\t SEG.NO\tBASE ADDRESS\t LIMIT \n\n");
for(i=1;i<=sost;i++)
printf("\t\t%d \t\t%d\t\t%d\n\n",st[i].sno,st[i].baddr,st[i].limit);
printf("\n\nEnter the logical Address: ");
scanf("%d",&swd);
n=swd;
while (n != 0)
{
n=n/10;
d++;
}

s = swd/pow(10,d-1);
disp = swd%(int)pow(10,d-1);

if(s<=sost)
{
if(disp < st[s].limit)
{
paddr = st[s].baddr + disp;
printf("\n\t\tLogical Address is: %d",swd);
printf("\n\t\tMapped Physical address is: %d",paddr);
printf("\n\tThe value is: %d",( st[s].val[disp] ) );
}
else
printf("\n\t\tLimit of segment %d is high\n\n",s);
}

else
printf("\n\t\tInvalid Segment Address \n");
}

void main()
{
char ch;
clrscr();
gstinfo();
do
{
ptladdr();
printf("\n\t Do U want to Continue(Y/N)");
flushall();
scanf("%c",&ch);
}while (ch == 'Y' || ch == 'y' );

getch(); }
Output:

Enter the size of the segment table: 3


Enter the information about segment: 1
Enter the base Address: 4

Enter the Limit: 5


Enter the 4 address Value: 11
Enter the 5 address Value: 12
Enter the 6 address Value: 13
Enter the 7 address Value: 14
Enter the 8 address Value: 15

Enter the information about segment: 2


Enter the base Address: 5

Enter the Limit: 4


Enter the 5 address Value: 21
Enter the 6 address Value: 31
Enter the 7 address Value: 41
Enter the 8 address Value: 51

Enter the information about segment: 3


Enter the base Address: 3

Enter the Limit: 4


Enter the 3 address Value: 31
Enter the 4 address Value: 41
Enter the 5 address Value: 41
Enter the 6 address Value: 51

SEGMENT TABLE
SEG.NO BASE ADDRESS LIMIT

1 4 5

2 5 4

3 3 4

Enter the logical Address: 3


Logical Address is: 3
Mapped Physical address is: 3
The value is: 31
Do U want to Continue(Y/N)

SEGMENT TABLE
SEG.NO BASE ADDRESS LIMIT

1 4 5

2 5 4

3 3 4

Enter the logical Address: 1

Logical Address is: 1


Mapped Physical address is: 4
The value is: 11
Do U want to Continue(Y/N)

Result:
Thus a program to implement the memory management technique – segmentation is
written, implemented and verified using sample inputs.
Ex.No:12 Threading And Synchronization Application
Aim:
To write a program to implement the threading and synchronization application.

Algorithm1:
1. Start the program
2. Declare all the necessary variables
3. Two threads (jobs) are created and in the start function of these threads, a counter
is maintained through which user gets the logs about job number which is started
and when it is completed.
4. Stop the program.

Program1: (Thread program)


#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];
int counter;

void* doSomeThing(void *arg)


{
unsigned long i = 0;
counter += 1;
printf("\n Job %d started\n", counter);

for(i=0; i<(0xFFFFFFFF);i++);
printf("\n Job %d finished\n", counter);

return NULL;
}

int main(void)
{
int i = 0;
int err;

while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
i++;
}

pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
Output 1:
$ ./tgsthreads
Job 1 started
Job 2 started
Job 2 finished
Job 2 finished
If you focus on the last two logs, you will see that the log ‘Job 2 finished’ is repeated twice
while no log for ‘Job 1 finished’ is seen.
Now, if you go back at the code and try to find any logical flaw, you’ll probably not find any
flaw easily. But if you’ll have a closer look and visualize the execution of the code, you’ll
find that :
• The log ‘Job 2 started’ is printed just after ‘Job 1 Started’ so it can easily be
concluded that while thread 1 was processing the scheduler scheduled the thread 2.
• If the above assumption was true then the value of the ‘counter’ variable got
incremented again before job 1 got finished.
• So, when Job 1 actually got finished, then the wrong value of counter produced the
log ‘Job 2 finished’ followed by the ‘Job 2 finished’ for the actual job 2 or vice versa
as it is dependent on scheduler.
• So we see that its not the repetitive log but the wrong value of the ‘counter’ variable
that is the problem.
The actual problem was the usage of the variable ‘counter’ by second thread when the first
thread was using or about to use it. In other words we can say that lack of synchronization
between the threads while using the shared resource ‘counter’ caused the problems or in one
word we can say that this problem happened due to ‘Synchronization problem’ between two
threads.
Mutexes
Now since we have understood the base problem, lets discuss the solution to it. The most
popular way of achieving thread synchronization is by using Mutexes.
A Mutex is a lock that we set before using a shared resource and release after using it. When
the lock is set, no other thread can access the locked region of code. So we see that even if
thread 2 is scheduled while thread 1 was not done accessing the shared resource and the code
is locked by thread 1 using mutexes then thread 2 cannot even access that region of code. So
this ensures a synchronized access of shared resources in the code.
Internally it works as follows :
• Suppose one thread has locked a region of code using mutex and is executing that
piece of code.
• Now if scheduler decides to do a context switch, then all the other threads which are
ready to execute the same region are unblocked.
• Only one of all the threads would make it to the execution but if this thread tries to
execute the same region of code that is already locked then it will again go to sleep.
• Context switch will take place again and again but no thread would be able to execute
the locked region of code until the mutex lock over it is released.
• Mutex lock will only be released by the thread who locked it.
• So this ensures that once a thread has locked a piece of code then no other thread can
execute the same region until it is unlocked by the thread who locked it.
• Hence, this system ensures synchronization among the threads while working on
shared resources.
A mutex is initialized and then a lock is achieved by calling the following two functions :
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict
attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
The first function initializes a mutex and through second function any critical region in the
code can be locked.
The mutex can be unlocked and destroyed by calling following functions :
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
The first function above releases the lock and the second function destroys the lock so that it
cannot be used anywhere in future.
A Practical Example
Lets see a piece of code where mutexes are used for thread synchronization
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];
int counter;
pthread_mutex_t lock;

void* doSomeThing(void *arg)


{
pthread_mutex_lock(&lock);

unsigned long i = 0;
counter += 1;
printf("\n Job %d started\n", counter);

for(i=0; i<(0xFFFFFFFF);i++);

printf("\n Job %d finished\n", counter);


pthread_mutex_unlock(&lock);
return NULL;
}

int main(void)
{
int i = 0;
int err;

if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}

while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
i++;
}

pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_mutex_destroy(&lock);
return 0;
}
In the code above:
• A mutex is initialized in the beginning of the main function.
• The same mutex is locked in the ‘doSomeThing()’ function while using the shared
resource ‘counter’
• At the end of the function ‘doSomeThing ()’ the same mutex is unlocked.
• At the end of the main function when both the threads are done, the mutex is
destroyed.
Now if we look at the output, we find:
$ ./threads
Job 1 started
Job 1 finished
Job 2 started
Job 2 finished
So we see that this time the start and finish logs of both the jobs were present. So thread
synchronization took place by the use of Mutex.
Result:

Thus a program to implement the threading and synchronization is written, verified


using sample inputs.
VIVA QUESTIONS
1. What is an operating system?
An operating system is a collection of software programs which control the allocation
and usage of various hardware resources in the system. It is the first program to be loaded in
the computer and it runs in the memory till the system is shut down.
Some of the popular Operating Systems are DOS, Windows, Ubuntu, Solaris etc.
2. What are its main functions?
The main functions of an OS are:

a.) Process Management


b.) Memory Management
c.) Input/ Output Management
d.) Storage/ File system management
3. What is a Kernel?
- Kernel is the part of OS which handles all details of sharing resources and device handling.
- It can be considered as the core of OS which manages the core features of an OS.
- Its purpose is to handle the communication between software and hardware
- Its services are used through system calls.
- A layer of software called shell wraps around the Kernel.
4. What are the main functions of a Kernel?
The main functions of OS a Kernel are:
•Process management
•Device management
•Memory management
•Interrupt handling
•I/O communication
•File system management
5. What are the different types of Kernel?
Kernels are basically of two types:
a.) Monolithic Kernels - In this architecture of kernel, all the system services were packaged
into a single system module which lead to poor maintainability and huge size of kernel.
b.) Microkernels - They follow the modular approach of architecture. Maintainability became
easier with this model as only the concerned module is to be altered and loaded for every
function. This model also keeps a tab on the ever growing code size of the kernel.
6. What are the disadvantages of Microkernels?
Following are the main disadvantages of Microkernels. Usually these disadvantages are
situation based.
a.) Larger running memory footprint
b.) Performance loss due to the requirement of more software for interfacing.
c.) Difficulty in fixing the messaging bugs.
d.) Complicated process management.
7. What is a command interpreter?
It is a program that interprets the command input through key board or command
batch file. It helps the user to interact with the OS and trigger the required system programs
or execute some user application.

Command interpreter is also referred to as:


- Control card interpreter
- Command line interpreter
- Console command processor
- Shell
8. Explain Process.
A process is a program that is running and under execution. On batch systems, it is called as a
"job" while on time sharing systems, it is called as a "task".
9. Explain the basic functions of process management.
Important functions of process management are:

- Creation and deletion of system processes.


- Creation and deletion of users.
- CPU scheduling.
- Process communication and synchronization.
10. What do you know about interrupt?
- Interrupt can be understood as a signal from a device causing context switch.
- To handle the interrupts, interrupt handlers or service routines are required.
- The address of each Interrupt service routine is provided in a list which is maintained in
interrupt vector.
11. What is a daemon?
- Daemon - Disk and execution monitor, is a process that runs in the background without
user’s interaction. They usually start at the booting time and terminate when the system is
shut down.
12. How would you identify daemons in Unix?
- The name of daemons usually end with 'd' at the end in Unix.
- For e.g. httpd, named, lpd.
13. What do you mean by a zombie process?
- These are dead processes which are not yet removed from the process table.
- It happens when the parent process has terminated while the child process is still running.
This child process now stays as a zombie.

14. What do you know about a Pipe? When is it used?


- It is an IPC mechanism used for one way communication between two processes which are
related.
- A single process doesn't need to use pipe. It is used when two process wish to communicate
one-way.
15. What is a named pipe?
- A traditional pipe is unnamed and can be used only for the communication of related
process. If unrelated processes are required to communicate - named pipes are required.
- It is a pipe whose access point is a file available on the file system. When this file is opened
for reading, a process is granted access to the reading end of the pipe. Similarly, when the file
is opened for writing, the process is granted access to writing end of the pipe.
- A named pipe is also referred to as a named FIFO or just FIFO.
16. What are the various IPC mechanisms?
IPC - Inter Process Communication.

Various IPC mechanisms are:

a.) Sockets
b.) Pipes
c.) Shared memory
d.) Signals
e.) Message Queues
17. What is a semaphore?
- A semaphore is a hardware or a software tag variable whose value indicates the status of a
common resource.
- Its purpose is to lock the common resource being used. A process which needs the resource
will check the semaphore to determine the status of the resource followed by the decision for
proceeding.
- In multitasking operating systems, the activities are synchronized by using the semaphore
techniques.
18. What kind of operations are possible on a semaphore?
Two kind of operations are possible on a semaphore - 'wait' and 'signal'.
19. What is context switching?
- Context is associated with each process encompassing all the information describing the
current execution state of the process
- When the OS saves the context of program that is currently running and restores the context
of the next ready to run process, it is called as context switching.
- It is important for multitasking OS.

20. Tell us something about Mutex.


- Mutex - ‘Mutual Exclusion Lock’ is a lock which protects access to shared data resource.
- Threads can create and initialize a mutex to be used later.
- Before entering a critical region the mutex is locked. It is unlocked after exiting the critical
region. If any thread tries to lock the mutex during this time, it can nt do so.
21. What is a critical section?
It is a section of code which can be executed only by one process at a time.
22. What is synchronization? What are the different synchronization mechanisms?
Synchronization means controlling access to a resource that is available to two or more
threads or process. Different synchronization mechanisms are:

- Mutex
- Semaphores
- Monitors
- Condition variables
- Critical regions
- Read/ Write locks
23. What is the basic difference between pre-emptive and non-pre-emptive scheduling.
Pre-emptive scheduling allows interruption of a process while it is executing and taking the
CPU to another process while non-pre-emptive scheduling ensures that a process keeps the
CPU under control until it has completed execution.
24. Is non-pre-emptive scheduling frequently used in a computer? Why?
No, it is rarely used for the reasons mentioned below:

- It can not ensure that each user gets a share of CPU regularly.
- The idle time with this increases reducing the efficiency and overall performance of the
system.
- It allows program to run indefinitely which means that other processes have to wait for very
long.
25. Explain condition variable.
- These are synchronization objects which help threads wait for particular conditions to
occur.
- Without condition variable, the thread has to continuously check the condition which is very
costly on the resources.
- Condition variable allows the thread to sleep and wait for the condition variable to give it a
signal.

26. What are read-write locks?


- Read - write locks provide simultaneous read access to many threads while the write access
stays with one thread at a time. They are especially useful in protecting the data that is not
frequently written but read simultaneously by many threads.
- They are slower than mutexes.
27. What is a deadlock?
- It is a condition where a group of two or more waiting for the resources currently in use by
other processes of the same group.
- In this situation every process is waiting for an event to be triggered by another process of
the group.
- Since no thread can free up the resource a deadlock occurs and the application hangs.
28. What are the necessary conditions for deadlock to occur?
a.) At least one resource should be occupied in a non-sharable condition.
b.) A process holding at least one resource is waiting for more resources currently in use by
other processes.
c.) It is not possible to pre-empt the resource.
d.) There exists a circular wait for processes.
29. Name the functions constituting the OS's memory management.
- Memory allocation and de-allocation
- Integrity maintenance
- Swapping
- Virtual memory
30. Name the different types of memory?
a.) Main memory also called primary memory or RAM
b.) Secondary memory or backing storage
c.) Cache
d.) Internal process memory
31. Throw some light on Internal Process Memory.
- This memory consists of a set of high-speed registers. They work as temporary storage for
instructions and data.
32. Explain compaction.
During the process of loading and removal of process into and out of the memory, the free
memory gets broken into smaller pieces. These pieces lie scattered in the memory.
Compaction means movement of these pieces close to each other to form a larger chunk of
memory which works as a resource to run larger processes.
33. What are page frames?
Page frames are the fixed size contiguous areas into which the main memory is divided by the
virtual memory.
34. What are pages?
- Pages are same sized pieces of logical memory of a program. Usually they range from 4 KB
to 8 KB depending on the addressing hardware of the machine.
- Pages improve the overall system performance and reduces requirement of physical storage
as the data is read in 'page' units.
35. Differentiate between logical and physical address.
- Physical addresses are actual addresses used for fetching and storing data in main memory
when the process is under execution.
- Logical addresses are generated by user programs. During process loading, they are
converted by the loader into physical address.
36. When does page fault error occur?
- It occurs when a page that has not been brought into main memory is accessed.
37. Explain thrashing.
- In virtual memory system, thrashing is a high page fault scenario. It occurs due to
under-allocation of pages required by a process.
- The system become extremely slow due to thrashing leading to poor performance.
38. What are the basic functions of file management in OS?
- Creation and deletion of files/ directories.
- Support of primitives for files/ directories manipulation.
- Backing up of files on storage media.
- Mapping of files onto secondary storage.
39. Explain thread.
- It is an independent flow of control within a process.
- It consists of a context and a sequence of instructions for execution.
40. What are the advantages of using threads?
The main advantages of using threads are:
a.) No special communication mechanism is required.
b.) Readability and simplicity of program structure increases with threads.
c.) System becomes more efficient with less requirement of system resources.
41. What are the disadvantages of using threads?
The main disadvantages of using threads are:
- Threads can not be re-used as they exist within a single process.
- They corrupt the address space of their process.
- They need synchronization for concurrent read-write access to memory.

42. What is a compiler?


A compiler is a program that takes a source code as an input and converts it into an object
code. During the compilation process the source code goes through lexical analysis, parsing
and intermediate code generation which is then optimized to give final output as an object
code.
43. What is a library?
It is a file which contains object code for subroutines and data to be used by the other
program.
44. What are the advantages of distributed system?
Advantages of distributed system are:
- Resources get shared
- Load gets shared
- Reliability is improved
- Provide a support for inter-process communication
45. When is a system in safe state?

The set of dispatch able processes is in a safe state if there exists at least one temporal order
in which all processes can be run to completion without resulting in a deadlock.

46. What is cycle stealing?

We encounter cycle stealing in the context of Direct Memory Access (DMA). Either
the DMA controller can use the data bus when the CPU does not need it, or it may force the
CPU to temporarily suspend operation. The latter technique is called cycle stealing. Note that
cycle stealing can be done only at specific break points in an instruction cycle.
47. What is busy waiting?

The repeated execution of a loop of code while waiting for an event to occur is called
busy-waiting.The CPU is not engaged in any real productive activity during this period, and
the process does not progress toward completion.
48. What are local and global page replacements?

Local replacement means that an incoming page is brought in only to the relevant
process address space. Global replacement policy allows any page frame from any process to
be replaced. The latter is applicable to variable partitions model only.

49. Define latency, transfer and seek time with respect to disk I/O.

Seek time is the time required to move the disk arm to the required track. Rotational
delay or latency is the time it takes for the beginning of the required sector to reach the head.
Sum of seek time (if any) and latency is the access time. Time taken to actually transfer a
span of data is transfer time.
50. What are rings in Windows NT?

Windows NT uses protection mechanism called rings provides by the process to


implement separation between the user mode and kernel mode.

51. What is Executive in Windows NT?

In Windows NT, executive refers to the operating system code that runs in kernel mode.

52. What are the sub-components of I/O manager in Windows NT?

1. Network redirector/ Server


2. Cache manager.
3. File systems
4. Network driver
5. Device driver

53. What are DDks? Name an operating system that includes this feature.

DDks are device driver kits, which are equivalent to SDKs for writing device drivers.
Windows NT includes DDks.

54. What level of security does Windows NT meets?

C2 level security.

55. What is FtDisk?

It is a fault tolerance disk driver for Windows NT.

You might also like