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

Lab 1: Introduction To Linux:: Hand-Out 1: Lab 01 Instructions

Uploaded by

Muhammad Zubair
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views

Lab 1: Introduction To Linux:: Hand-Out 1: Lab 01 Instructions

Uploaded by

Muhammad Zubair
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

CS 2203: Operating Systems Spring 2018

Centre for Advance Studies in Engineering (CASE) Computer Science Department


Hand-out 1: Lab 01 Instructions

Lab 1: Introduction to Linux

Objectives
 Introduce the Linux environment and basic shell commands.

 Write, compile, and execute a “Hello World!” C program in Linux


environment using gcc.

2. Introduction
 Ubuntu 16.04 is installed on the lab computers. Ubuntu is an open-
source Linux-based operating system alternative to Windows. We will
learn the basic desktop environment and common shell commands.
Please login using the credentials provided by the lab instructor.

 Play with the Ubuntu desktop environment.



3. Linux Basics

Linux System
Linux System can be split into two parts:
 Shell
 Kernel
Formally, a Shell is interface between a user and a Linux operating system,
i.e. user interacts with the Linux operating system through the shell.

Kernel is the core of Linux Operating System, which is operational as long as


the computer system is running. The kernel is part of the Linux Operating
system which consists of routines which interact with underlying hardware, and
routines which include system calls handling, process management, scheduling,
signals, the file system, and I/O to storage devices.
Linux File System Hierarchy
Unlike DOS, which permits you to organize your folders (directories) and files anyway you
please, the Linux file system is organized into a standard directory structure. A portion of
the Linux directory structure is pictured below:

Link:

https://www.google.com.pk/search?q=linux+directory+structure&source=lnms&tbm=isch&sa=X&ved=0
ahUKEwjI8Oz2rKLZAhXJNI8KHf69BC8Q_AUICigB#imgrc=6luX9xRzZ28PsM:
CS 2203: Operating Systems Spring 2018
Centre for Advance Studies in Engineering (CASE) Computer Science Department
Hand-out 1: Lab 01 Instructions

/home Users’ home directory

/etc All system administrator commands, configuration files, and


installation control files.

/bin The core set of system commands and programs. Most


systems cannot boot (initially start) without executing some of
the commands in this directory.

/dev The device files used to access system peripherals (for


example, your terminal can be accessed from /dev/tty).

/lib The standard set of programming libraries required by Linux


programs.

/tmp Temporary files created and used by many Linux programs.


/var Log files, spool files etc.

/root The root user’s home directory.

/usr/bin Common commands and programs.

/usr/doc Documentation

/usr/games Games

/usr/include Header files

/usr/info Online documentation

/usr/man Manual pages (help)

/usr/share Shared information

Spring 2018
CS 2203: Operating Systems
Centre for Advance Studies in Engineering (CASE) Computer Science Department
Hand-out 1: Lab 01 Instructions Instructor: Danish Hamid

Basic Commands
In this section, we learn some basic Linux commands e.g., ls, cd, mkdir etc.

Directory Commands
Command Description
ls List the file in the directory, just like dir command in DOS.

Options

-a Display all the files, and subdirectories, including


hidden files.
-l Display detailed information about each file, and
directory.
-r Display files in the reverse order.

Command Description
mkdir directory-name Creates a new directory.
Directory-name specifies the name of the new
directory. If the name doesn’t begin with a slash,
the new directory is created as a subdirectory of
the current working directory. If the name begins
with a slash, the name defines the path from the
root directory to the new directory.

$cd /
Try to use the following command first because this will bring you back
to your home directory
$ cd

shehreyar@shehreyarvirtualBox:/$ mkdir books


This command will create a new directory under the home directory.

Though you have created a sub-directory books, but you are still in the home
(parent directory of books) directory i.e. shehreyar@shehreyar- virtualBox:~$

Spring 2018
CS 2203: Operating Systems
Centre for Advance Studies in Engineering (CASE) Computer Science Department
Hand-out 1: Lab 01 Instructions
How would you go to the directory books?
Command Description

cd Change to another directory.

For Example:
$cd dir-name
To change to any sub-directory under the current directory.

shehreyar@shehreyar- virtualBox:~$cd books


(When Enter is pressed, the prompt becomes)

shehreyar@shehreyar- virtualBox:~/books$
Do you see any difference between the two prompts?
Now you are in books directory, a step down to home. How could you go up?

shehreyar@shehreyar- virtualBox:~/books$ cd .. (there’s space between cd and


..) Now you will again be in your parent directory. And the prompt
becomes: shehreyar@shehreyar- virtualBox:~$

4. C Program in Linux Environment


In this section we write, compile, and execute a Hello Word program in Linux
environment.
Step 1: Create a director; mkdir lab1
Step 2: Switch to director; cd lab1
Step 3: Create a file; touch Hello.c
Step 4: Open the file; gedit Hello.c
Step 5: Type the following source code:
#include<stdio.h>
main()
{
printf("Hello World");
}

Step 6: Compile; gcc –o Outputhello Hello.c


step 7: Execute; ./Outputhello
CS 2203: Operating Systems Spring 2018
Centre for Advance Studies in Engineering (CASE) Computer Science Department
Hand-out 1: Lab 01 Instructions

5. In-Lab Exercises
1. Suppose you need to list the contents of a directory in long listing format.
What parameters should you use with ls to perform this task? Hint:
remember that the man command gives you an online reference manual for
any Linux command.

2. Create the following directory structure:

3. Write a program that odd numbers from 1 to 10 and print their sum, Compile and
run it using gcc.

4. Learn the usage of find command. Hint: remember that the man
command gives you an on line reference manual for any Linux command
and also you can get help from the Internet.
Important note: Don't copy paste exact information .write in your own word after
understanding.

Important: The lab instructor will grade you at the end of the lab.

Submission: A word document containing:

 Front Page that includes your Name, Lab no and Roll no. at least.

 Screen Shot for each question (Note: If there is need of more screen shots in
any task then add all of them in your document).

********** GOOD LUCK **********


CS 2203: Operating Systems January 2013
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 02 Instructions

Lab 2: System Monitoring


