You are on page 1of 89

2023

Lab Manual

Subject:
Operating system
Submitted By:
Adeeba Zahra 2020-BCS-001
Arbab Aslam 2020-BCS-006
Ayesha Khalid 2020-BCS-010
Sehrish Jabeen 2020-BCS-037
Submitted To:
Sir Majid Shafique
Contents
Lab#1: Introduction to Linux........................................................................................................................4
 LAB TASK..........................................................................................................................................4
Lab#2: Introduction to Basic Shell commands...........................................................................................18
 LAB TASKS......................................................................................................................................22
Lab#3: Implementing Linux Commands......................................................................................................25
 LAB TASKS......................................................................................................................................29
Lab#4: Introduction to Shell Programming................................................................................................32
 LAB TASKS......................................................................................................................................39
Lab#5: System Calls....................................................................................................................................42
 LAB TASKS......................................................................................................................................46
Lab#6 & 7: System Calls.............................................................................................................................49
 LAB TASKS......................................................................................................................................53
Lab#8: Interprocess Communication using Pipes......................................................................................64
 LAB TASKS......................................................................................................................................66
Lab#9: Memory Management Schemes-First Fit Best Fit..........................................................................68
 LAB TASKS......................................................................................................................................69
Lab#10: Threads.........................................................................................................................................72
 LAB TASKS......................................................................................................................................76
Lab#11: Shortest Job First..........................................................................................................................78
 LAB TASK........................................................................................................................................79
Lab#12: Round-Robin CPU Scheduling Algorithm..........................................Error! Bookmark not defined.
 LAB TASK............................................................................................Error! Bookmark not defined.

List of Figure:
Figure 1........................................................................................................................................................5
Figure 2........................................................................................................................................................5
Figure 3........................................................................................................................................................6
Figure 4........................................................................................................................................................6
Figure 5........................................................................................................................................................7
Figure 6........................................................................................................................................................7
Figure 7........................................................................................................................................................8
Figure 8........................................................................................................................................................8
Figure 9........................................................................................................................................................9
Figure 10......................................................................................................................................................9
Figure 11....................................................................................................................................................10
Figure 12....................................................................................................................................................10
Figure 13....................................................................................................................................................11
Figure 14....................................................................................................................................................11
Figure 15....................................................................................................................................................11
Lab#1: Introduction to Linux
Linux:
Linux is a generic term refereeing to Unix-like computer operating system based on Linux

Kernel:
Linux is an operating system. (Labs of operating system will be conducted in Linux operating
system.)
The following are the characteristics of Linux:
 Forget about viruses
 Free and unlimited support
 Security
 Flexibility
 Compatibility
 Stability
 Low cost
 Network friendliness
 Fast and easy installation
 Multitasking
 Open Source

Layers in Linux:
Three important parts of Linux are Kernel, Shell and File system.

Kernel:
 Kernel is the heart of the operating system.
 It is the low level core of the System that is the interface between applications and H/W.
 Functions are Manage Memory, I/O devices, allocates the time between user and process;
inter process communication, sets process priority.

Shell:
 The shell is a program that sits on the as an interface between users and kernel.
 It is a command interpreter and also has programming capability of its own.

File System:
 Linux treats everything as a file including hardware devices. Arranged as a directory
hierarchy.
 The top level directory is known as “root (/)”.

LAB TASK
Task#1: Install Linux operating system in your systems.
Figure 1

Figure 2
Figure 3

Figure 4
Figure 5

Figure 6
Figure 7

Figure 8
Figure 9

Figure 10
Figure 11

Figure 12
Figure 13

Figure 14

Figure 15

Task#2: Run Basic Command on windows:


 The Command Prompt

 Typing a Command

 Viewing the Contents of a Directory

 Changing Directories
 Changing Back to the Root Directory

 Creating a Directory
 Deleting a Directory
 Changing Drives
 Copying Files
 Renaming Files

 Deleting Files

Lab#2: Introduction to Basic Shell commands


 Command: cat
“cat" is short for concatenate. This command is used to create, view and concatenate files.
Example:
o cat file1 file2 > file3
This command combines the contents of the first two files into the third file.

 Command: pwd
"pwd" stands for print working directory. It displays your current position in the UNIX/LINUX file
system.
Example:
o pwd
It is simply used to report your current working directory.

 Command: ls
"ls" stands for list. It is used to list information about files and directories.
Example:
o ls
It provides a very basic listing of the files in your current working directory. Filenames beginning
with a decimal are considered hidden files, and they are not shown.
o ls -al
This command provides a long listing of information about all files in the current directory.
This is probably the most used version of the ls command.

 Command: mv
The "mv" command is used to move and rename files.
Examples:
o mv Lab OSLab
This command renames the file "Lab" to the new name "OSLab".
o mv OSLab garbage
This command renames the file "OSLAB1" to the new name "garbage". (Notice that if "garbage" is
a directory, "OSLAB" would be moved into that directory).
To move directory (folder) use the following command mv /source directory /destination directory.
Example
mv /home/mshahzad/Downloads/test /home/mshahzad/Documents/

 Command: rm
The "rm" command is used to remove files and directories.
Examples:
o rm OSLab
This command deletes the file named "OSLab" (assuming you have permission to delete this file).
o rm OSLab1 OSLab2
This command deletes the files named "Chapter1", "Chapter2", and "Chapter3".
o rm -i OSLab1 OSLab2
This command prompt you before deleting any of the three files specified. The -i option stands for
inquire.
You must answer y (for yes) for each file you really want to delete. This can be a safer way to
delete files.
o rm in*
This command deletes all files in the current directory whose filename begins with the characters
"in".
o rm *.txt
This command deletes all files in the current directory whose filename ends with the characters ".txt".
o rm -r Labs
This command deletes the directory named "Labs”. This directory, and all of its' contents, are
erased from the disk, including any sub-directories and files.

 Command: cp
The "cp" command is used to copy files and directories. When using the cp command, you must
always specify both the source and destination of the file(s) to be copied.
Examples:
o cp /home/Lab1 /home/OSLabs
This command copies the "Lab1" file in "/home" to the directory named "/home/OSLabs".

 Command: mkdir
The "mkdir" command is used to create new directories (sub-directories).
Examples:
o mkdir Lab
This command creates a new directory named "Lab" in your current directory. (This example
assumes that you have the proper permissions to create a new sub-directory in your current
working directory.)
o mkdir memos letters
This command creates two new sub-directories (memos, letters) in the current directory.
o mkdir /home/labb
This command creates a new directory named "labb" in the directory "/home".
 Command: rmdir
The "rm" command is used to remove files and directories. (Warning - be very careful when
removing files and directories!)
Examples:
o rm Lab
This command deletes the file named "Lab" (assuming you have permission to delete this file).
o rm Lab1 Lab2
This command deletes the files named "Lab1","Lab2".
o rm -i Lab1 Lab2
This command prompt you before deleting any of the three files specified. The -i option stands for
inquire. You must answer y (for yes) for each file you really want to delete. This can be a safer
way to delete files.
o rm *.txt
This command deletes all files in the current directory whose filename ends with the characters ".txt".
o rm in*
This command deletes all files in the current directory whose filename begins with the characters
"in".
o rm -r labb
This command deletes the directory named "labb". This directory, and all of its' contents, are
erased from the disk, including any sub-directories and files.

 Command: cd, chdir


