CS3561 OSRecord
CS3561 OSRecord
CS3561 OSRecord
Aim
To study and execute Unix commands.
Login
Type telnet server_ipaddress in run window.
User has to authenticate himself by providing username and password. Once verified, a greeting and $
prompt appears. The shell is now ready to receive commands from the user. Options suffixed with a
hyphen (–) and arguments are separated by space.
General commands
Command Function
Date Used to display the current system date and time.
date +%D Displays date only
date +%T Displays time only
date +% Y Displays the year part of date
date +% H Displays the hour part of time
Cal Calendar of the current month
cal year Displays calendar for all months of the specified year
cal month year Displays calendar for the specified month of the year
Who Login details of all users such as their IP, Terminal No, User name,
who am i Used to display the login details of the user
Uname Displays the Operating System
uname –r Shows version number of the OS (kernel).
uname –n Displays domain name of the server
echo $HOME Displays the user's home directory
Bc Basic calculator. Press Ctrl+d to quit
lp file Allows the user to spool a job along with others in a print queue.
man cmdname Manual for the given command. Press q to exit
history To display the commands used by the user since log on.
exit Exit from a process. If shell is the only process then logs out
Directory commands
Command Function
Pwd Path of the present working directory
mkdir dir A directory is created in the given name under the current directory
mkdir dir1 dir2 A number of sub-directories can be created under one stroke
cd subdir Change Directory. If the subdir starts with / then path starts from
root (absolute) otherwise from current working directory.
cd To switch to the home directory.
cd / To switch to the root directory.
cd .. To move back to the parent directory
rmdir subdir Removes an empty sub-directory.
File commands
Command Function
cat > filename To create a file with some contents. To end typing press Ctrl+d. The >
symbol means redirecting output to a file. (< for input)
cat filename Displays the file contents.
cat >> filename Used to append contents to a file
cp src des Copy files to given location. If already exists, it will be overwritten
cp –i src des Warns the user prior to overwriting the destination file
cp –r src des Copies the entire directory, all its sub-directories and files.
mv old new To rename an existing file or directory. –i option can also be used
2
The commands can be combined using the pipeline (|) operator. For example, number of users
logged in can be obtained as.
who | wc -l
Finally to terminate the unix session execute the command exit or logout.
Output
$ date
Sat Apr 9 13:03:47 IST 2011
$ date +%D
04/09/11
$ date +%T
13:05:33
$ date +%Y
2011
$ date +%H
13
$ cal 08 1998
August 1998
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
$ who
root :0 Apr 9 08:41
vijai pts/0 Apr 9 13:00 (scl-64)
3
$ uname
Linux
$ uname -r
2.4.20-8smp
$ uname -n
localhost.localdomain
$ echo $HOME
/home/vijai
$ echo $USER
vijai
$ bc
3+5
8
$ pwd
/home/vijai/shellscripts/loops
$ mkdir filter
$ ls
filter list.sh regexpr shellscripts
$ cd shellscripts/loops/
$
$ cd
$
$ cd /
[vijai@localhost /]$
$ rmdir filter
$ ls
list.sh regexpr shellscripts
$ cat greet
hi ece-a
wishing u the best
$ cat greet
hi cse
wishing u the best bye
$ ls
greet list.sh regexpr shellscripts
$ ls -a
. .bash_logout .canna .gtkrc regexpr .viminfo.tmp
.. .bash_profile .emacs .kde shellscripts .xemacs
.bash_history .bashrc greet list.sh .viminfo
$ ls -l
-rw-rw-r-- 1 vijai vijai 32 Apr 11 14:52 greet
-rw-rw-r-- 1 vijai vijai 30 Apr 4 13:58 list.sh
drwxrwxr-x 2 vijai vijai 4096 Apr 9 14:30 regexpr
$ cp greet ./regexpr/
$ ls
greet list.sh regexpr shellscripts
$ ls ./regexpr
demo greet
$ cp -i greet ./regexpr/
cp: overwrite 'greet'? n
$ mv greet greet.txt
$ ls
greet.txt list.sh regexpr shellscripts
$ mv greet.txt ./regexpr/
$ ls
list.sh regexpr shellscripts
$ rm -i *.sh
rm: remove regular file 'fact.sh'? y rm: remove
regular file 'prime.sh'? y
$ ls
list.sh regexpr shellscripts
$ wc list.sh
4 9 30 list.sh
$ wc -l list.sh
4 list.sh
$ ls -l list.sh
-rw-rw-r-- 1 vijai vijai 30 Apr 4 13:58 list.sh
$ ls -l list.sh
-rwxrwxr-- 1 vijai vijai 30 Apr 4 13:58 list.sh
$ chmod 740 list.sh
$ ls -l list.sh
-rwxr----- 1 vijai vijai 30 Apr 4 13:58 list.sh
5
Result
Thus the study and execution of Unix commands has been completed successfully.
Algorithm
1. Declare a variable x to be shared by both child and parent.
2. Create a child process using fork system call.
3. If return value is -1 then
Print "Process creation unsuccessfull" Terminate
using exit system call.
4. If return value is 0 then
Print "Child process"
Print process id of the child using getpid system call Print
value of x
Print process id of the parent using getppid system call
5. Otherwise
Print "Parent process"
Print process id of the parent using getpid system call Print
value of x
Print process id of the shell using getppid system call.
6. Stop
Program
/* Process creation - fork.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include
<sys/types.h>
main()
{
pid_t pid;
int x = 5;
pid = fork();
x++;
if (pid < 0)
{
printf("Process creation error");
exit(-1);
}
6
else if (pid == 0)
{
printf("Child process:");
printf("\nProcess id is %d", getpid());
printf("\nValue of x is %d", x);
printf("\nProcess id of parent is %d\n", getppid());
}
else
{
printf("\nParent process:");
printf("\nProcess id is %d", getpid());
printf("\nValue of x is %d", x);
printf("\nProcess id of shell is %d\n", getppid());
}
}
Output
$ gcc fork.c
$ ./a.out Child
process:
Process id is 19499
Value of x is 6
Process id of parent is 19498
Parent process:
Process id is 19498
Value of x is 6
Process id of shell is 3266
Result
Thus a child process is created with copy of its parent's address space.
Algorithm
Program
7
{
wait(NULL);
printf ("\nParent starts\nEven Nos: ");
for (i=2;i<=10;i+=2)
printf ("%3d",i);
printf ("\nParent ends\n");
}
else if (pid == 0)
{
printf ("Child starts\nOdd Nos: ");
for (i=1;i<10;i+=2)
printf ("%3d",i);
printf ("\nChild ends\n");
}
}
Output
$ gcc wait.c
$ ./a.out
Child starts
Odd Nos: 1 3 5 7 9
Child ends
Parent starts
Even Nos: 2 4 6 8 10
Parent ends
Result
Thus using wait system call zombie child processes were avoided.
Algorithm
8
Program
/* Load a program in child process - exec.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
main()
{
pid_t pid;
switch(pid = fork())
{
case -1:
perror("Fork failed"); exit(-1);
case 0:
printf("Child process\n"); execl("/bin/date",
"date", 0); exit(0);
default:
wait(NULL);
printf("Child Terminated\n"); exit(0);
}
}
Output
$ gcc exec.c
$ ./a.out Child
process
Sat Feb 23 17:46:59 IST 2013
Child Terminated
Result
Thus the child process loads a binary executable file into its address space.
Aim
To display file status using stat system call.
exit()
The exit system call is used to terminate a process either normally or abnormally
Closes all standard I/O streams.
9
stat()
The stat system call is used to return information about a file as a structure.
Algorithm
1. Get filename as command line argument.
2. If filename does not exist then stop.
3. Call stat system call on the filename that returns a structure
4. Display members st_uid, st_gid, st_blksize, st_block, st_size, st_nlink, etc.,
5. Convert time members such as st_atime, st_mtime into time using ctime function
6. Compare st_mode with mode constants such as S_IRUSR, S_IWGRP, S_IXOTH and display
file permissions.
7. Stop
Program
/* File status - stat.c */
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char*argv[])
{
struct stat file; int n;
if (argc != 2)
{
printf("Usage: ./a.out <filename>\n");
exit(-1);
}
if ((n = stat(argv[1], &file)) == -1)
{
perror(argv[1]);
exit(-1);
}
printf("User id : %d\n", file.st_uid);
printf("Group id : %d\n", file.st_gid);
printf("Block size : %d\n", file.st_blksize);
printf("Blocks allocated : %d\n", file.st_blocks);
printf("Inode no. : %d\n", file.st_ino);
printf("Last accessed : %s", ctime(&(file.st_atime)));
printf("Last modified : %s", ctime(&(file.st_mtime)));
printf("File size : %d bytes\n", file.st_size);
printf("No. of links : %d\n", file.st_nlink);
printf("Permissions : ");
printf( (S_ISDIR(file.st_mode)) ? "d" : "-");
printf( (file.st_mode & S_IRUSR) ? "r" : "-");
printf( (file.st_mode & S_IWUSR) ? "w" : "-");
printf( (file.st_mode & S_IXUSR) ? "x" : "-");
printf( (file.st_mode & S_IRGRP) ? "r" : "-");
printf( (file.st_mode & S_IWGRP) ? "w" : "-");
printf( (file.st_mode & S_IXGRP) ? "x" : "-");
printf( (file.st_mode & S_IROTH) ? "r" : "-");
printf( (file.st_mode & S_IWOTH) ? "w" : "-");
printf( (file.st_mode & S_IXOTH) ? "x" : "-"); printf("\n");
if(file.st_mode & S_IFREG) printf("File type : Regular\n");
if(file.st_mode & S_IFDIR) printf("File type : Directory\n");
}
Output
$ gcc stat.c
$ ./a.out fork.c
10
User id : 0
Group id : 0
Block size : 4096
Blocks allocated : 8
Inode no. : 16627
Last accessed : Fri Feb 22 21:57:09 2013
Last modified : Fri Feb 22 21:56:13 2013
File size : 591 bytes
Algorithm
1. Get directory name as command line argument.
2. If directory does not exist then stop.
3. Open the directory using opendir system call that returns a structure
4. Read the directory using readdir system call that returns a structure
5. Display d_name member for each entry.
6. Close the directory using closedir system call.
7. Stop
Program
/* Directory content listing - dirlist.c */
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
struct dirent *dptr; DIR *dname;
if (argc != 2)
{
printf("Usage: ./a.out <dirname>\n"); exit(-1);
}
if((dname = opendir(argv[1])) == NULL)
{
perror(argv[1]);
exit(-1);
}
while(dptr=readdir(dname))
printf("%s\n", dptr->d_name);
closedir(dname);
11
}
Output
$ gcc dirlist.c
$ ./a.out vijai wait.c
a.out
..
stat.c dirlist.c fork.c
.
exec.c
Result
Thus files and subdirectories in the directory was listed that includes hidden files.
creat()
Used to create a new file and open it for writing.
It is replaced with open() with flags O_WRONLY|O_CREAT | O_TRUNC
Algorithm
1. Declare a character buffer buf to store 100 bytes.
2. Get the new filename as command line argument.
3. Create a file with the given name using open system call with O_CREAT and
O_TRUNC options.
4. Check the file descriptor.
a) If file creation is unsuccessful, then stop.
5. Get input from the console until user types Ctrl+D
a) Read 100 bytes (max.) from console and store onto buf using read system call
b) Write length of buf onto file using write system call.
6. Close the file using close system call.
7. Stop
Program
/* File creation - fcreate.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd, n, len; char
buf[100];
if (argc != 2)
{
12
close(fd);
}
Output
$ gcc fcreate.c
$ ./a.out hello File I/O
Open system call is used to either open or create a file. creat system call is used to create a file.
It is seldom used.
^D
Result
Thus a file has been created with input from the user. The process can be verified by
using cat command
read()
Reads no. of bytes from the file or from the terminal.
If read is successful, it returns no. of bytes read.
The file offset is incremented by no. of bytes read.
If end-of-file is encountered, it returns 0.
Algorithm
Program
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd,i;
char buf[100]; if (argc < 2)
{
printf("Usage: ./a.out <filename>\n"); exit(-1);
}
Output
$ gcc fread.c
$ ./a.out hello File I/O
open system call is used to either open or create a file. creat system call is used to create a file. It
is seldom used.
Result
Thus the given file is read and displayed on the console. The process can be verified by using cat
command.
write()
Writes no. of bytes onto the file.
After a successful write, file's offset is incremented by the no. of bytes written.
If any error due to insufficient storage space, write fails.
close()
Closes a opened file.
When process terminates, files associated with the process are automatically closed.
Algorithm
1. Declare a character buffer buf to store 100 bytes.
2. Get exisiting filename as command line argument.
3. Create a file with the given name using open system call with O_APPEND option.
4. Check the file descriptor.
a) If value is negative, then stop.
5. Get input from the console until user types Ctrl+D
a) Read 100 bytes (max.) from console and store onto buf using read system call
b) Write length of buf onto file using write system call.
6. Close the file using close system call.
7. Stop
14
Program
/* File append - fappend.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
main(int argc, char *argv[])
{
int fd, n, len; char
buf[100];
if (argc != 2)
{
printf("Usage: ./a.out <filename>\n");
exit(-1);
}
Output
$ gcc fappend.c
$ ./a.out hello
read system call is used to read from file or console write system call is used to write
to file.
^D
Result
Thus contents have been written to end of the file. The process can be verified by using
cat command.
Exp# 3a ls command
Date:
Aim
To simulate ls command using UNIX system calls.
Algorithm
1. Store path of current working directory using getcwd system call.
2. Scan directory of the stored path using scandir system call and sort the resultant array
of structure.
3. Display dname member for all entries if it is not a hidden file.
4. Stop.
Program
/* ls command simulation - list.c */
#include <stdio.h>
#include <dirent.h>
15
main()
{
struct dirent **namelist; int n,i;
char pathname[100];
getcwd(pathname);
n = scandir(pathname, &namelist, 0, alphasort);
if(n < 0)
printf("Error\n"); else
for(i=0; i<n; i++)
if(namelist[i]->d_name[0] != '.')
printf("%-20s", namelist[i]->d_name);
}
Output
$ gcc list.c -o list
$ ./list a.out cmdpipe.c consumer.c
dirlist.c ex6c.c ex6a.c ex6d.c ex6b.c exec.c
fappend.c fcfs.c fread.c fcreate.c hello
fork.c list list.c rr.c pri.c simls.c
producer.c stat.c wait.c
sjf.c
Result
}
}
Output
$ gcc mygrep.c -o mygrep
$ ./mygrep printf dirlist.c
printf("Usage: ./a.out <dirname>\n"); printf("%s\n", dptr->d_name);
Result
Thus the program simulates grep command by listing lines containing the search text.
Exp# 3c cp command
Date:
Aim
To simulate cp command using UNIX system call.
Algorithm
Program
/* cp command simulation - copy.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#define SIZE 1024
main(int argc, char *argv[])
{
int src, dst, nread;
char buf[SIZE];
if (argc != 3)
{
printf("Usage: gcc copy.c -o copy\n");
printf("Usage: ./copy <filename> <newfile> \n");
exit(-1);
}
if ((src = open(argv[1], O_RDONLY)) == -1)
{
perror(argv[1]);
exit(-1);
}
if ((dst = creat(argv[2], 0644)) == -1)
{
perror(argv[1]);
exit(-1);
}
while ((nread = read(src, buf, SIZE)) > 0)
{
if (write(dst, buf, nread) == -1)
{
printf("can't write\n"); exit(-1);
}
}
close(src); close(dst);
}
Output
$ gcc copy.c -o copy
$ ./copy hello hello.txt
Result
Thus a file is copied using file I/O. The cmp command can be used to verify that contents of
both file are same
Exp# 3d rm command
Date:
Aim
To simulate rm command using UNIX system call.
Algorithm
1. Get filename as command-line argument.
18
Program
/* rm command simulation - del.c */ #include <stdio.h>
#include <stdlib.h> #include
<fcntl.h>
main(int argc, char* argv[])
{
int fd;
if (argc != 2)
{
printf("Usage: gcc del.c -o del\n"); printf("Usage: ./del
<filename>\n"); exit(-1);
}
fd = open(argv[1], O_RDONLY); if (fd != -1)
{
close(fd); unlink(argv[1]);
}
else
perror(argv[1]);
}
Output
$ gcc del.c -o del
$ ./del hello.txt
Result
Thus files can be deleted in a manner similar to rm command. The deletion of file can be verified
by using ls command.
Aim
To write simple shell scripts using shell programming fundamentals.
The activities of a shell are not restricted to command interpretation alone. The shell also has
rudimentary programming features. Shell programs are stored in a file (with extension .sh). Shell
programs run in interpretive mode. The original UNIX came with the Bourne shell (sh) and it is universal
even today. C shell (csh) and Korn shell (ksh) are also widely used. Linux offers Bash shell (bash) as a
superior alternative to Bourne shell.
Preliminaries
1. Comments in shell script start with #.
2. Shell variables are loosely typed i.e. not declared. Variables in an expression or output must
be prefixed by $.
3. The read statement is shell's internal tool for making scripts interactive.
4. Output is displayed using echo statement.
5. Expressions are computed using the expr command. Arithmetic operators are + -
* / %. Meta characters * ( ) should be escaped with a \.
Output
$ sh swap.sh
Enter value for A : 12
Enter value for B : 23
Values after Swapping
A Value is 23 and B Value is 12
Output
$ sh degconv.sh
Enter Fahrenheit : 213
Centigrade is : 100
C) Biggest of 3 numbers
# Biggest – big3.sh
echo -n "Give value for A B and C: "
read a b c
if [ $a -gt $b -a $a -gt $c ] then
echo "A is the Biggest number"
elif [ $b -gt $c ]
then
echo "B is the Biggest number" else
echo "C is the Biggest number"
fi
Output
$ sh big3.sh
Give value for A B and C: 4 3 4
C is the Biggest number
D) Grade Determination
# Grade – grade.sh
echo -n "Enter the mark : "
read mark
if [ $mark -gt 90 ]
then
echo "S Grade"
20
Output
$ sh grade.sh
Enter the mark : 65
C Grade
E) Vowel or Consonant
# Vowel - vowel.sh
echo -n "Key in a lower case character : "
read choice
case $choice in a|e|i|o|u)
echo "It's a Vowel";; *)
echo "It's a Consonant"
esac
Output
$ sh vowel.
F) Simple Calculator
Output
$ sh calc.sh
Enter the two numbers : 2 4
1. Addition
2. Subtraction
21
3. Multiplication
4. Division
Enter the option : 1 2 + 4 = 6
G) Multiplication Table
# Multiplication table – multable.sh clear
echo -n "Which multiplication table? : "
read n
for x in 1 2 3 4 5 6 7 8 9 10 do
p=`expr $x \* $n`
echo -n "$n X $x = $p"
sleep 1
done
Output
$ sh multable.sh
Which multiplication table? : 6 6 X 1 = 6
6 X 2 = 12
.....
H) Number Reverse
# To reverse a number – reverse.sh
echo -n "Enter a number : "
read n
rd=0
while [ $n -gt 0 ] do
rem=`expr $n % 10`
rd=`expr $rd \* 10 + $rem`
n=`expr $n / 10`
done
echo "Reversed number is $rd"
Output
$ sh reverse.sh
Enter a number : 234
Reversed number is 432
I) Prime Number
# Prime number – prime.sh
echo -n "Enter the number : "
read n
i=2
m=`expr $n / 2` until [ $i -gt
$m ] do
q=`expr $n % $i` if [ $q -
eq 0 ] then
echo "Not a Prime number"
exit
fi
i=`expr $i + 1` done
echo "Prime number"
Output
$ sh prime.sh
Enter the number : 17
Prime number
Result
Thus shell scripts were executed using different programming constructs
22
Aim
To schedule snapshot of processes queued according to FCFS scheduling.
Process Scheduling
CPU scheduling is used in multiprogrammed operating systems.
By switching CPU among processes, efficiency of the system can be improved.
Some scheduling algorithms are FCFS, SJF, Priority, Round-Robin, etc.
Gantt chart provides a way of visualizing CPU scheduling and enables to understand better.
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. wtime
i+1 = wtimei + btimei
b. ttime = wtimei + btimei
i
6. Compute average waiting time awat and average turnaround time atur
7. Display the btime, ttime and wtime for each process.
8. Display GANTT chart for the above scheduling
9. Display awat time and atur
10. Stop
Program
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;
Output
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
Result
Thus waiting time & turnaround time for processes based on FCFS scheduling was computed
and the average waiting time was determined.
Aim
To schedule snapshot of processes queued according to SJF 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
25
Program
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("-");
26
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
Average waiting time : 11.80ms
0 5 11 17 26 36
Result
Thus waiting time & turnaround time for processes based on SJF scheduling was computed
27
Aim
To schedule snapshot of processes queued according to Priority scheduling.
Priority
Process that has higher priority is processed first.
Prioirty can be preemptive or non–preemptive
When two processes have same priority, FCFS is used to break the tie.
Can result in starvation, since low priority processes may not be processed.
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
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);
28
}
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("\n P%-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\nAverage waiting time : %5.2fms", awat); printf("\
nAverage turn around time : %5.2fms\n", atur);
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("-");
29
Output
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
Average waiting time : 13.80ms
Average turn around time : 22.00ms
GANTT Chart
| P2 | P5 | P1 | P3 | P4 |
0 7 12 22 28 41
Result
Thus waiting time & turnaround time for processes based on Priority scheduling was
computed and the average waiting time was determined.
Aim
To schedule snapshot of processes queued according to Round robin scheduling.
Round Robin
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.
Round robin is a fair preemptive scheduling algorithm.
A process that is yet to complete in a round is preempted after the time slice and put at the
end of the queue.
When a process is completely processed, it is removed from the queue.
Algorithm
1. Get length of the ready queue, i.e., number of process (say n)
2. Obtain Burst time Bi for each processes Pi.
3. Get the time slice per round, say TS
30
Program
/* Round robin scheduling - rr.c */ u
/* Round robin scheduling - rr.c */
#include <stdio.h>
main()
int i,x=-1,k[10],m=0,n,t,s=0;
float awat,atur;
scanf("%d", &n);
bur1[i] = bur[i];
b[i] = bur[i] / t;
if((bur[i]%t) != 0)
b[i] += 1;
m += b[i];
}
31
printf("--------------------------------- ");
printf("\n");
a[0] = 0;
while(j < m)
if(x == n-1) x = 0;
else
x++;
if(bur[x] >= t)
bur[x] -= t;
a[j+1] = a[j] + t;
if(b[x] == 1)
p[s] = x;
k[s] = a[j+1];
s++;
j++;
b[x] -= 1;
else if(bur[x] != 0)
if(b[x] == 1)
{
32
p[s] = x;
j++;
b[x] -= 1;
printf("\n"); for(i=0;i<m;i++)
printf("------------------------- ");
printf("\n");
temp = p[i];
p[i] = p[j];
p[j] = temp;
temp = k[i];
k[i] = k[j];
k[j] = temp;
{
33
tur[i] = k[i];
ttur += tur[i];
twat += wat[i];
printf("\n\n");
printf("-");
printf("\nProcess\tBurst\tTrnd\tWait\n");
printf("-");
printf("-");
awat = (float)twat / n;
atur = (float)ttur / n;
printf("\n\nAverage waiting time : %.2f ms", awat); printf("\nAverage turn around time : %.2f ms\n", atur);
}
Output
Enter no. of process : 5
Burst time for process P1 : 10
Burst time for process P2 : 29
Burst time for process P3 : 3
Burst time for process P4 : 7
Burst time for process P5 : 12
Enter the time slice (in ms) : 10
GANTT Chart
P1 | P2 | P3 | P4 | P5 | P2 | P5 | P2 |
34
0 10 20 23 30 40 50 52 61
P1 10 10 0
P2 29 61 32
P3 3 23 20
P4 7 30 23
P5 12 52 40
Result
Thus waiting time and turnaround time for processes based on Round robin
scheduling was computed and the average waiting time was determined.
INTERPROCESS COMMUNICATION
AIM:
To implement the concept of interprocess communication using pipes using c
program.
ALGORITHM:
1. create the pipe and create the process.
2. get the input in the main process and pass the output to the child process using pipe.
3. perform the operation given in the child process and print the output.
4. stop the program.
PROGRAM:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
main()
{
int p1[2],p2[2],p3[2],p4[2];
int i,j=0,k=0,l=0;
char r[10],s[10],t[10],u[10];
printf("\t PROCESS 1.ENTER THE STRING");
scanf("%s",r);
pipe(p1);
pipe(p2);
write(p1[1],r,sizeof(r));
write(p2[1],r,sizeof(r));
int a=fork();
if(a==0)
35
{
printf("\n\t PROCESS 2:it splits the given string\n");
read(p1[0],r,sizeof(r));
int n=strlen(r);
for(i=0;i<n/2;i++)
{
s[i]=r[i];
}
for(i=n/2;i<=n;i++)
{
t[j++]=r[i];
}
pipe(p3);
pipe(p4);
write(p3[1],s,sizeof(s));
write(p4[1],t,sizeof(t));
int b=fork();
if(b==0)
{
printf("p4 %d\t",getpid());
printf("p2 %d\n",getppid());
read(p3[0],s,sizeof(s));
printf("\t PROCESS 4:sub string \t %s \t",s);
printf("no of char=%d \n",strlen(s));
}
else
{
int c=fork();
if(c==0)
{
printf("p5 %d\t",getpid());
printf("p2 %d\n",getppid());
read(p4[0],t,sizeof(t));
printf("\t PROCESS 5:sub string \t %s \t",t);
printf("no of char=%d \n",strlen(t));
}
else
{
wait();
printf("p2 %d\t",getpid());
printf("p1 %d\n",getppid());
} }}
else
{
wait();
int d=fork();
if(d==0)
{
printf("p3 %d\t",getpid());
printf("p1 %d\n",getppid());
read(p2[0],r,sizeof(r));
for(i=strlen(r)-1;i>=0;i--)
{
u[l++]=r[i];
}
for(i=0;i<strlen(r);i++)
{
if(u[i]==r[i])
k++;
36
else
continue;
}
if(k==strlen(r))
printf("\t PROCESS 3: the given string is palindrome\n");
else
printf("\t PROCESS 3: the given string is not palindrome\n");
}
else
{
printf("p1 %d\t",getpid());
printf("kernal %d\t\n",getppid());
}
}}
OUTPUT:
Aim
To demonstrate the utility of semaphore in synchronization and multithreading.
Semaphore
The POSIX system in Linux has its own built-in semaphore library.
To use it, include semaphore.h.
Compile the code by linking with -lpthread -lrt.
To lock a semaphore or wait, use the sem_wait function.
To release or signal a semaphore, use the sem_post function.
A semaphore is initialised by using sem_init(for processes or threads)
To declare a semaphore, the data type is sem_t.
Algorithm
1. 2 threads are being created, one 2 seconds after the first one.
2. But the first thread will sleep for 4 seconds after acquiring the lock.
3. Thus the second thread will not enter immediately after it is called, it will enter 4 – 2
= 2 secs after it is called.
37
4. Stop.
Program
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mutex;
void* thread(void* arg)
{
//wait sem_wait(&mutex); printf("\
nEntered..\n");
//critical section sleep(4);
//signal
printf("\nJust Exiting...\n"); sem_post(&mutex);
}
int main()
{
sem_init(&mutex, 0, 1);
pthread_t t1,t2;
pthread_create(&t1,NULL,thread,NULL); sleep(2);
pthread_create(&t2,NULL,thread,NULL);
pthread_join(t1,NULL); pthread_join(t2,NULL);
sem_destroy(&mutex);
return 0;
}
Output
$ gcc sem.c -lpthread
$ ./a.out Entered..
Just Exiting... Entered..
Just Exiting...
Result
Thus semaphore implementation has been demonstrated.
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.
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.
38
Program
/* Fibonacci and Prime using pipe - fibprime.c */
#uncludecsdcsdcdscdfvdfvdfvfdvdfvdfvd
#include< >
pid_t pid;
int pfd[2];
int i,j,flg,f1,f2,f3;
static unsigned int ar[25],br[25];
pid=fork();
if(pipe(pfd) == -1)
{
printf("Error in pipe"); exit(-1);
}
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));
}
if (br[i]%j == 0)
39
{
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.
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())
40
{
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.
Aim
To exchange message between server and client using message queue.
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.
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.
41
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()
42
{
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.
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.
Algorithm
Server
1. Initialize size of shared memory shmsize to 27.
2. Initialize key to 2013 (some random value).
43
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.
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
if(shmdt(shm) != 0)
fprintf(stderr, "Could not close memory segment.\n");
Client
*shm = '*';
}
Output
Server
$ ./shms
Shared memory id : 196611 Writing (a-z) onto shared memory
Client finished reading
Client
$ ./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.
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:
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)
{
{
printf("\nCan't create mutex semaphore"); exit(1);
}
if((empty = semget(IPC_PRIVATE, 1, PERMS|IPC_CREAT)) == -1)
{
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
48
Result
Thus synchronization between producer and consumer process for access to a shared memory
segment is implemented.
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 its 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.
PROGRAM
#include <stdio.h>
#include <stdio.h>
main()
{
int r[1][10], av[1][10];
int all[10][10], max[10][10], ne[10][10], w[10],safe[10];
int i=0, j=0, k=0, l=0, np=0, nr=0, count=0, cnt=0;
clrscr();
printf("enter the number of processes in a system");
scanf("%d", &np);
printf("enter the number of resources in a system");
scanf("%d",&nr);
for(i=1; i<=nr; i++)
{
printf("Enter no. of instances of resource R%d " ,i);
scanf("%d", &r[0][i]);
av[0][i] = r[0][i];
}
for(i=1; i<=np; i++) for(j=1; j<=nr; ++)
all[i][j] = ne[i][j] = max[i][j] = w[i]=0;
printf("Enter the allocation matrix");
for(i=1; i<=np; i++)
{
for(j=1; j<=nr; j++)
{
scanf("%d", &all[i][j]);
av[0][j] = av[0][j] - all[i][j];
}
}
printf("Enter the maximum matrix"); for(i=1; i<=np; i++)
{
for(j=1; j<=nr; j++)
{
scanf("%d",&max[i][j]);
}
for(i=1; i<=np; i++)
{
49
Output
enter the number of processes in a system 3
enter the number of resources in a system 3
enter no. of instances of resource R1 10
enter no. of instances of resource R2 7
enter no. of instances of resource R3 7
Enter the allocation matrix 3 2 1
112
412
50
process P2
allocated 1 maximum 3 need 2
allocated 1 maximum 4 need 3
allocated 2 maximum 5 need 3
process P3
allocated 4 maximum 5 need 1
allocated 1 maximum 2 need 1
allocated 2 maximum 4 need 2
Availability R1 2 R2 3 R3 2
safe sequence
P3 Availability R1 6 R2 4 R3 4
P1 Availability R1 9 R2 6 R3 5
P2 Availability R1 10 R2 7 R3 7
Result
Thus bankers algorithm for dead lock avoidance was executed successfully.
Algorithm
1. Mark each process that has a row in the Allocation matrix of all zeros.
2. Initialize a temporary vectorW to equal the Available vector.
3. Find an indexi such that processi is currently unmarked and thei th row ofQ
4. is less than or equal to W . That is,Q ik … Wk, for 1 … k … m . If no such row is
5. found, terminate the algorithm.
5. If such a row is found, mark processi and add the corresponding row of the
6. allocation matrix to W . That is, setWk = Wk + Aik, for 1 … k … m . Return
7. to step 3.
Program
#include<stdio.h>
#include<conio.h>
int max[100][100];
int alloc[100][100];
int need[100][100];
int avail[100];
int n, r;
void input();
void show();
void cal();
main()
{
int i,j;
printf("Deadlock Detection Algo\n");
input();
show();
cal();
52
getch();
}
void input()
{
int i,j;
printf("Enter the no of Processes\t"); scanf("%d",&n);
printf("Enter the no of resource instances\t"); scanf("%d", &r);
void cal()
{
int finish[100], temp, need[100][100], flag=1, k, c1=0; int dead[100];
int safe[100]; int i, j;
for(i=0; i<n; i++)
{
finish[i] = 0;
}
/*find need matrix */ for(i=0; i<n; i++)
{
for(j=0; j<r; j++)
{
need[i][j]= max[i][j] - alloc[i][j];
}
}
while(flag)
{
flag=0; for(i=0;i<n;i++)
{
53
Description
Thread synchronization is defined as a mechanism which ensures that two or more
concurrent processes or threads do not simultaneously execute some particular program
segment known as critical section.
Processes’ access to critical section is controlled by using synchronization techniques.
When one thread starts executing the critical section (serialized segment of the
program) the other thread should wait until the first thread finishes.
If proper synchronization techniques are not applied, it may cause a race condition where
the values of variables may be unpredictable
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 this
ensures a synchronized access of shared resources in the code.
Algorithm
1. Create two threads
2. Let the threads share a common resource, say counter
3. Even if thread2 si scheduled to start while thread was not done, access to shared
resource is not done as it is locked by mutex
4. Once thread1 completes, thread2 starts execution
5. Stop
Program
#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* trythis(void *arg)
{
pthread_mutex_lock(&lock);
unsigned long i = 0; counter += 1;
printf("\n Job %d has started\n", counter);
for(i=0; i<(0xFFFFFFFF);i++);
printf("\n Job %d has finished\n", counter);
pthread_mutex_unlock(&lock);
return NULL;
}
55
main()
{
int i = 0;
int error;
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init has failed\n");
return 1;
}
while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &trythis, NULL);
if (error != 0)
printf("\nThread can't be created :[%s]", strerror(error));
i++;
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_mutex_destroy(&lock);
return 0;
}
Output
$ gcc filename.c -lpthread
$ ./a.out
Job 1 started
Job 1 finished
Job 2 started
Job 2 finished
Result
Thus concurrent threads were synchronized using mutex lock.
Memory Management
The first-fit, best-fit, or worst-fit strategy is used to select a free hole from the set of
available holes.
First fit
Allocate the first hole that is big enough.
Searching starts from the beginning of set of holes.
Algorithm
1. Declare structures hole and process to hold information about set of holes and processes
respectively.
2. Get number of holes, say nh.
3. Get the size of each hole
4. Get number of processes, say np.
5. Get the memory requirements for each process.
6. Allocate processes to holes, by examining each hole as follows:
a. If hole size > process size then
i. Mark process as allocated to that hole.
ii. Decrement hole size by process size.
56
main()
{
int i, np, nh, j;
printf("Enter the number of Holes : ");
scanf("%d", &nh);
for(i=0; i<nh; i++)
{
printf("Enter size for hole H%d : ",i);
scanf("%d", &h[i].size);
h[i].actual = h[i].size;
}
printf("\nEnter number of process : " );
scanf("%d",&np);
for(i=0;i<np;i++)
{
printf("enter the size of process P%d : ",i);
scanf("%d", &p[i].size);
p[i].flag = 0;
}
for(i=0; i<np; i++)
{
for(j=0; j<nh; j++)
{
if(p[i].flag != 1)
{
if(p[i].size <= h[j].size)
{
p[i].flag = 1; p[i].holeid = j;
h[j].size -= p[i].size;
}
}
}
}
printf("\n\tFirst fit\n");
printf("\nProcess\tPSize\tHole");
for(i=0; i<np; i++)
{
if(p[i].flag != 1)
57
Output
Result
Thus processes were allocated memory using first fit method/
Program
#include <stdio.h>
struct process
{
int size; int flag;
int holeid;
} p[10];
struct hole
{
int hid; int size;
int actual;
} h[10];
main()
{
int i, np, nh, j;
void bsort(struct hole[], int);
printf("Enter the number of Holes : ");
scanf("%d", &nh);
for(i=0; i<nh; i++)
{
printf("Enter size for hole H%d : ",i);
scanf("%d", &h[i].size);
h[i].actual = h[i].size; h[i].hid = i;
}
printf("\nEnter number of process : " );
scanf("%d",&np);
for(i=0;i<np;i++)
{
printf("enter the size of process P%d : ",i);
scanf("%d", &p[i].size);
p[i].flag = 0;
}
for(i=0; i<np; i++)
{
bsort(h, nh); for(j=0; j<nh; j++)
{
if(p[i].flag != 1)
{
Output
Result
Thus processes were allocated memory using best fit method.
Program
#include <stdio.h>
#include <math.h>
main()
{
int size, m, n, pgno, pagetable[3]={5,6,7}, i, j, frameno;
double m1;
int ra=0, ofs;
FIFO
Page replacement is based on when the page was brought into memory.
When a page should be replaced, the oldest one is chosen.
Generally, implemented using a FIFO queue.
Simple to implement, but not efficient.
Results in more page faults.
The page-fault may increase, even if frame size is increased (Belady's anomaly)
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
#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);
count++;
for(k=0; k<nf; k++)
printf("%4d", frame[k]);
}
}
printf("\n\nTotal no. of page faults : %d\n",count);
}
Output
Enter length of ref. string : 20
Enter reference string : 1 2 3 4 2 1 5 6 2 1 2 3 7 6 3
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
Total no. of page faults : 10
2 4 5
3 6 1 2 3 5
7
Result 6 1 2 3 7
6
Thus page replacement was implemented using FIFO algorithm.
3
Aim
To implement demand paging for a reference string using LRU method.
LRU
Pages used in the recent past are used as an approximation of future usage.
The page that has not been used for a longer period of time is replaced.
LRU is efficient but not optimal.
Implementation of LRU requires hardware support, such as counters/stack.
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.
63
Program
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 = 1;
break;
}
64
if(dm == 1)
{
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\nTotal 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
Length of Reference string : 15
Enter reference string :
12342 156212 37 63
Enter no. Ref. of frames : 5
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
Total no. of page faults : 8
Result
Thus page replacement was implemented using LRU algorithm.
Program
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct
{
char dname[10];
char fname[25][10];
int fcnt;
}dir;
main()
{
int i, ch; char f[30];
clrscr();
dir.fcnt = 0;
printf("\nEnter name of directory -- ");
scanf("%s", dir.dname);
while(1)
{
printf("\n\n 1. Create File\t2. Delete File\t3. Search File \n4. Display Files\t5. Exit\nEnter
your choice--");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\n Enter the name of the file -- ");
scanf("%s", dir.fname[dir.fcnt]); dir.fcnt++;
break;
case 2:
printf("\n Enter the name of the file -- ");
scanf("%s", f);
for(i=0; i<dir.fcnt; i++)
{
if(strcmp(f, dir.fname[i]) == 0)
{
printf("File %s is deleted ",f);
strcpy(dir.fname[i], dir.fname[dir.fcnt-1]);
66
break;
}
}
if(I == dir.fcnt)
printf("File %s not found", f);
else
dir.fcnt--;
break;
case 3:
printf("\n Enter the name of the file -- ");
scanf("%s", f);
for(i=0; i<dir.fcnt; i++)
{
if(strcmp(f, dir.fname[i]) == 0)
{
printf("File %s is found ", f);
break;
}
}
if(I == dir.fcnt)
printf("File %s not found", f);
break;
case 4:
if(dir.fcnt == 0)
printf("\n Directory Empty");
else
{
printf("\n The Files are -- ");
for(i=0; i<dir.fcnt; i++)
printf("\t%s", dir.fname[i]);
}
break;
default:
exit(0);
}
}
getch();
}
Output
Enter name of directory -- CSE
1. Create File 2. Delete File 3. Search File
4. Display Files 5. Exit
Enter your choice -- 1
Enter the name of the file -- fcfs
Result
Thus files were organized into a single level directory.
Algorithm
1. Display menu
2. Accept choice
3. If choice =1 then
Accept directory name
Create an entry for that directory
4. If choice =2 then
Get directory name
If directory exist then accept filename without collision else report error
5. If choice =3 then
Get directory name
If directory exist then Get filename
If file exist in that directory then delete entry else report error
6. If choice =4 then
Get directory name
If directory exist then Get filename
If file exist in that directory then Display filename else report error
7. If choice =5 then Display files directory-wise
8. If choice =6 then Stop
Program
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct
{
68
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 2
Enter name of the directory -- ECE Enter
name of the file -- amruth File created
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 2
Enter name of the directory -- CSE Enter
name of the file -- kowshik File created
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 2
Enter name of the directory -- CSE Enter
name of the file -- pranesh File created
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 2
Enter name of the directory -- ECE Enter
name of the file -- ajith
File created
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 5
Directory Files
CSE kowshik pranesh
ECE amruth ajith
1. Create Directory 2. Create File 3. Delete File 4. Search File 5. Display 6. Exit
Enter your choice -- 3
Enter name of the directory -- ECE Enter
name of the file -- ajith
File ajith is deleted
Result
Thus user files have been stored in their respective directories and retrieved easily.
Aim
To implement file allocation on free disk space in a contiguous manner.
File Allocation
The three methods of allocating disk space are:
1. Contiguous allocation
2. Linked allocation
3. Indexed allocation
Contiguous
Each file occupies a set of contiguous block on the disk.
The number of disk seeks required is minimal.
The directory contains address of starting block and number of contiguous block (length)
occupied.
Supports both sequential and direct access.
First / best fit is commonly used for selecting a hole.
Algorithm
1. Assume no. of blocks in the disk as 20 and all are free.
2. Display the status of disk blocks before allocation.
3. For each file to be allocated:
a. Get the filename, start address and file length
b. If start + length > 20, then goto step 2.
c. Check to see whether any block in the range (start, start + length-1) is allocated. If
so, then go to step 2.
d. Allocate blocks to the file contiguously from start block to start + length – 1.
71
Program
/* Contiguous Allocation - cntalloc.c */
#include <stdio.h>
#include <string.h>
int num=0, length[10], start[10];
char fid[20][4], a[20][4];
void directory()
{
int i;
printf("\nFile Start Length\n");
for(i=0; i<num; i++)
printf("%-4s %3d %6d\n",fid[i],start[i],length[i]);
}
void display()
{
int i;
for(i=0; i<20; i++) printf("%4d",i);
printf("\n"); for(i=0; i<20; i++)
printf("%4s", a[i]);
}
main()
{
int i,n,k,temp,st,nb,ch,flag;
char id[4];
for(i=0; i<20; i++) strcpy(a[i], "");
printf("Disk space before allocation:\n");
display();
do
{
printf("\nEnter File name (max 3 char) : ");
scanf("%s", id);
printf("Enter start block : ");
scanf("%d", &st);
printf("Enter no. of blocks : ");
scanf("%d", &nb);
strcpy(fid[num], id);
length[num] = nb;
flag = 0;
num++;
printf("\nAny more allocation (1. yes / 2. no)? : ");
scanf("%d", &ch);
} while (ch == 1);
printf("\n\t\t\tContiguous Allocation\n");
printf("Directory:");
directory();
printf("\nDisk space after allocation:\n");
display();
}
Output
Disk space before allocation:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Enter File name (max 3 char) : cp Enter
start block : 14
Enter no. of blocks : 3
Allocation done
Any more allocation (1. yes / 2. no)? : 1
Enter File name (max 3 char) : tr
Enter start block : 18
Enter no. of blocks : 3
Requirement exceeds range
Enter File name (max 3 char) : tr
Enter start block : 10
Enter no. of blocks : 3
Allocation done
Any more allocation (1. yes / 2. no)? : 1
Enter File name (max 3 char) : mv
Enter start block : 0
Enter no. of blocks : 2
Allocation done
Any more allocation (1. yes / 2. no)? : 1
Enter File name (max 3 char) : ps
Enter start block : 12
Enter no. of blocks : 3
Contiguous allocation not possible.
Any more allocation (1. yes / 2. no)? : 2
Contiguous Allocation
Directory:
File Start Length cp
14 3
tr 10 3
mv 0 2
Result
Thus contiguous allocation is done for files with the available free blocks.
73
Linked
Each file is a linked list of disk blocks.
The directory contains a pointer to first and last blocks of the file.
The first block contains a pointer to the second one, second to third and so on.
File size need not be known in advance, as in contiguous allocation.
No external fragmentation.
Supports sequential access only.
Indexed
In indexed allocation, all pointers are put in a single block known as index block.
The directory contains address of the index block.
The ith entry in the index block points to ith block of the file.
Indexed allocation supports direct access.
It suffers from pointer overhead, i.e wastage of space in storing pointers.
Algorithm
1. Get no. of files
2. Accept filenames and no. of blocks fo each file
3. Obtrain start block for each file
4. Obtain other blocks for each file
5. Check block availability before allocation
6. If block is unavailable then report error
7. Accept file name
8. Display linked file allocation blocks for that file
9. Stop
Program
#include <stdio.h>
#include <conio.h>
#include <string.h>
main()
{
static int b[20], i, j, blocks[20][20];
char F[20][20], S[20], ch;
int sb[20], eb[20], x, n;
clrscr();
printf("\n Enter no. of Files ::");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\n Enter file %d name ::", i+1); scanf("%s", &F[i]);
printf("\n Enter No. of blocks::", i+1); scanf("%d",&b[i]);
}
for(i=0;i<n;i++)
{
printf("\n Enter Starting block of file%d::",i+1);
scanf("%d", &sb[i]);
printf("\nEnter blocks for file%d::\n", i+1); for(j=0; j<b[i]-1;)
{
printf("\n Enter the %dblock ::", j+2); scanf("%d", &x);
if(b[i] != 0)
{
74
blocks[i][j] = x; j++;
}
else
printf("\n Invalid block::");
}
}
printf("\nEnter the Filename :");
scanf("%s", &S);
for(i=0; i<n; i++)
{
if(strcmp(F[i],S) == 0)
{
printf("\nFname\tBsize\tStart\tBlocks\n");
printf("\n \n");
printf("\n%s\t%d\t%d\t", F[i], b[i], sb[i]); printf("%d->",sb[i]);
for(j=0; j<b[i]; j++)
{
if(b[i] != 0)
printf("%d->", blocks[i][j]);
}
}
}
printf("\n \n");
getch();
}
Output
Enter no. of Files ::2
Enter file 1 name ::fcfs
Enter No. of blocks::3
Enter file 2 name ::sjf
Enter No. of blocks::2
Enter Starting block of file1::8
Enter blocks for file1::
Enter the 2block ::3
Enter the 3block ::5
Enter Starting block of file2::2
Enter blocks for file2::
Enter the 2block ::6 Enter
the Filename ::fcfs
Fname Bsize Start Blocks
---------------------------------------------
fcfs 3 8 8->3->5
---------------------------------------------
Result
Thus blocks for file were allocation using linked allocation method.