Objectives
• Learn the basic CLI and GUI tools to monitor system resources.
• Identify system calls used by programs written in C language.
• Learn to write simple batch/shell scripts.

System Monitoring
In this section, we learn about basic tools (CLI and GUI) to monitor system resources.
1. To identify the available CPU, memory, and disk resources, we can used the following
commands:
(a) cat /proc/cpuinfo (read the CPU information)
(b) cat /proc/meminfo (read the memory (RAM) information)
(c) df -h (_nd out secondary storage (hard-disk) information)
Make sure you are able to identify the total RAM size, disk space, and CPU resource
available.
2. top is a command line program provides a real-time view of the processes running in
the system. It provides system summary and also the list of tasks managing by Linux
kernel. The program is useful to identify the processes running with CPU and memory
utilization. Lets play with the top program:
provide
• Launch a terminal and execute top command.
• You can press q to exit from top program.
• To understand the output generated by the top command, read the article available at
• http://linuxaria.com/howto/understanding-the-top-command-on-linux?lang=en
• Take few minutes to get comfortable with the top program.
3. Lets see a GUI tool to monitor system resources. Ubuntu provides a tool named \System
Monitor", you can launch it by searching in Dash Home. It is similar to Task Manager
(Windows). Take your time to get comfortable with the tool.

C Programs and System Calls


strace is a tool helps to run specified command and traces its interaction with operating
system. We can run any program using strace and identify the system calls it makes. Let’s
practice strace tools:
1. Launch a terminal and run strace ls.
2. Try to read the output generated by the program and identify the system calls.
3. Now create a \Hello World" program in C language. Compile it and run it through
strace. Make sure to identify system call against printf function.
4. Now create a new program in C language, let’s call it \File Reader". Create a new _le
named
filereader.c and type in the following code:
/*
The code is taken from
CS 2203: Operating Systems January 2013
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 02 Instructions

http://www.daniweb.com/software-development/c/code/216411/reading-a-file-
line-by-line
*/
#include <stdio.h>
int main ( void )
{
static const char filename[] = "file.txt";
FILE *file = fopen ( filename, "r" );
if ( file != NULL )
{
char line [ 128 ]; /* or other suitable maximum line size */
while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
{
fputs ( line, stdout ); /* write the line */
}
fclose ( file );
}
else
{
perror ( filename ); /* why didn't the file open? */
}
return 0;
}
5. Compile and execute the program.
6. Now run the program through strace and identify system calls against C functions.
7. Now read the _le using cat command through strace and identify system calls.
8. Do you see any difference in system calls using \File Reader" and cat command?

Simple Batch/Shell Script


In Linux we have a command interpreter known as shell. In this section, we practice to write
a very simple shell script. The objective is to write set of commands in a _le and run the _le
to understand the batch execution interface.
1. Create a _le named hello.sh.
2. Type in the following code:
#!/bin/sh
echo "Hello! Lets Execute ls."
ls
echo "Lets Read System Log File."
head /var/log/syslog
3. Now type sh hello.sh and press enter.
4. Did you understand what happened?
CS 2203: Operating Systems January 2013
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 02 Instructions

In-Lab Exercises
• Create a simple shell script to print "Hello Word!" and a C program to print "Hello Word!". You
need to profile the execution time and system calls used by both programs. Hint! time command
may help to identify the program execution time.
• Download prime.c program from the course homepage. You need to compile and execute it.
Identify the average CPU and memory utilization of the program.
• Write a simple shell script to back up a file. Your program should be able to remove the original
_le and print appropriate messages.

Submission Guidelines
Once you are done with In-lab Exercises, make sure to show them to the lab instructors. You
also need to submit a report on canvas.
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 03 Processes

Lab 3: Process creation and command line arguments

Objectives
• Learn to create processes using fork() system call.
• Learn to use command line arguments.
Credits: https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm

Process Creation
A process is a program in execution. The process which creates another process is called parent
process.
The process which is created is called child process. We can identify process by their unique key
called Process identifier or pid (integer number). In Linux we can use fork() system call to create
processes. By this system call new process is created containing copy of parent process. Both
process (parent and child) continue executing instructions after fork(). The return number of fork()
for new (child) process will be 0 (zero), whereas for parent process value will be nonzero positive
process identi_er. If fork() fails, it return a negative number. In this section, we create a simple
program using fork() to create child process using C language.

1. Create a new file named fork_example.c and type in the following code:

#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
pid = fork(); /* fork a child process */
if( pid <0 ) /* error occurred */
{
printf("Fork Failed");
}
else if (pid == 0) /* child process */
{
printf( Child Process %d \n, pid);
}
else if (pid > 0) /* parent process */
{
printf(Parent Process %d \n, pid);
}
}

1. Compile and execute the program.

2. Try to understand the program

Using Command line Arguments in C


It is possible to pass some values from the command line to your C programs when they are
executed. These values are called command line arguments and many times they are important
for your program especially when you want to control your program from outside instead of hard
coding those values inside the code.
The command line arguments are handled using main() function arguments where argc refers to
the number of arguments passed, and argv[] is a pointer array which points to each argument
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 03 Processes

passed to the program. Following is a simple example which checks if there is any argument
supplied from the command line and take action accordingly

#include <stdio.h>
int main( int argc, char *argv[] )
{
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
return 0;
}
When the above code is compiled and executed with single argument, it produces the following
result.
$./a.out testing
The argument supplied is testing

When the above code is compiled and executed with a two arguments, it produces the following
result.
$./a.out testing1 testing2
Too many arguments supplied.

When the above code is compiled and executed without passing any argument, it produces the
following result.
$./a.out
One argument expected

It should be noted that argv[0] holds the name of the program itself and argv[1] is a pointer to the
first command line argument supplied, and *argv[n] is the last argument. If no arguments are
supplied, argc will be one, and if you pass one argument then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument itself has a space
then you can pass such arguments by putting them inside double quotes "" or single quotes ''. Let
us re-write above example once again where we will print program name and we also pass a
command line argument by putting inside double quotes

#include <stdio.h>
int main( int argc, char *argv[] )
{
printf("Program name %s\n", argv[0]);
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 03 Processes

printf("One argument expected.\n");


}
return 0;
}