"cd" stands for change directory. It is the primary command for moving around the file system.
Examples:
o cd /home
This command moves you to the "/home" directory. "/home" becomes your current working
directory.
o cd /h*
Moves you to the "/home" directory - if this is the only directory matching this wildcard pattern.
o cd
Issuing the "cd" command without any arguments moves you to your home directory.

 Command: clear
“Clear” is used to clear the full screen of text, perhaps garbage on the terminal.
Examples:
o clear
This command clears all text on the terminal.
LAB TASKS
Verify that you are in your home directory. Make the directory LABS using the following
command. List the files in the current directory to verify that the directory LABS has been
made correctly. Change directories to LABS. Create the file named file1. List the contents of
the file file1 to the screen. Make a copy of the file file1 under the name file2. Verify that the
files file1 and file2 both exist. List the contents of both file1 and file2 to the monitor screen.
Then delete the file file1. Clear the window. Rename file2 to thefile. Copy thefile to your
home directory. Remove thefile from the current directory. Copy thefile from your home
directory to the current directory. Change directories to your home directory. Remove thefile
from your home directory and from directory LABS. Verify thefile is removed from the
directory LABS. Remove the directory LABS from your home directory with the following
command. Verify that thefile and LABS are gone from your home directory.
 Verify that you are in your home directory.

 Make the directory LABS

 verify that the directory LABS has been made correctly.

 Change directories to LABS.

 Create the file named file1.


 List the contents of the file file1 to the screen.

 Make a copy of the file file1 under the name file2.

 Verify that the files file1 and file2 both exist.

 List the contents of both file1 and file2 to the monitor screen.

 Then delete the file file1.

 Clear the window.


 Rename file2 to thefile.

 Copy thefile to your home directory.

 Remove thefile from the current directory.

 Copy thefile from your home directory to the current directory.

 Change directories to your home directory.


 Remove thefile from your home directory and from directory LABS

 Verify thefile is removed from the directory LABS.

 Remove the directory LABS from your home directory.

 Verify that thefile and LABS are gone from your home directory.

Lab#3: Implementing Linux Commands


 Command: date
This command is used to print system date and time.
Example:
date
 Command: cal
"cal" stands for calendar. It displays the calendar of the current month.
Example:
cal
 Command: cat
It displays the content of the file sequentially with no break.
Example:
cat > file1 (”>” is called Redirection Operator)
It will create the file ‘file1’ and you can enter the text there. Then press “Ctrl+d” for saving the
file. If file1 already exists then it over writes the contents of the file1.
cat >>file1
This example appends more text to already existing file. Then press “Ctrl+d” for saving the file.

 Command: head
It displays the top part/lines of the file. By default it allows 10 lines, but you can change the
settings of the number of lines to be displayed by using –n.
Examples:
head –n25 file1.txt
This example displays the first 25 lines of the file named “file1.txt”.

 Command: tail
It displays the last part/lines of the file. By default it allows 10 lines, but you can change the
settings of the number of lines to be displayed by using –n.
Examples:
tail –n25 file1.txt
This example displays the last 25 lines of the file named “file1.txt”.

 Command: ls -l
This command is use to find permission level of the file.
The permission levels are
“r” Read only
“w” Write
“x” execute
I n case of directory, “x” grants permission to list directory contents.

 Command: chmod
Each file in UNIX/LINUX has an associated permission level. This allows the user to prevent
others from reading/writing/executing their files or directories.
If you own a file, you can change its permissions with “chmod”.
Example
chmod 7 7 7 filename
user group others
Gives user, group and others r, w, x permissions
chmod 770 filename
Gives the user read, write and execute.
Gives group members read and execute.
Gives others no permissions.
Using numeric representations for permissions:
r = 4; w = 2; x = 1; total = 7
Redirection of Input and Output
Mostly all command gives output on screen or take input from keyboard, but in Linux (and in other
OSs also) it's possible to send output to file or to read input from file.

 Command: ls
“ls” command is used to output to screen.
Examples:
ls > file1
This command put output of ls to file1.
It outputs Linux-commands result (output of command or shell script) to file. Note that if file
already exist, it will be overwritten else new file is created.
ls >> file1
This command put output of ls at the end of file1.
It output Linux-commands result (output of command or shell script) to end of file. If file exists, it
will be opened and new information/data will be written to end of file, without losing previous
information/data, and if file does not exist, then new file is created.
ls < file1
This command put contents to command or shell script from the file.
It takes input to Linux-command from file instead of key-board.

 Command: sort
“sort” is used to sort the contents in the file.
Examples:
sort file1
This command sorts the contents in the file1.
sort < file1 > sort_names
cat sort_names
In above example sort command takes input from “file1” file and output of sort command (i.e.
sort_name) is redirected to sort_name file.
tr "[a-z]" "[A-Z]" < file1 > cap_names
cat cap_names
tr command is used to translate all lower case characters to upper-case letters. It takes input from
“file1” file, and tr's output is redirected to cap_names file.

 Shell Scripts and C programming


Variables in Shell
To process our data/information, data must be kept in computers RAM memory. RAM memory is
divided into small locations, and each location had unique number called memory
location/address, which is used to hold our data. Programmer can give a unique name to this
memory location/address called memory variable or variable
In Linux (Shell), there are two types of variable:
1. System variables - Created and maintained by Linux itself. This type of variable defined in
CAPITAL LETTERS.

2. User defined variables (UDV) - Created and maintained by user. This type of variable
defined in lower letters.
To define UDV use following syntax
Syntax: variable name=value
'value' is assigned to given 'variable name' and Value must be on right side = sign.
Example:
no=10
It define variable called ‘no’ having value 10.
vech=Bus
It define variable called 'vech' having value Bus
There are rules for naming variable name (Both UDV and System Variable)
 Variable name must begin with Alphanumeric character or underscore character (_),
followed by one or more Alphanumeric character.
 Don't put spaces on either side of the equal sign when assigning value to variable. e.g.
In following variable declaration there will be no error.
 Variables are case-sensitive, just like filename in Linux. For example: To print or access
value of UDV (User defined variables)
Example:
vech=Bus
echo $vech
It will print the value of vech.

 Shell Arithmetic
Use to perform arithmetic operations.
Examples:
o expr 1 + 3
o expr 2 - 1
These examples print the result.
By default in Linux if particular command/shell script is executed, it return two type of values
which is used to see whether command or shell script executed is successful or not.

(1) If return value is zero (0), command is successful.


(2) If return value is nonzero, command is not successful or some sort of error executing
command/shell script.
LAB TASKS

Task # 1: Create file name students.txt, gstudent.txt, pgstudents.txt Enter students’


names in gstudent.txt and pgstudent.txt. Now create directory having name OSLAB
and copy all files to this directory. Now append the file students.txt with first five
sorted names from pstudent.txt and last five sorted names from gstudent.txt. Then
show the contents of sorted names from file students.txt. Change the permissions of
file students.txt read only and both other files read and execute only.
Output:
Task # 2: Define variable x and y with value 20 and 30 and print it on screen, then
sum, subtract, divide these numbers and print it on the screen.
Output:
Task # 3: Write a program that will displays the fibanocaii series of any given
number. Take the limit from the user.
Output:
Lab#4: Introduction to Shell Programming
 Shell:
A shell is a command line interpreter. It takes commands and executes them. As such, it
implements a programming language.

 Shell scripts
A shell script or a shell program is a series of commands put in a file and executed by the Shell.

 Why and where it is used Why Shell scripts?


Since the user cannot interact with the kernel directly, Shell programming skills are a must to be
able to exploit the power of UNIX to the fullest extent. A shell script can be used for variety of
tasks and some of them are listed below.
 Uses of Shell scripts
1. Customizing your work environment. For Example Every time you login, if you want to see the
current date, a welcome message, and the list of users who have logged in you can write a shell
script for the same.
2. Automating your daily tasks. For example, to back up all the programs at the end of the day.
3. Automating repetitive tasks.
4. Executing important system procedures, like shutting down the system, formatting a
disk, creating a file system etc.
5. Performing some operations on many files.
Shells (bash) Structured Language Constructs
Linux calculator program
(bc) $ bc
After this command bc is started and waiting for your commands, i.e. give it some calculation as
follows type 5 + 2 as:
5+2
7
7 is response of bc i.e. addition of 5 + 2.
5 > 2
1
1 (One?) is response of bc, How? bc compare 5 with 2 as, Is 5 is greater then 2, and print the
answer by showing 1 value. Now try
5 <2
0
0 (Zero) indicates the false i.e. Is 5 is less than 2?
Try other operators in bc to clear your idea and see bc's response Whenever there is any type of
comparison in Linux Shell, it gives only two answer one is YES and other is NO.

In Linux Shell Value Meaning Example


Zero Value (0) Yes/True 0
NON-ZERO Value No/False -1, 32, 55 anything
but not zero

Remember both bc and Linux Shell uses different ways to show True/False values.

Value Shown in bc as Shown in Linux Shell as


True/Yes 1 0
False/No 0 Non - zero value
 if condition:
if condition which is used for decision making in shell script, If given condition is true then
command1 is executed.
Syntax:
if condition then command1 if condition is
true or if exit status of condition is 0 (zero)
...
...
fi
Condition is defined as:
"Condition is nothing but comparison between two values." Example:

Type following commands (assumes you have file called foo)


$ cat foo
A file foo is
created $ echo $?
The cat command return zero (0) i.e. exit status, on successful, this can be used, in if condition as
follows, Write shell script as:

$ cat > showfile


#
#
#Script to print file # if
cat $1
then
echo "File $1, found and successfully echoed" fi

Run above script as:


$ chmod 755 showfile
$./showfile foo
Shell script name is showfile ($0) and foo is argument (which is $1).Then shell compare it as
follows: if cat $1 which is expanded to if cat foo. if cat command finds foo file and if its
successfully shown on screen, it means our cat command is successful and its exist status is 0
(indicates success), So our if condition is also true and hence statement echo " File $1, found and
successfully echoed" is proceed by shell. Now if cat command is not successful then it returns
non-zero value (indicates some sort of failure) and this statement echo " File $1, found and
successfully echoed" is skipped by our shell. if...else...fi
If given condition is true then command1 is executed otherwise command2 is executed.
Syntax:
if condition
then

condition is zero (true - 0)


execute all commands up to else statement
else

if condition is not true then