When the above code is compiled and executed with a single argument separated by space but
inside double quotes, it produces the following result.

$./a.out "testing1 testing2"


Program name ./a.out
The argument supplied is testing1 testing2

Practice Problem (6 points):

Program 1. Write a program that accepts a number through CLI and generate Fibonacci series in
child process.

Homework Exercise (4 points)

Program 2. Modify program 1 so that it can accepts more than 1 number by CLI.
Like ./myFabonacciSeries 10 12 7
Your program should spawn a new child process for each number to generate its Fibonacci
series.
Sample output:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Parent process starts …
Child process for [10 Fibonacci numbers]
10: 0 0 1 1 2 3 5 8 13 21
Child process exiting for [10 Fibonacci numbers]
Child process for [12 Fibonacci numbers]
12: 0 0 1 1 2 3 5 8 13 21 34 55
Child process exiting for [12 Fibonacci numbers]
Child process for [7 Fibonacci numbers]
7: 0 0 1 1 2 3 5
Child process exiting for [7 Fibonacci numbers]
Parent process exiting …
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Submission Guidelines
You should submit source code and a report in proper format [OS_Lab03] through course
CANVAS account.
CS 2203: Operating Systems March 2018
Center for Advanced Studies in Engineering (CASE) Computer Science Department
Hand-out 4: Lab 04 Instructions

Lab 04: Pipes

Objectives
Learn to use pipes for inter process communication.

Inter Process Communication Using Simple Pipes

Inter- process Communication (IPC) is set of ways to communicate between processes or


threads. Pipe is one of the ways to communicate. Pipe is special file; the child inherits the
pipe from its parent process. Process writes to one end of the pipe (write-end), other reads
from the other end of pipe (read-end). Its unidirectional (one way communication). For two
way communication we use two pipes.

int pipe( int fd[2]);


Two file descriptors are returned through the argument:
fd[0] is open for reading
fd[1] is open for writing.

Typically, a process creates the pipeline, then uses “fork” to create a child process. Each
process now has a copy of the file descriptor array; one process writes data into pipeline,
while the other reads from it
CS 2203: Operating Systems March 2018
Center for Advanced Studies in Engineering (CASE) Computer Science Department
Hand-out 4: Lab 04 Instructions

This gives two read ends and two write ends. The read end of the pipe will not be closed until
both of the read ends are closed, and the write end will not be closed until both the write ends
are closed. Either process can write into the pipe, or either can read from it. Which process
will get what is not known? For predictable behavior, one of the processes must close its read
end, and the other must close its write end. Then it will become a simple pipeline again.
CS 2203: Operating Systems March 2018
Center for Advanced Studies in Engineering (CASE) Computer Science Department
Hand-out 4: Lab 04 Instructions

Reference Code:

1. Create a file named mypipe.c.


2. Type in the following code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2]; pid_t
childpid;
char string[] = "Hello,
world!\n"; char readbuffer[80];
int result = pipe(fd);
if (result < 0 )
{
printf("Error Creating
Pipe"); return 1;
}
childpid = fork();
if(childpid == -1)
{
printf("Error in
fork()"); return 1;
}
if(childpid == 0)
{
close(fd[0]);
/* Send "string" through the output side of pipe
*/ printf ("child writing\n");
write(fd[1], string,
sizeof(string)); return 0;
}
else
{
close(fd[1]);
printf ("parent reading\n");
/* Read in a string from the pipe */
read(fd[0], readbuffer, sizeof(readbuffer));
printf("Received string: %s", readbuffer);
}
return 0;
CS 2203: Operating Systems March 2018
Center for Advanced Studies in Engineering (CASE) Computer Science Department
Hand-out 4: Lab 04 Instructions

In-Lab Exercises

Problem 1: Write a program to calculate factorial of a number. Following constraints must be


fulfilled:
• Use pipe to solve your problem.
• Child process should send number for factorial to parent.
• Parent process is responsible to calculate the factorial.
• parent process should print the final result.

HINT: use atoi () build in function.

Problem 2: Write a program to find that given string is palindrome or not. Following
constraints must be fulfilled:
• Use pipe to solve your problem.
• Parent process should send the string for palindrome to child.
• Child process is responsible to find whether the given string is palindrome
or not.
• Child process should send the final answer to parent.
• Parent process is responsible to print the final answer.

Problem 3: Write a program that counts number of vowels in a string. Following


constraints must be fulfilled:
• Use pipe to solve your problem.
• Child process should send string to parent.
• Parent process is responsible to count the vowels and also print the final answer.

Submission Guidelines: A word document containing:


• Front page with at least name, roll no and Lab no.
• C source code for the above mentioned tasks.
• Output Screenshot.
CS 2203: Operating Systems Spring 2013
Center for Advnace Studies in Engineering (CASE) Computer Science Program
Lab 04 Instructions prepared by:Shehreyar Rashid, Waheed Iqbal
Instructors:

Lab 5
4: File Permissions and Named Pipes

Objectives
• Learn about file and directories permissions in Linux.
• Learn to use pipe operator (|) in Linux.

• Implement Named Pipe for inter process communication.

File Permissions
In operating system, files and directories have specific permissions e.g., read, write, or execute. In this
section, we explore file and directory permissions in Linux operating system. File and directory permissions
are divided into three main entities, owner, group, and other users of the system. Lets identify the file
and folder permissions:
1. Launch a terminal and execute ls -l. The output would be similar to as follows:
-rwxrwxr-x 1 shehreyar shehreyar 7161 2013-01-21 13:13 hello.c.
Figure 1 explains a sample access permission for each user, group, and other users of the system. The
first character in access permission for each file or folder indicates whether the file is a directory (d) or
not (-). The next nine slots are divided into three sets, each of length 3. The first set of three indicates
the owner access, the next set of three indicates the group access, and the last set of three indicates
the access for everybody else (others). The maximum access is represented by rwx, indicating read,
writes, and execute. Whenever a dash (-) appears, an access permission has not been given.

Figure 1: Folder permission to the owner, group, and other users access specifications.

2. Make sure to understand the file and directory permission concept in the Linux.
3. The access permissions can be changed using chmod command. Try to read the manual for chmod
command. Lets practice to change file permissions:
• Create a new file named “test.txt”. Now identify the default permission to the file.
• chmod o+w test.txt (give write permission to others).
• chmod o-w test.txt (remove write permission from others).
• chmod a+w test.txt (give write permission to all).

1
• chmod a-w test.txt (remove write permission to others).
• chmod u+x test.txt (give execute permission to owner).
• chmod go-x test.txt (remove execute permission from group and others).
4. Make sure to practice and get comfortable with changing file permissions.

Pipe Operator (|) in Linux


The pipe operator (|) use to send standard output of one Linux command to another Linux command as a
standard input. Lets practice pipe operator in Linux:
• ls | wc (output of ls reads as input by wc command).
• ls | sort (output of ls reads as input by sort command).
• ls -l | gedit (output of ls loads by gedit into a new document).

Named Pipes
In the labs, we have discussed ordinary pipes which is used to communicate between parent and child
processes. In this lab, we implement Named Pipe to communicate between two different processes.
1. Create a new file named fifo server.c and type in the following code:

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>

int main()
{

int server_to_client;
char *myfifo = "/tmp/fifo";
char buf[100];
mkfifo("/tmp/fifo", 0666);
server_to_client = open(myfifo, O_RDONLY);

printf("Server is ready!\n");
read(server_to_client, buf, 100);
printf("Received string: %s", buf);

close(server_to_client);
unlink(myfifo);
return 0;
}

2. Create a another file named fifo client.c and type in the following code:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

2
int main()
{
int client_to_server;
char *myfifo = "/tmp/fifo";
char str[100] = "Test Message From Client\n";

client_to_server = open(myfifo, O_WRONLY);


write(client_to_server, str, sizeof(str));

close(client_to_server);
return 0;
}

3. Compile the server and client programs. You need to open two terminals to run server and client
programs simultaneously.

4. The lab instructor will help you to understand the program.

In-lab Exercises
1. Update the Named Pipe program to send multiple messages to the server.

2. Update the Named Pipe program to make it bidirectional. Server must send an acknowledgment
message to the client. Hint! You may need to create two FIFO queues.

Submission Guidelines
Once you are done with In-lab Exercises, make sure to show them to the lab instructors. You also need
to submit a report through email to [[email protected]
course canvas account ] in a format available at the course
home page.

3
Lab 6: Threads creation using posix api
CS 2203: Operating Systems Spring 2017
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 06 Threads creation using posix api
Lab Instructors: Waqas Ahmed, Danish Khatak

Objectives

• Learn to create threads in a process using posix pthread api.

Credits: Operating System concepts by silbershatz 9th edition.

Problem 4.26
The Fibonacci sequence is the series of numbers 0, 1, 1, 2, 3, 5, 8, ....
Formally, it can be expressed as:

Write a multithreaded program that generates the Fibonacci sequence. This program should work
as follows: On the command line, the user will enter the number of Fibonacci numbers that the
program is to generate. The program will then create a separate thread that will generate the
Fibonacci numbers, placing the sequence in data that can be shared by the threads (an array is
probably the most convenient data structure). When the thread finishes execution, the parent thread
will output the sequence generated by the child thread. Because the
parent thread cannot begin outputting the Fibonacci sequence until the child thread finishes, the
parent thread will have to wait for the child thread to finish.

Problem 4.21

Write a multithreaded program that calculates various statistical values for a list of
numbers. This program will be passed a series of numbers on the command line and will then
create three separate worker threads. One thread will determine the average of the numbers, the
second will determine the maximum value, and the third will determine the minimum value. For
example, suppose your program is passed the integers

90 81 78 95 79 72 85

The program will report

The average value is 82


The minimum value is 72
The maximum value is 95

The variables representing the average, minimum, and maximum values will be stored globally.
The worker threads will set these values, and the parent thread will output the values once the
workers have exited. (We could obviously expand this program by creating additional threads that
determine other statistical values, such as median and standard deviation.)
Problem 4.24

Write a multithreaded program that outputs prime numbers. This program should work as
follows: The user will run the program and will enter a number on the command line. The program
will then create a separate thread that outputs all the prime numbers less than or equal to the number
entered by the user.
Lab 7: Implementation of Single-Producer Multi-Consumer problem
between pthreads
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 06 Producer-Consumer problem implementation
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn to share data between multiple threads using producer-consumer problem

Credits: Operating System concepts by silbershatz 9th edition.

One solution to the producer–consumer problem (Threads of same process) uses data
segment or heap segment of process address space to share data among them. To allow producer
and consumer processes to run concurrently, we must have available a buffer of items that can be
filled by the producer and emptied by the consumer. This buffer will reside in a region of memory
that is shared by the producer and consumer threads.
A producer can produce one item while the consumer is consuming another item. The
producer and consumer must be synchronized, so that the consumer does not try to consume an
item that has not yet been produced. Two types of buffers can be used. The unbounded buffer
places no practical limit on the size of the buffer. The consumer may have to wait for new items,
but the producer can always produce new items. The bounded buffer assumes a fixed buffer size.
In this case, the consumer must wait if the buffer is empty, and the producer must wait if the buffer
is full.
Let’s look more closely at the bounded buffer illustrates that how we can share data items
using circular queue that reside in data segment of process address space.

Figure 1.
The shared buffer is implemented as a circular array with two logical pointers or shared
index variables: in and out. The variable in points to the next free position in the buffer; out points
to the first full position in the buffer. The buffer is empty when in == out; the buffer is full when
((in + 1) % BUFFER SIZE) == out. The code for the producer process is shown in Figure 1, and
the code for the consumer process is shown in Figure 2. The producer thread has a local variable
next produced in which the new item to be produced is stored. The consumer thread has a local variable next
consumed in which the item to be consumed is stored. This scheme allows at most BUFFER SIZE − 1 items in
the buffer at the same time.
Figure 2.

One issue this illustration does not address concerns the situation in which both the producer process and the
consumer process attempt to access the shared buffer concurrently. In Next labs, we discuss and implement
how synchronization among cooperating processes/threads can be implemented effectively in a shared memory
environment.

Problem 1

Write a program that initiate two threads, producer and consumer. Producer should produce
random numbers using rand( ) function between 0 and 1000. It must block indefinitely if circular
queue is full. Consumer thread will read numbers from queue and determine that each number is
Armstrong-number or not.
Set thread cancelation point in both producer and consumer threads so that you can cancel each
thread at some point, then main thread get a chance to output meaning full statistics.

Problem 2
Include 2nd consumer thread to share some load with 1st consumer thread, compare your statistics
with single-producer/single-consumer values. Do you see any problem? if any, then elaborate!
CS&SE Operating System
Lab 05 : Implementation of Process scheduling
algorithm; FIFO, SJF, RR, PPS

Statement Purpose:
This lab will give you the concept and implementation of Process scheduling algorithm for both
preemptive and non-preemptive.

Activity Outcomes:
This lab teaches you the following topics related to Process scheduling algorithms:

1. First Come First Serve

2. Shortest Remaining Job First

3. Round Robin

4. Preemptive Priority Scheduling

5. Multi-level queue scheduling algorithm

Introduction
Associate with each process the length of its next CPU burst. Use these lengths to schedule the process
with the shortest time. Scheduling algorithms are used when more than one process is executable and
the OS has to decide which one to run first.

Terms used
1. Submit time :The process at which the process is given to CPU
2. Burst time : The amount of time each process takes for execution
3. Response time:The difference between the time when the processstarts execution and the
submit time.
4. Turnaround time:The difference between the time when the process completes execution
and the submit 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
CS&SE Operating System
Lab 05 : Implementation of Process scheduling
algorithm; FIFO, SJF, RR, PPS

CPU Sceduling Algorithm:

1. First Come First Serve(FCFS)


The processes are executed in the order in which they have been submitted.
2. Shortest Job First(SJF)
The processes are checked at each arrival time and the process which have the shortest
remainingburst time at that moment gets executed first. This is a preemptive & non-preemptive
algorithm
3. Round Robin (RR)
Each process is assigned a time interval called its quantum(time slice). If the process is still
running at the end of the quantum the CPU is preempted and given to another process, and this
continues in circular fashion, till all the processes are completely executed.
4. Preemptive Priority Scheduling
Each process is assigned a priority and executable process with highest priority is allowed to
run.
5. Multilevel Queue Scheduling

Multi-level queue scheduling algorithm is used in scenarios where the processes can be classified
into groups based on property like process type, CPU time, IO access, memory size, etc. In a multi-
level queue scheduling algorithm, there will be 'n' number of queues, where 'n' is the number of
groups the processes are classified into. Each queue will be assigned a priority and will have its
own scheduling algorithm like round-robin scheduling or FCFS. For the process in a queue to
execute, all the queues of priority higher than it should be empty, meaning the process in those
high priority queues should have completed its execution. In this scheduling algorithm, once
assigned to a queue, the process will not move to any other queues.

Lab Activity 1:
Write a C program to simulate the following non-preemptive CPU scheduling algorithms to find
turnaround time and waiting time for the above problem.
a) FCFS b) SJF c) Round Robin d) Priority