execute all commands up to fi fi
Example:
Write Script as follows:
isnump_n
#
#
# Script to see whether argument is positive or negative
#
if [ $# -eq 0 ]
then
echo "$0 : You must give one integer" else if
test $1 -gt 0
then
echo "$1 number is positive" else
echo "$1 number is negative" fi Fi

Try it as follows:
$ chmod 755 isnump_n
$ ./isnump_n 5
5 number is positive
$ ./isnump_n -45
-45 number is negative
$ ./isnump_n
./ispos_n : You must give/supply one integers
$ isnump_n 0
number is negative

Example:
You can write the entire if-else construct within either the body of the if statement of the body of
an else statement. This is called the nesting of ifs.
nestedif.sh a=0
echo "1. Unix (Sun Os)" echo "2. Linux (Red Hat)"
echo "Select your os choice [1 or 2]? " read a if [
$a -eq 1 ]
thenecho "You Pick up Unix (Sun Os)" else #### nested if i.e. if within if ######

if [ $a -eq 2 ] then
echo "You Pick up Linux (Red Hat)"else
echo "What you don't like Unix/Linux OS."fi fi
 Nested … if :
You can use the nested ifs as follows also:
test command or [ expr ]
test command or [ expr ] is used to see if an expression is true, and if it is true it return zero(0),
otherwise returns nonzero for false.
Syntax:
test expression OR [ expression ]
Example:
Following script determine whether given argument number is positive.

$ cat > ispostive


#
#
# Script to see whether argument is positive
#
if test $1 -gt 0
then
echo "$1 number is positive" fi

Run it as follows:
$ chmod 755 ispostive
$./ ispostive 5
5 number is positive
$./ispostive -45
Nothing is printed
$./ispostive
./ispostive: test: -gt: unary operator expected
Multilevel if-then-else
Syntax: if condition
then
condition is zero (true - 0)
execute all commands up to elif
statement elif condition1 then
condition1 is zero (true - 0)
execute all commands up to elif
statement elif condition2 then
condition2 is zero (true - 0)
execute all commands up to elif statement else
None of the above condtion,condtion1,condtion2 are true (i.e.
all of the above nonzero or false)
execute all commands up to
fi fi
For multilevel if-then-else statement try the following script:
$ cat > elf
#
# Script to test if..elif...elsegive number "

#
if [ $1 -gt 0 ]; then echo "$1 is positive" elif [ $1 -lt 0 ] then
echo "$1 is negative" elif [ $1 -eq 0 ] then

echo "$1 is zero" else


echo "Opps! $1 is not number, give number" fi

Try above script as follows:


$ chmod 755 elf
$ ./elf 1
$ ./elf -2
$ ./elf 0
$ ./elf a
Here o/p for last sample run:
./elf: [: -gt: unary operator expected
./elf: [: -lt: unary operator expected
./elf: [: -eq: unary operator expected
Opps! a is not number, give number
Above program gives error for last run, here integer comparison is expected therefore error like
"./elf: [: -gt: unary operator expected" occurs, but still our program notify this error to user by
providing message "Opps! a is not number, give number".

LAB TASKS
Task # 1: Write shell script as follows:
cat > trmif
#
# Script to test rm command and exist status
#
if rm $1
then
echo "$1 file deleted"
fi
Press Ctrl + d to save
$ chmod 755 trmif
Answer the following question in reference to above script:
1. foo file exists on your disk and you give command, $ ./trmfi foo what will be output?
2. If bar file not present on your disk and you give command, $ ./trmfi bar what will
be output?
3. And if you type $ ./trmfi What will be output?

Output:
Task # 2: Write a shell script that computes the gross salary of an employee according to the
following:
1. if basic salary is <1500 then HRA=10% of the basic salary.
2. if basic salary is >1500 then HRA=20% of the basic salary.
Output:
Task # 3: Write a shell script to ADD two numbers taken from
argument? Note: show error if no argument or more than 2 arguments are
passed
$ ./ADD 5 6
Output : Sum of 5 and 6 = 5+6 = 11

Output:
Lab#5: System Calls
 System Calls
The System Call is the request for running any Program and for performing any operation on the
system. For making any request a user will prepare a special call which is also known as the
system call. The system call is the fundamental interface between an application and the Linux
kernel. Some of the system calls are:
1. fork()
2. wait()
3. exec()
4. exit()
 fork ()
The fork () system call will spawn a new child process which is an identical process to the parent
except that has a new system process ID. The process is copied in memory from the parent and a
new process structure is assigned by the kernel. The return value of the function is which
discriminates the two threads of execution. A zero is returned by the fork function in the child's
process, and on failure it returns -1.
Example:
#include<stdio.h>

#include <unistd.h> // contains prototype for fork #include


<sys/types.h> // contains prototype for pid_t main()
{ pid_t pid; pid = fork(); if
(pid

== 0) printf("\n I'm the child process");


else if

(pid > 0) printf("\n I'm the parent process. My child pid is %d",
pid); else

perror("error in fork");

The pid_t data type is a signed integer type which is capable of representing a process ID. In the
GNU C Library, this is an int. it can be an int, short int, long int.
There is another function getpid ()that returns the process ID of the current process.
The C library function void perror (const char *str) prints a descriptive error message to stderr.
First the string str is printed followed by a colon then a space.
When the fork is executed, an identical process called the child is created. Then both the parent
and the child process begin execution at the next statement. When a fork is executed, everything
in the parent process is copied to the child process. This includes variable values, code, and file
descriptors. Following the fork, the child and parent processes are completely independent. There
is no guarantee which process will print first. The child process begins execution at the statement
immediately after the fork, not at the beginning of the program. A parent process can be
distinguished from the child process by examining the return value of the fork call. Fork returns a
zero to the child process and the process id of the child process to the parent process. A
process can execute as many forks as desired.
 wait ()

The wait () system call suspends execution of the calling process until one of its children
terminates. This system call blocks calling process until the child process terminates. If child
process has already terminated, the wait () call returns immediately. if the calling process has
multiple child processes, the function returns when one returns. If the call is successful, the
process ID of the
terminating child is returned. If a parent dies before its child, the child (orphan process) is
automatically adopted by the original “init” process whose PID is 1.
wait (int *status);
where status is an integer value where the UNIX system stores the value returned by child process.
Zombie process—a process that has terminated but whose exit status has not yet been received by
its parent process or by init.
Example
#include <stdio.h>

#include<sys/wait.h> // contains prototype for wait


#include<stdlib.h>

void main()

int pid, status; printf("Hello World!\n"); pid


= fork();

if(pid == -1) // check for error in fork


{

printf(“fork failed\n”);

exit(1);

} if(pid

== 0)

{ printf(“Child!\n”);

else

wait(&status); // parent waits for child to finish

printf(“Parent wait Finish!\n”); }


}

exit ( )

terminates the process which calls this function and returns the exit status value, exit (1) for
abnormal termination (when error occurs), exit (0) for normal termination.

 exit ()
The exit() system call ends a process and returns a value to its parent. The prototype for the exit()
system call is:
void exit(status)
int status;
where status is an integer between 0 and 255. This number is returned to the parent via wait() as
the exit status of the process. By convention, when process exits with a status of zero that means
it didn't encounter any problems; when a process exit with a non-zero status that means it did
have problems. exit() is actually not a system routine; it is a library routine that call the system
routine
_exit(). exit() cleans up the standard I/O streams before calling _exit(), so any output that has
been buffered but not yet actually written out is flushed. Calling _exit() instead of exit() will
bypass this cleanup procedure.
exit() does not return.

 exec ()
Typically the exec system call is used after a fork system call by one of the two processes to
replace the process’ memory space with a new executable program. The new process image is
constructed from an ordinary, executable file. There can be no return from a successful exec
because the calling process image is overlaid by the new process image.

execl (const char *file, const char *arg0, ..., const char *argn,char *)0);

Takes the path name of an executable program (binary file) as its first argument. The rest of the
arguments are a list of command line arguments to the new program argv[] The list is terminated
with a null pointer.
Example 1
#include <unistd.h> #include
<stdio.h> void main()

{ printf(“ 1 \n”);

execl(“/bin/ls”,”ls”,NULL);

Example 2
Step 1
Create a file with name prog2.c, compile it and run it.

#include <stdio.h> void main() {


printf(“2\n”); }

Compile it: chmod 755 prog2.c


gcc –o

aa prog2.c

Step 2
#include <stdio.h>
#include <unistd.h> void
main()

{ printf(“1 \n”); execl(“/home/username/aa”,“aa”,NULL);

LAB TASKS
Example#1:

Example#2:

Example#3:
Task 1: Write a program where a child is created to execute a command.
Output:
Task 2: Write a program that spawns two children, then wait for their
completion, and behaves differently according to which one is finished.
Output:
Lab#6 & 7: System Calls
 System Calls
The System Call is the request for running any Program and for performing any operation on the
system. For making any request a user will prepare a special call which is also known as the
system call. The system call is the fundamental interface between an application and the Linux
kernel.

The file structure related system calls available in the UNIX system let you create, open, and
close files, read and write files, randomly access files, alias and remove files, get information
about files, check the accessibility of files, change protections, owner, and group of files, and
control devices. These operations either use a character string that defines the absolute or relative
path name of a file, or a small integer called a file descriptor that identifies the I/O channel.

Some of the file related system calls are:


create(), open(), read(), write(), lseek(), close()
 create ()
This system call lets you to create the file.
The prototype for the create() system call is:
int create(file_name,
mode) char *file_name;
int mode;
where file_name is pointer to a null terminated character string that names the file and mode
defines the file's access permissions. The mode is usually specified as an octal number such as
0666 that would mean read/write permission for owner, group, and others. If the file named by
file_name does not exist, the UNIX system creates it with the specified mode permissions.
However, if the file does exist, its contents are discarded and the mode value is ignored. The
permissions of the existing file are retained.
Example:
#include <stdio.h>

#include <sys/types.h> // contains protype for pid_t

//defines types used by sys/stat.h


#include <sys/stat.h> // defines S_IREAD &
S_IWRITE

int main()

int fd;

fd = creat("datafile.dat", S_IREAD | S_IWRITE); if


(fd == -1)

printf("Error in opening datafile.dat\n");


else
{

printf("datafile.dat opened for read/write access\n");


printf("datafile.dat is currently empty\n");

}
close(fd);
exit (0);

 open ()
This system call can be used to open an existing file or to create a new file if it does not exist
already. The syntax of open has two forms:

int open(const char *path, int flags); int open(const char *path, int flags, mode_t
modes);The first form is normally used to open an existing file, and the second form to open a
file and to create a file if it does not exist already. Both forms returns an integer called the file
descriptor. The file descriptor will be used for reading from and writing to the file. If the file
cannot be opened or created, it returns -1. The first parameter path in both forms specifies the file
name to be opened or created. The second parameter (fl specifies how the file may be used. The
following list some commonly used flag values.

Flags Description
O_RDONLY open for reading only
O_WRONLY open for writing only
O_RDWR open for reading and writing
O_CREAT create file if it does not exist
O_APPEND append on each write
There is a limit on how many files a program can open, because it takes resources to store all
information needed to correctly handle an opened file. So, close all files you don't currently need
to save some resources. The number of files that can be opened varies from system to system and
user to user. Some system allows as many as 2000 files, and sometimes a user's resource is
limited.

Example:
open(“hello.c”,O_RDWR) // hello.c is opened and is ready for reading and writing.
If successful open returns non negative integer else return -1.

 close ()
To close a channel, use the close() system call. The prototype for the close() system call is:
int close(file_descriptor)
int file_descriptor;
where file_descriptor identifies a currently open channel. close() fails if file_descriptor does not
identify a currently open channel.
Example of open() and close():
#include <stdio.h>

#include <fcntl.h> /* defines options flags */

#include <sys/types.h> /* defines types used by sys/stat.h

*/ #include <sys/stat.h> /* defines S_IREAD & S_IWRITE */

#include <stdlib.h>

//static char message[] = "Hello, world";

int main()

{
int fd;

// char buffer[80];

/* open datafile.dat for read/write access (O_RDWR)


create datafile.dat if it does not exist (O_CREAT) return
error if datafile already exists (O_EXCL)
permit read/write access to file (S_IWRITE | S_IREAD) */
fd = open("datafile.dat",O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE); if (fd != -
1)

printf("datafile.dat opened for read/write access\n");


close (fd);

}
else

printf("*** datafile.dat already exists ***\n");


exit (0); }

 read () & write()

The read() system call does all input and the write() system call does all output. When used
together, they provide all the tools necessary to do input and output sequentially. When used with
the lseek() system call, they provide all the tools necessary to do input and output randomly.

Both read() and write() take three arguments. Their prototypes are:
int read(file_descriptor, buffer_pointer, transfer_size) int file_descriptor; char
*buffer_pointer; unsigned transfer_size;
int write(file_descriptor, buffer_pointer,
transfer_size) int file_descriptor; char
*buffer_pointer; unsigned transfer_size;
where file_descriptor identifies the I/O channel, buffer_pointer points to the area in memory
where the data is stored for a read() or where the data is taken for a write(), and transfer_size
defines the maximum number of characters transferred between the file and the buffer. read() and
write() return the number of bytes transferred.

There is no limit on transfer_size, but you must make sure it's safe to copy transfer_size bytes to
or from the memory pointed to by buffer_pointer. A transfer_size of 1 is used to transfer a byte at
a time for so-called "unbuffered" input/output. The most efficient value for transfer_size is the
size of the largest physical record the I/O channel is likely to have to handle.
 lseek ()
The UNIX system file system treats an ordinary file as a sequence of bytes. Generally, a file is
read or written sequentially, that is, from beginning to the end of the file. The UNIX system lets
you read and write anywhere in the file. Known as "random access", this capability is made
possible with the lseek() system call. During file I/O, the UNIX system uses a long integer, also
called a File Pointer, to keep track of the next byte to read or write. This long integer represents
the number of bytes from the beginning of the file to that next character. Random access I/O is
achieved by changing the value of this file pointer using the lseek() system call.

The prototype for lseek() is:


long lseek(file_descriptor, offset, whence) int file_descriptor; long offset;
int whence;
where file_descriptor identifies the I/O channel and offset and whence work together to describe
how to change the file pointer according to the following table:

whence new position

0 offset bytes into the file


1 current position in the file plus offset
2 current end-of-file position plus offset

If successful, lseek() returns a long integer that defines the new file pointer value measured in
bytes from the beginning of the file. If unsuccessful, the file position does not change.

Example of read (), write (), lseek ():

#include <stdio.h>

#include <fcntl.h> / * defines options flags */


#include <sys/types.h> /* defines types used by sys/stat.h */
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */ static char
message[] = "Hello, world";

int main()
{
int fd;
char buffer[80];

/* open datafile.dat for read/write access (O_RDWR)


create datafile.dat if it does not exist (O_CREAT) return
error if datafile already exists (O_EXCL) permit read/write
access to file (S_IWRITE | S_IREAD)
*/
fd = open("datafile.dat",O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE); if (fd != -
1)

printf("datafile.dat opened for read/write access\n");

write(fd, message, sizeof(message));

lseek(fd, 0L, 0); /* go back to the beginning of the file */


if (read(fd, buffer, sizeof(message)) == sizeof(message))
printf("\"%s\" was written to datafile.dat\n", buffer); else

printf("*** error reading datafile.dat ***\n");


close (fd);

}
else

printf("*** datafile.dat already exists ***\n");


exit (0);

LAB TASKS
Example#1
Output:

Example#2

Output:

Example#3
Output:
Example#4
Task#1: Create a file named “oslab.txt” present in directory named “os”
located in home directory.
Output:

Task#2.1: Open a file for reading named “oslab.txt” present in directory named
“os” located in home directory.

Output:

Task#2.2: Open a new file for reading and writing, whose location is provided
by the user.
Task#3.1: Read at most 100 bytes into buf from standard input.
Task#3.2: Read bytes into temporary buffer buf from file whose location and
name is entered by the user as an argument at the time of execution.
Task#4.1: Write “read” and “write” commands for the following conditions
Read data from standard input and write it on standard output. Read data
from the file, given as an argument by the user and write it on standard output.
Start reading from the end of file.
Output:

Task#4.2: Read data from standard input and write it on the file given as an
argument by the user.
Output:

Task#4.3: Read and write data from the files named “lab3.c” and “lab4.c”
respectively. The files are present in the directory “lab”, located in the home
directory.
Output:

Task 5: Write complete code to copy the contents of an input file to an output
file using system calls where the input and output files names are entered by the
user.
Output:

Task 6: What is the purpose of link and unlink system call.


The system call is used within the C language to deletes a title or name from any file system, e.g.,
Linux system. It eliminates the entry or link of a specific file or directory from the file system,
which shows that the file or folder has been deleted, which is not the case. If the file or folder is
currently not working or opened, that file or folder may be deleted upon usage in unlink() system
call. That’s the case when the file or folder link count is 0.

Lab#8: Interprocess Communication using Pipes


 Inter Process Communication:
Interprocess communication (IPC) is a mechanism for processes to communicate and to
synchronize their actions. It is a set of programming interfaces that allows a programmer to
coordinate activities among different program processes that can run concurrently in an operating
system. This allows a program to handle many user requests at the same time. Since even a single
user request may result in multiple processes running in the operating system on the user's behalf,
the processes need to communicate with each other. The IPC interfaces make this possible. Each
IPC method has its own advantages and limitations so it is not unusual for a single program to use
all of the IPC methods.
IPC methods include pipes and named pipes; message queuing; semaphores; shared memory; and
sockets.

 Pipes:
A pipe is a communication channel between two ends. It is mostly used to communicate between
processes running within a computer. It is a communication device that permits unidirectional
communication. Data written to the “write end” of the pipe is read back from the “read end”.
Pipes are serial devices; the data is always read from the pipe in the same order it was written.
A pipe’s data capacity is limited. If the writer process writes faster than the reader process
consumes the data, and if the pipe cannot store more data, the writer process blocks until more
capacity becomes available. If the reader tries to read but no data is available, it blocks until data
becomes available.
Thus, the pipe automatically synchronizes the two processes.

 Creating Pipes:
To create a pipe, invoke the pipe command. Supply an integer array of size 2.The call to pipe
stores the reading file descriptor in array position 0 and the writing file descriptor in position 1.
For example, consider the code: int pipe_fds[2]; int read_fd; int write_fd; pipe (pipe_fds); read_fd
= pipe_fds[0]; write_fd = pipe_fds[1];
Data written to the file descriptor read_fd can be read back from write_fd.
To create a simple pipe with C, we make use of the pipe () system call. It takes a single argument,
which is an array of two integers. If successful, the array will contain two new file descriptors to
be used for the pipeline.
System call: pipe ();
Prototype: int pipe (int fd[2]
); It returns 0 on success, -1
on error.
NOTE:
o fd[0] is set up for reading
o fd[1] is set up for writing

The first integer in the array (element 0) is set up and opened for reading, while the second integer
(element 1) is set up and opened for writing. Visually speaking, the output of fd1 becomes the
input for fd0.
Some of the system calls that are used in piping are:
Open Open or create a file
Read Read from a pipe
Write Write data to a pipe
Close Close/destroy a pipe
Pipe Create a pipe for IPC
Example:

//Parent creates pipe, forks a child, child writes into pipe, and parent reads from pipe
#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>
#include <string.h> main()

{ int pipefd[2], pid, n, rc, nr, status;


char *testString = "Hello, world!\n";
char buf[1024]; rc = pipe (pipefd);
if (rc < 0)

{
perror("pipe");

}
pid = fork ();
if (pid < 0)

{
perror("fork");

if (pid == 0)

{ /* Child’s Code */ close(pipefd[0]);

write(pipefd[1], testString, strlen(testString));

close(pipefd[1]); }

else /* Parent’s Code */


{
close(pipefd[1]);
n = strlen(testString); nr =
read(pipefd[0], buf, n); rc
= write(1, buf, nr);
wait(&status);

printf("End!\n"); }

return(0); }

LAB TASKS

Task#1: Compute the Factorial of a number using IPC (PIPE implementation).


Parent creates pipe
Forks a child
Parent writes into pipe (the number whose factorial is to be calculated, take the
number from the user)
Child reads from pipe and compute the Factorial of a number written by
Parent

Output:
Task#2: Using pipes, parent read data from one file, and child write data into
another file.

Output:
Lab#9: Memory Management Schemes-First Fit Best Fit
 Memory Management Algorithms
In an environment that supports dynamic memory allocation, the memory manager must keep a
record of the usage of each allocatable block of memory. This record could be kept by using almost
any data structure that implements linked lists. An obvious implementation is to define a free list of
block descriptors, with each descriptor containing a pointer to the next descriptor, a pointer to the
block, and the length of the block. The memory manager keeps a free list pointer and inserts entries
into the list in some order conducive to its allocation strategy. A number of strategies are used to
allocate space to the processes that are competing for memory.

 First Fit
Another strategy is first fit, which simply scans the free list until a large enough hole is found.
Despite the name, first-fit is generally better than best-fit because it leads to less fragmentation.
Small holes tend to accumulate near the beginning of the free list, making the memory allocator
search farther and farther each time. Solution: Next Fit

 Best Fit
The allocator places a process in the smallest block of unallocated memory in which it will fit. It
requires an expensive search of the entire free list to find the best hole. More importantly, it leads
to the creation of lots of little holes that are not big enough to satisfy any requests. This situation is
called fragmentation, and is a problem for all memory-management strategies, although it is
particularly bad for best-fit. One way to avoid making little holes is to give the client a bigger
block than it asked for. For example, we might round all requests up to the next larger multiple of
64 bytes. That doesn't make the fragmentation go away, it just hides it.
 Unusable space in the form of holes is called external fragmentation
 Unusable space in the form of holes is called external fragmentation

Algorithm:
1. Start the program.
2. Get the number of segments and size.
3. Get the memory requirement and select the option.
4. If the option is ‘2’ call first fit function.
5. If the option is ‘1’ call best fit function.
6. Otherwise exit.
7. For first fit, allocate the process to first possible segment which is free.
8. For best fit, do the following steps.
a. Sorts the segments according to their sizes.
b. Allocate the process to the segment which is equal to or slightly greater than the process size.
2. Stop the program.
LAB TASKS
Task#1
// C implementation of First - Fit algorithm
#include<stdio.h>
// Function to allocate memory to
// blocks as per First fit algorithm
void firstFit(int blockSize[], int m, int processSize[], int n)
{
int i, j;
// Stores block id of the
// block allocated to a process
int allocation[n];
// Initially no block is assigned to any process
for(i = 0; i < n; i++)
{
allocation[i] = -1;
}
// pick each process and find suitable blocks
// according to its size ad assign to it
for (i = 0; i < n; i++) //here, n -> number of processes
{
for (j = 0; j < m; j++) //here, m -> number of blocks
{
if (blockSize[j] >= processSize[i])
{
// allocating block j to the ith process
allocation[i] = j;
// Reduce available memory in this block.
blockSize[j] -= processSize[i];
break; //go to the next process in the queue
}
}
}
printf("\nProcess No.\tProcess Size\tBlock no.\n");
for (int i = 0; i < n; i++)
{
printf(" %i\t\t\t", i+1); printf("%i\
t\t\t\t", processSize[i]); if
(allocation[i] != -1)
printf("%i", allocation[i] + 1);
else
printf("Not Allocated");
printf("\n");
}
}
// Driver code
int main()
{
int m; //number of blocks in the memory
int n; //number of processes in the input queue
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
m = sizeof(blockSize) / sizeof(blockSize[0]);
n = sizeof(processSize) / sizeof(processSize[0]);
firstFit(blockSize, m, processSize, n);

return 0 ;
}
Output:

Task#2
int main()
{
int m; //number of blocks in the memory
int n; //number of processes in the input queue
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426, 312};
m = sizeof(blockSize) / sizeof(blockSize[0]);
n = sizeof(processSize) / sizeof(processSize[0]);
firstFit(blockSize, m, processSize, n);
return 0 ;
}

Output:

Task#2
// Driver code
int main()
{
int m; //number of blocks in the memory
int n; //number of processes in the input queue
int blockSize[] = {100, 500, 200, 300, 600, 400};
int processSize[] = {212, 417, 112, 426, 312, 326, 410};
m = sizeof(blockSize) / sizeof(blockSize[0]);
n = sizeof(processSize) / sizeof(processSize[0]);
firstFit(blockSize, m, processSize, n);
return 0 ;
}

Output:

Lab#10: Threads

A thread is a single sequence stream within in a process. Threads have some of the properties of
processes; they are sometimes called lightweight processes. In a process, threads allow multiple
executions of streams. In many respect, threads are popular way to improve application through
parallelism. The CPU switches rapidly back and forth among the threads giving illusion that the
threads are running in parallel. Like a traditional process i.e., process with one thread, a thread can
be in any of several states (Running, Blocked, Ready or Terminated). Each thread has its own
stack. Since thread will generally call different procedures and thus a different execution history.
This is why thread needs its own stack. An operating system that has thread facility, the basic unit
of CPU utilization is a thread. A thread has or consists of a program counter (PC), a register set,
and a stack space. Threads are not independent of one other like processes as a result threads shares
with other threads their code section, data section, OS resources also known as task, such as open
files and signals.

Multithreading is the ability of a program or an operating system process to manage its use by
more than one user at a time and to even manage multiple requests by the same user without
having to have multiple copies of the programming running in the computer. Each user request for
a program or system service (and here a user can also be another program) is kept track of as a
thread with a separate identity. As programs work on behalf of the initial request for that thread
and are interrupted by other requests, the status of work on behalf of that thread is kept track of
until the work is completed.

 Thread Programming:
Some of the basic thread routines are as follows:

 Creation:
int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *),
void *arg);
 Analogous to a combined fork and exec routine
 Returns a thread id in thread.
 When attr is NULL the default thread attributes are used.

Pthread_t: It is defining a thread pointer. When a thread is created identifier is written into the
variable to which the pointer points. This identifier helps to refer to thread.

Pthread_attr_t: It is used to set the thread attributes. If attr is NULL, the default attributes are
used.

Name of function: The name of the function to be started by the thread for execution.
Arguments to be passed to the function: When a new thread is created it executes the
function pointed by the function variable name.
On success, pthread_create ( ) returns 0, and on error, it returns an error number.

 Termination
void pthread_exit(void * return_value);
 Analogous to exit
 The exit routine kills all threads and exits the process
 If the current thread is the last thread then the process terminates
 Returning from the start_routine is equivalent to calling pthread_exit
 Returning from the initial thread main is the equivalent to calling exit

 Detach and Join


int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void ** status);
 Analogous to wait
 Must specify thread. There is no wait any.
 Current thread blocks until thread terminates
 The return value of thread is returned in status
 All threads must be detached or joined with.
pthread_join: It is used to wait for the thread represented in the thread_join call. It waits for the
thread represented in the call to finish executing. It waits for the specified thread to complete, and
gathers information about the thread's exit status.

 Self and Equal


pthread_t pthread_self(void);
int pthread_equal(pthread_1 t1, pthread_t t2);

Example:

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

void *msg_function(void *ptr);


main()
{
pthread_t thread1, thread2;
char *msg1 = "I'm Thread1";
char *msg2 = "I'm Thread2";
int t1, t2;
/* create independent threads each of which will execute function */
t1 = pthread_create(&thread1, NULL, msg_function, (void*)msg1);
t2 = pthread_create(&thread2, NULL, msg_function, (void*)msg2);
/* Wait till threads are complete before main continues. Unless we wait we run the risk of
executing an exit which will terminate the process and all threads before the threads have
completed. */
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
/* value return by the threads */
printf("Thread 1 returns: %d\n", t1);
printf("Thread 2 returns: %d\n", t2);
exit(0);
}
void *msg_function (void *ptr)
{
char *msg;
msg = (char*) ptr;
printf("%s\n", msg);
}
Compile: gcc –o exp exp.c -pthread
Run: ./a

Output

Example 2:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void *msg_function(void *ptr);
main()
{
pthread_t thread1, thread2;
char *msg1 = "I'm Thread1";
char *msg2 = "I'm Thread2";
int t1, t2;
t1 = pthread_create(&thread1, NULL, msg_function,
(void*)msg1); t2 = pthread_create(&thread2, NULL, msg_function,
(void*)msg2); pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("Thread 1 returns: %d\n", t1);
printf("Thread 2 returns: %d\n", t2);
exit(0);
}
void *msg_function (void *ptr)
{
char *msg;
int i;
msg = (char*) ptr;
for (i=0; i<5; i++)
{
printf("%s - %d\n", msg,i);
/* sleep() causes the current thread to suspend execution for a specified period. This is an efficient
means of making processor time available to the other threads of an application or other
applications that might be running on a computer system. */
sleep(1);
}
}

Output

LAB TASKS

Write a program that sorts the array in ascending order using bubble sort and
descending order using selection sort by means of multithreading.
#include <stdio.h>
#include<stdlib.h>
#include<pthread.h>
void *bubbleSort();
void *SelectionSort();
void *bubbleSort()
{
int arr[]={3,2,5,1,6};
int i, j,k,temp;
for (i = 0; i < 5-1; i++)
// Last i elements are already in place
for (j = 0; j < 5-i-1; j++)
if (arr[j] > arr[j+1])
{ temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
printf("Buble sort ");
for (k=0; k < 5; k++)
printf("%d ",arr[k]);
}
void *SelectionSort(){
int arr[]={3,2,5,1,6};
int i, j,k,temp;
for(i=0;i<5;i++)
{ for(j=i+1;j<5;j++){
if(arr[i]< arr[j]){
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;}
}
}
printf("\nSelection sort");
for(i=0;i<5;i++)
printf(" %d",arr[i]);
}
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL,bubbleSort,NULL);
pthread_create(&thread2, NULL, SelectionSort,NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}

Output:

Lab#11: Shortest Job First

Associate with each process the length of its next CPU burst. Use these lengths to schedule the
process with the shortest time.

Two schemes:
Non preemptive: Once CPU given to the process it cannot be preempted until completes its
CPU burst

Preemptive: If a new process arrives with CPU burst length less than remaining time of current
executing process, preempt. This scheme is known as the Shortest-Remaining-Time-First (SRTF)
SJF is optimal gives minimum average waiting time for a given set of processes
Suppose that there are four processes P1, P2, P3, P4

Proces Arriva Burst


s l
Time
Time
P1 0 7
P2 2 4
P3 4 1
P3 5 4

The Gantt chart for the schedule is

Average waiting time: (0+6+3+7)/4=4

Algorithm:
 Take total no. of processes from user.
 Take Name, Arrival Time and Burst Time for each process.
 Select the process which have shortest burst will execute first.
 If all processes arrive at 0 time interval than process with the smallest CPU
Burst will execute first.
 If processes arrive at different time intervals than CPU will be given to the
process that will arrive first and let the other processes to be in queue.
 If two processes have same burst length then FCFS scheduling algorithm will be
used.
 Sort the processes in ascending order of their CPU Burst.
 Compute Waiting Time & Turnaround Time for each process.
 Compute Average Waiting Time & Turnaround Time of processes.
 Display Average Waiting and Turnaround Time of processes.
 Display the Gantt chart.
LAB TASK

Example 1:

#include<stdio.h>
int main()
{
int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;float avg_wt,avg_tat;
printf("Enter number of process:");scanf("%d",&n);
printf("\nEnter Burst Time:\n");for(i=0;i<n;i++)
{
printf("p%d:",i+1);
scanf("%d",&bt[i]);p[i]=i+1;
}
//sorting of burst times
for(i=0;i<n;i++)
{
pos=i; for(j=i+1;j<n;j++)
{
if(bt[j]<bt[pos])pos=j;
}
temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}
wt[0]=0;
for(i=1;i<n;i++)
{
wt[i]=0;
for(j=0;j<i;j++)
wt[i]+=bt[j];
total+=wt[i];
}
avg_wt=(float)total/n;total=0;
printf("\nProcess\t Burst Time \tWaiting Time\tTurnaround
Time");
for(i=0;i<n;i++)
{
tat[i]=bt[i]+wt[i]; total+=tat[i];
printf("\np%d\t\t %d\t\t
%d\t\t\t%d",p[i],bt[i],wt[i],tat[i]);
}
avg_tat=(float)total/n;
printf("\n\nAverage Waiting Time=%f",avg_wt); printf("\nAverage
Turnaround Time=%f\n",avg_tat);

Output:
Lab Task
Implement Shortest Job First (Non-Preemptive) CPU Scheduling Algorithm.

#include<stdio.h>
int main()
{
int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;
float avg_wt,avg_tat;
printf("Enter number of process:");
scanf("%d",&n);
printf("\nEnter Burst Time:\n");
for(i=0;i<n;i++)
{
printf("p%d:",i+1);
scanf("%d",&bt[i]);
p[i]=i+1;
}
//sorting of burst times
for(i=0;i<n;i++)
{
pos=i;
for(j=i+1;j<n;j++)
{
if(bt[j]<bt[pos])
pos=j;
}
temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}
wt[0]=0;
for(i=1;i<n;i++)
{
wt[i]=0; for(j=0;j<i;j+
+)
wt[i]+=bt[j];
total+=wt[i];
}
avg_wt=(float)total/n;
total=0;
printf("\nProcess\t Burst Time \tWaiting Time\tTurnaround Time");
for(i=0;i<n;i++)
Output:

Lab#12: Round-Robin CPU Scheduling Algorithm


The round-robin (RR) scheduling algorithm is designed especially for time-sharing systems. It is
similar to FCFS scheduling, but pre-emption is added to switch between processes. A small unit of
time called time slice or quantum is defined. All runable processes are kept in a circular queue. The
CPU scheduler goes around this queue, allocating the CPU to each process for a time interval of
one quantum. New processes are added to the tail of the queue. Every time a process is granted the
CPU, a context switch occurs, which adds overhead to the process execution time.

Algorithm for Round Robin:


o Get total no. of processes from user.
o Get Name, Arrival Time and Burst Time for each process.
o Get the Quantum/Time Slice.
o Maintain a circular ready queue.
o Make the CPU scheduler goes around the ready queue allocating CPU to each process
for the time slice specified.
o Make the CPU scheduler picks the first process and after quantum expired,
dispatches the process.
✓ If the process have burst less than the time quantum then:
o The process releases the CPU.
o The scheduler will then proceed to the next process in the ready queue.
✓ If the CPU burst of the currently running process is longer than 1 time quantum
then:
▪ The process will be executed for quantum time and then the process will
be put at the tail of the ready queue.
▪ The CPU scheduler will then select the next process in the ready queue.
o Compute Waiting Time & Turnaround Time for each process.
o Calculate Average Waiting Time & Average Turnaround Time of processes.
o Display the Gantt chart.

LAB TASK

Example 1:
#include<stdio.h>
int main()
{
int i, limit, total = 0, x, counter = 0, time_quantum;
int wait_time = 0, turnaround_time = 0, arrival_time[10], burst_time[10], temp[10];
float average_wait_time, average_turnaround_time;
printf(" Enter Total Number of Processes: ");
scanf("%d", &limit);
x = limit;
for(i = 0; i < limit; i++)
{
printf(" \n Enter Details of Process[%d]n ", i + 1);
printf(" Arrival Time: " );
scanf("\n %d", &arrival_time[i]);
printf(" Burst Time: ");
scanf("\n %d", &burst_time[i]);
temp[i] = burst_time[i];
}
printf(" Enter Time Quantum: ");
scanf("\n %d", &time_quantum);
printf(" Process ID Burst Time Turnaround Timet Waiting Time ");
for(total = 0, i = 0; x != 0;)

{
if(temp[i] <= time_quantum && temp[i] > 0)
{
total = total + temp[i];
temp[i] = 0;
counter = 1;
}
else if(temp[i] > 0)
{
temp[i] = temp[i] - time_quantum;
total = total + time_quantum;
}
if(temp[i] == 0 && counter == 1)
{
x--;
printf(" \n Process[%d] %d %d %d", i + 1, burst_time[i], total - arrival_time[i], total -
arrival_time[i]- burst_time[i]);
wait_time = wait_time + total - arrival_time[i] - burst_time[i];
turnaround_time = turnaround_time + total - arrival_time[i];
counter = 0;
if(i == limit - 1)
{
i = 0;
}
else if(arrival_time[i + 1] <= total)
{ i+
+;}
else
{
i = 0;}}
average_wait_time = wait_time * 1.0 / limit;
average_turnaround_time = turnaround_time * 1.0 / limit;

printf(" \n Average Waiting Time: %f ", average_wait_time);


printf(" \n Avg Turnaround Time: %f ", average_turnaround_time);
return 0;
}

Output:

Lab Task
Implement Round Robin CPU Scheduling Algorithm.
#include<stdio.h>
int main()
{
int i, limit, total = 0, x, counter = 0, time_quantum;
int wait_time = 0, turnaround_time = 0, arrival_time[10], burst_time[10], temp[10];
float average_wait_time, average_turnaround_time;
printf("\nEnter Total Number of Processes:\t");
scanf("%d", &limit);
x = limit;
for(i = 0; i < limit; i++)
{
printf("\nEnter Details of Process[%d]\n", i + 1);

printf("Arrival Time:\t");

scanf("%d", &arrival_time[i]);

printf("Burst Time:\t");

scanf("%d", &burst_time[i]);

temp[i] = burst_time[i];
}

printf("\nEnter Time Quantum:\t");


scanf("%d", &time_quantum);
printf("\nProcess ID\t\tBurst Time\t Turnaround Time\t Waiting Time\n");
for(total = 0, i = 0; x != 0;)
{
if(temp[i] <= time_quantum && temp[i] > 0)
{
total = total + temp[i];
temp[i] = 0;
counter = 1;
}
else if(temp[i] > 0)
{
temp[i] = temp[i] - time_quantum;
total = total + time_quantum;
}
if(temp[i] == 0 && counter == 1)
{
x--;
printf("\nProcess[%d]\t\t%d\t\t %d\t\t\t %d", i + 1, burst_time[i], total - arrival_time[i], total -
arrival_time[i] - burst_time[i]);
wait_time = wait_time + total - arrival_time[i] - burst_time[i];
turnaround_time = turnaround_time + total - arrival_time[i];
counter = 0;
}
if(i == limit - 1)
{
i = 0;
}
else if(arrival_time[i + 1] <= total)
{
i++;
}
else
{
i = 0;
}
}

average_wait_time = wait_time * 1.0 / limit;


average_turnaround_time = turnaround_time * 1.0 / limit; printf("\n\
nAverage Waiting Time:\t%f", average_wait_time); printf("\nAvg
Turnaround Time:\t%f\n", average_turnaround_time); return 0;
}
Output:

You might also like