Solution:

a) FCFS CPU SCHEDULING ALGORITHM

#include<stdio.h>
#include<conio.h>
void main()
{
int bt[20], wt[20], tat[20], i, n;
CS&SE Operating System
Lab 05 : Implementation of Process scheduling
algorithm; FIFO, SJF, RR, PPS

float wtavg, tatavg;


clrscr();
printf("\nEnter the number of processes --");
scanf("%d", &n);
for(i=0;i<n;i++)
{
printf("\nEnter Burst Time for Process %d --", i);
scanf("%d", &bt[i]);
}
wt[0] =wtavg = 0;
tat[0] = tatavg = bt[0];
for(i=1;i<n;i++)
{
wt[i] =wt[i-1] +bt[i-1];
tat[i] = tat[i-1] +bt[i];
wtavg = wtavg + wt[i];
tatavg = tatavg + tat[i];
}
printf("\t PROCESS \tBURST TIME \t WAITING TIM \t TURNAROUND TIME\n");
for(i=0;i<n;i++)
print"\n\t P%d \t\t %d \t\t %d \t\t %d", i, bt[i], wt[i], tat[i]);
printf("\nAverage Waiting Time --%f", wtavg/n);
printf("\nAverage Turnaround Time --%f", tatavg/n);
getch();
}

INPUT
Enter the number of processes –3
Enter Burst Time for Process 0 -24
Enter Burst Time for Process 1 --3
Enter Burst Time for Process 2 --3

OUTPUT

PROCESS BURST TIME WAITING TIME TURNAROUND TIME


P0 24 0 24
P1 3 24 27
P2 3 27 30
Average Waiting Time --17.000000
Average Turnaround Time --27.000000
CS&SE Operating System
Lab 05 : Implementation of Process scheduling
algorithm; FIFO, SJF, RR, PPS

Lab Tasks:
1) SJF CPU SCHEDULING ALGORITHM
INPUT
Enter the number of processes --4
Enter Burst Time for Process 0 --6
Enter Burst Time for Process 1 --8
Enter Burst Time for Process 2 --7
Enter Burst Time for Process 3 --3

OUTPUT
PROCESS BURST TIME WAITING TIME TURNAROUND TIME
P3 3 0 3
P0 6 3 9
P2 7 9 16
P1 8 16 24

Average Waiting Time --7.000000


Average Turnaround Time -- 13.00000

2) Implement PRIORITY CPU SCHEDULING ALGORITHM


INPUT
Enter the number of processes -- 5
Enter the Burst Time & Priority of Process 0 ---10 3
Enter the Burst Time & Priority of Process 1 --- 1 1
Enter the Burst Time & Priority of Process 2 --- 2 4
Enter the Burst Time & Priority of Process 3 ---1 5
Enter the Burst Time & Priority of Process 4 ---5 2

OUTPUT
PROCESS PRIORITY BURST TIME WAITING TIME TURNAROUNDTIME
1 1 1 0 1
4 2 5 1 6
0 3 10 6 16
2 4 2 16 18
3 5 1 18 19

Average Waiting Time is --- 8.200000

Average Turnaround Time is ---12.00000


Lab 9: Synchronization and CPU affinity for threads
CS 2203: Operating Systems Spring 2017
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 9: Synchronization and Thread affinity
Lab Instructors: Waqas Ahmed, Danish Khatak

Objectives

• Learn to understand/implement software solution for synchronization.


• Learn to set CPU affinity for different threads in linux.

Credits: Operating System concepts by silbershatz 9th edition.


http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html

Peterson’s Solution [topic 5.3 page 207]


Figure given below illustrate a classic software-based solution to the critical-section problem
known as Peterson’s solution. Because of the way modern computer architectures perform basic
machine-language instructions, such as load and store, there are no guarantees that Peterson’s
solution will work correctly on such architectures. However, we present the solution because it
provides a good algorithmic description of solving the critical-section problem and illustrates
some of the complexities involved in designing software that addresses the requirements of
mutual exclusion, progress, and bounded waiting.

Peterson’s solution is restricted to two processes that alternate execution between their critical
sections and remainder sections. The processes are numbered P 0 and P 1. For convenience,
when presenting P i , we use P j to denote the other process; that is, j equals 1 − i .
Peterson’s solution requires the two processes to share two data items:

int turn;
boolean flag[2];
The variable turn indicates whose turn it is to enter its critical section. That is, if turn == i , then
process P i is allowed to execute in its critical section. The flag array is used to indicate if a
process is ready to enter its critical section. For example, if flag[i] is true , this value indicates
that Pi is ready to enter its critical section. With an explanation of these data structures complete,
we are now ready to describe the algorithm shown in Figure 5.2.

Lab Exercises:

1) Write a program to demonstrate whether peterson's solution work correctly in multi-


processor environment or not. You need to define a single global variable “data” and
initialized it to 0. Create two threads using pthread_create function. One thread has a
task to increment it for 100,000 times and second thread should decrement “data”
variable to same 100,000 times. Its result should be obvious, on termination of both
threads “data” variable contains 0 in it.?
2) Modify your program to protect critical section of code using peterson's entry and exit
section code. Is there any improvements?
3) Set same cpu affinity for both threads and observe the output.

Note: for task 3 you need following MACROS and function to achieve desire functionality.
cpu_set_t cpuset;
/*
* This data set is a bitset where each bit represents a CPU. How the system’s CPUs are mapped to bits in
* the bitset is system dependent The data type has a fixed size; in the unlikely case that the number of bits
* are not sufficient to describe the CPUs of the system a different interface has to be used.
*/
CPU_ZERO(&cpuset);
/*
* Macro:
* This macro initializes the CPU set set to be the empty set.
*/
CPU_SET(1, &cpuset);
/*Macro:
* This macro adds cpu to the CPU set set.
*/

CPU_SETSIZE
/*
* The value of this macro is the maximum number of CPUs which
* can be handled with a cpu_set_t object.
*/

CPU_ISSET(j, &cpuset);
/*
* This macro returns a nonzero value (true) if cpu is a
* member of the CPU set set, and zero (false) otherwise.
*/
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,const cpu_set_t *cpuset);

4) Implement PRODUCER thread and CONSUMER thread having shared buffer of 10


integer elements. Protect critical region of shared data using peterson’s entry and exit
section.
Lab 10: Semaphores (Implementation of Reader’s Writer’s Problem)
CS 2203: Operating Systems Spring 2017
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab 10: Semaphores
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn to understand semaphores for synchronization.

Credits: Operating System concepts by silbershatz 9th edition.


http://man7.org/linux/man-pages/man3/sem_open.3.html

Posix semaphores
All POSIX semaphore functions and types are prototyped or defined in semaphore.h.
To define a semaphore object, use
sem_t sem_name;

To initialize a semaphore, use sem_init:


int sem_init(sem_t *sem, int pshared, unsigned int value);

 sem points to a semaphore object to initialize


 pshared is a flag indicating whether or not the semaphore should be shared
with fork()ed processes. LinuxThreads does not currently support shared
semaphores
 value is an initial value to set the semaphore to

Example of use:
sem_init(&sem_name, 0, 10);

To wait on a semaphore, use sem_wait:


int sem_wait(sem_t *sem);
Example of use:
sem_wait(&sem_name);
 If the value of the semaphore is negative, the calling process blocks; one of
the blocked processes wakes up when another process calls sem_post.

To increment the value of a semaphore, use sem_post:


int sem_post(sem_t *sem);
Example of use:
sem_post(&sem_name);

 It increments the value of the semaphore and wakes up a blocked process


waiting on the semaphore, if any.

To find out the value of a semaphore, use


int sem_getvalue(sem_t *sem, int *valp);

 gets the current value of sem and places it in the location pointed to by valp

Example of use:
int value;
sem_getvalue(&sem_name, &value);
printf("The value of the semaphors is %d\n", value);

To destroy a semaphore, use


int sem_destroy(sem_t *sem);

 destroys the semaphore; no threads should be waiting on the semaphore if its


destruction is to succeed.

Example of use:
sem_destroy(&sem_name);

Using semaphores - a short example

Consider the problem we had before and now let us use semaphores:
Declare the semaphore global (outside of any funcion):
sem_t mutex;
Initialize the semaphore in the main function:
sem_init(&mutex, 0, 1);
Problems:

Q 1. Write a program having two threads, thread1 and thread2 contain following
printf statements. Use one or more semaphore between printf statements to
synchronize the sequence in Alphabetical order (considering only last capital
letter).

Void * thread1(void * arg) Void * thread2(void * arg)


{ {
Printf(“thread1: A”); Printf(“thread1: B”);
Printf(“thread1: C”); Printf(“thread1: D”);
Printf(“thread1: E”); Printf(“thread1: F”);
} }

Q 2 write a program having two threads, thread1 should increment global variable
200000 times and thread2 decrement same global variable by same number of
time. Produce and observe output of global variable in main thread with and
without semaphore.

Q 3. Write a muti-threaded program to implement readers and writers problem.


Lab 11: DeadLock Avoidance
CS 2203: Operating Systems Spring 2017
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn to implement banker’s algorithm for deadlock avoidance.

Credits: Operating System concepts by silbershatz 9th edition.

7.5.3 Banker’s Algorithm (page 330 to page 333)


The resource-allocation-graph algorithm is not applicable to a resource allocation system with multiple instances
of each resource type. The deadlock avoidance algorithm that we describe next is applicable to such a system
but is less efficient than the resource-allocation graph scheme. This algorithm is commonly known as the
banker’s algorithm.
The name was chosen because the algorithm could be used in a banking system to ensure that the bank never
Allocated its available cash in such a way that it could no longer satisfy the needs of all its customers. When a
new process enters the system, it must declare the maximum number of instances of each resource type that it
may need. This number may not exceed the total number of resources in the system. When a user requests a set
of resources, the system must determine whether the allocation of these resources will leave the system in a safe
state. If it will, the resources are allocated; otherwise, the process must wait until some other process releases
enough resources.
Several data structures must be maintained to implement the banker’s algorithm. These data structures encode
the state of the resource-allocation system. We need the following data structures, where n is the number of
Processes in the system and m is the number of resource types:

• Available. A vector of length m indicates the number of available resources of each type. If Available[j]
Equals k, then k instances of resource type Rj are available.
• Max. An n × m matrix defines the maximum demand of each process. If Max[i][j] equals k, then
Process Pi may request at most k instances of resource type Rj .
• Allocation. An n × m matrix defines the number of resources of each type currently allocated to each
Process. If Allocation[i][j] equals k, then process Pi is currently allocated k instances of
Resource type Rj .
• Need. An n × m matrix indicates the remaining resource need of each process. If Need[i][j] equals k,
then process Pi may need k more instances of resource type Rj to complete its task. Note that
Need[i][j] equals Max[i][j] − Allocation[i][j].
These data structures vary over time in both size and value.

You can refer to book for further reading….


Lab Exercise:

Problem 1.
Write a code to implement banker’s algorithm. Define Max, Allocation along with Need matrix for
five processes shown in figure below. If system has total resources of type A=10, B= 5, and C = 7, Derive
Need matrix and determine at time instant t that system state is safe or not.

Problem 2.
If following processes request more resources one by one as shown in figure, check system state will become
unsafe or not.

P1 requests (1, 0, 2)
P4 requests (3, 3, 0)
P0 requests (0, 2, 0)
Lab 12: IPC using POSIX Message Queues
CS 2203: Operating Systems Spring 2017
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn to understand and use posix message queues for Inter Process Communication.

Credits: Operating System concepts by silbershatz 8th edition.


https://www.softprayog.in/programming/interprocess-communication-using-posix-message-
queues-in-linux

POSIX Message queues

POSIX Inter-process Communication (IPC) was introduced in the POSIX.1b standard (IEEE Std
1003.1b-1993) for real time extensions. POSIX message queues have been made available in
Linux since the version 2.6.6 (May 2004). POSIX IPC calls are as per the standard but may not
be available on older Unix-like systems. Compared with the System V IPC calls, the POSIX IPC
calls have a cleaner interface and are easier to use.

POSIX Message queue naming in Linux

POSIX message queues are identified using name strings. On Linux, POSIX queues are named as
string starting with a forward slash (/) followed by one or more characters, none of which is a slash
and ending with the null character. Any process knowing the queue name and having appropriate
permissions can send or receive messages from the queue and also do other operations on it.

POSIX Message queue calls

Programs using POSIX message queues on Linux must link with the real-time library, librt using
the compiler option -lrt. The function call names start with the prefix, mq_.

mq_open, mq_close
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
mqd_t mq_open (const char *name, int oflag);
mqd_t mq_open (const char *name, int oflag, mode_t mode, struct mq_attr *attr);
The mq_open function is for opening a POSIX queue. The first parameter specifies the queue name
which is as described in an earlier paragraph above. The second parameter is a flag which can
be O_RDONLY for receiving messages, O_WRONLY, for sending messages and O_RDWR for both send
and receive operations on the queue.

If O_CREAT is specified in oflag, the second form of mq_open has to be used with two additional
parameters. In that case, perms specify permissions for the queue and the pointer to
struct mq_attr gives the attributes for the message queue. If this pointer is NULL, a queue with
default attributes is created.

struct mq_attr {
long mq_flags; /* Flags: 0 or O_NONBLOCK */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue */
};

The value of mq_maxmsg in the structure whose pointer is passed as attr in mq_open should be less
than or equal to that in the /proc interface file, /proc/sys/fs/mqueue/msg_max (default value in
the file is 10). Similarly the value of mq_msgsize should be less than that in the
file, /proc/sys/fs/mqueue/msgsize_max, the default value in the file being 8192 bytes. These
limits are ignored for privileged processes.

If the mq_open call is successful, the message queue descriptor is returned. The message queue
descriptor can be used in subsequent calls for the queue.

int mq_send ( mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
ssize_t mq_receive (mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

mq_send is for sending a message to the queue referred by the descriptor mqdes.
The msg_ptr points to the message buffer. msg_len is the size of the message, which should be less
than or equal to the message size for the queue. msg_prio is the message priority, which is a non-
negative number specifying the priority of the message. Messages are placed in the queue in the
decreasing order of message priority, with the older messages for a priority coming before newer
messages. If the queue is full, mq_send blocks till there is space on the queue, unless
the O_NONBLOCK flag is enabled for the message queue.

mq_receive receives a message from the queue referred by the descriptor mqdes. The oldest of
the highest priority is deleted from the queue and passed to the process in the buffer pointed
by msg_ptr. msg_len is the length of buffer in bytes and it must be greater than the maximum message
size, the mq_msgsize attribute, for the queue
Question # 1

Write a program to pass message between child and parent process using message queues. Use
fork( ) system call to create single child process.

Question # 2

Write a program to pass bidirectional message between child and parent process using message queues.

newExternalTemp = (myTemp * 3 + 2 * centralTemp) / 5;

newCentralTemp = (2 * centralTemp +four temps received from external processes) / 6;

message queues. Each client will send its message, external temperature to server message queue
(created by server). In response to each of these values received by server, server will send its
newly calculated central temperature to each of the clients message queue (created by client).
Lab 13: IPC using POSIX Message Queues Part 2
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn to understand and use posix message queues for Inter Process Communication.

Credits: Operating System concepts by silbershatz 8th edition.


https://www.softprayog.in/programming/interprocess-communication-using-posix-message-
queues-in-linux

POSIX Message queues

POSIX Inter-process Communication (IPC) was introduced in the POSIX.1b standard (IEEE Std
1003.1b-1993) for real time extensions. POSIX message queues have been made available in
Linux since the version 2.6.6 (May 2004). POSIX IPC calls are as per the standard but may not
be available on older Unix-like systems. Compared with the System V IPC calls, the POSIX IPC
calls have a cleaner interface and are easier to use.

POSIX Message queue naming in Linux

POSIX message queues are identified using name strings. On Linux, POSIX queues are named as
string starting with a forward slash (/) followed by one or more characters, none of which is a slash
and ending with the null character. Any process knowing the queue name and having appropriate
permissions can send or receive messages from the queue and also do other operations on it.

POSIX Message queue calls

Programs using POSIX message queues on Linux must link with the real-time library, librt using
the compiler option -lrt. The function call names start with the prefix, mq_.

mq_open, mq_close
#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
mqd_t mq_open (const char *name, int oflag);
mqd_t mq_open (const char *name, int oflag, mode_t mode, struct mq_attr *attr);
The mq_open function is for opening a POSIX queue. The first parameter specifies the queue name
which is as described in an earlier paragraph above. The second parameter is a flag which can
be O_RDONLY for receiving messages, O_WRONLY, for sending messages and O_RDWR for both send
and receive operations on the queue.

If O_CREAT is specified in oflag, the second form of mq_open has to be used with two additional
parameters. In that case, perms specify permissions for the queue and the pointer to
struct mq_attr gives the attributes for the message queue. If this pointer is NULL, a queue with
default attributes is created.

struct mq_attr {
long mq_flags; /* Flags: 0 or O_NONBLOCK */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue */
};

The value of mq_maxmsg in the structure whose pointer is passed as attr in mq_open should be less
than or equal to that in the /proc interface file, /proc/sys/fs/mqueue/msg_max (default value in
the file is 10). Similarly the value of mq_msgsize should be less than that in the
file, /proc/sys/fs/mqueue/msgsize_max, the default value in the file being 8192 bytes. These
limits are ignored for privileged processes.

If the mq_open call is successful, the message queue descriptor is returned. The message queue
descriptor can be used in subsequent calls for the queue.

int mq_send ( mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);
ssize_t mq_receive (mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

mq_send is for sending a message to the queue referred by the descriptor mqdes.
The msg_ptr points to the message buffer. msg_len is the size of the message, which should be less
than or equal to the message size for the queue. msg_prio is the message priority, which is a non-
negative number specifying the priority of the message. Messages are placed in the queue in the
decreasing order of message priority, with the older messages for a priority coming before newer
messages. If the queue is full, mq_send blocks till there is space on the queue, unless
the O_NONBLOCK flag is enabled for the message queue.

mq_receive receives a message from the queue referred by the descriptor mqdes. The oldest of
the highest priority is deleted from the queue and passed to the process in the buffer pointed
by msg_ptr. msg_len is the length of buffer in bytes and it must be greater than the maximum message
size, the mq_msgsize attribute, for the queue
Question # 1

Write a program to pass message between child and parent process using message queues. Use
fork( ) system call to create single child process.

Question

This mini-project consists of using POSIX message queues for communicating temperatures
between each of four external processes and a central process. The project can be completed on
systems that support POSIX message passing, such as UNIX, Linux, and Mac OS X.

Four external processes will communicate temperatures to a central process, which in turn will
reply with its own temperature and will indicate whether the entire system has stabilized. Each
process will receive its initial temperature upon creation and will recalculate a new temperature
according to two formulas:

newExternalTemp = (myTemp * 3 + 2 * centralTemp) / 5;

newCentralTemp = (2 * centralTemp +four temps received from external processes) / 6;

Figure above depicts the way client and server on same machine can communicate through
message queues. Each client will send its message, external temperature to server message queue
(created by server). In response to each of these values received by server, server will send its
newly calculated central temperature to each of the clients message queue (created by client).
Lab 14: Logical to Physical Address Translation
CS 2203: Operating Systems Spring 2018
Center for Advance Studies in Engineering (CASE) Computer Science Program
Lab Instructors: Waqas Ahmed, Kainat Iqbal

Objectives

• Learn the conversion process of virtual memory references into physical addresses.

Credits: Operating System concepts by silbershatz 9th edition.

Implement following scenario according to given specifications.


Virtual Address Space = 128 bytes
Physical Address Space = 256 bytes
Page Size = 16 bytes.

Figure 1
Above diagram shows a process having virtual address space (VAS) of 128 byte is divided into equal size pages
of 16 bytes and mapped to available physical address space (PAS) of 256 bytes. Whenever CPU wants to load
and executes this process, its virtual pages will be get loaded into physical page frames. Mapping of virtual pages
to physical page frames is stored in page table and its reference is stored in process control block PCB.

CPU generates logical addresses to fetch instructions and memory operands of this process to execute them
sequentially. Since 128 byte VAS is given it can address each byte individually by generating 7 bit logical
addresses. Total entries in page table are 8 so we need most significant 3/7 “P” bits to index into page table to
get page frame number. Further page frame number will be appended with remaining 4/7 “D” offset bits to make
it 8 bit physical address.
Example
Logical address 70 decimal (1000110 binary).
This binary # can be divided into 2 parts
P = 100
D = 0110
Using P bits we can found page frame # 7 (111 binary) from page table.
Physical Address = 111 0110 = 118 decimal
Obtained PA is in range 112-127 of PAS where virtual page 4 is mapped to page frame 7.

Question

Write a program that translate range between 0-15 (decimal) logical Addresses to Physical Addresses and
verify your conversion.

You might also like