Lab 1: Introduction To Linux:: Hand-Out 1: Lab 01 Instructions
Lab 1: Introduction To Linux:: Hand-Out 1: Lab 01 Instructions
Objectives
Introduce the Linux environment and basic shell commands.
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.
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
/usr/doc Documentation
/usr/games Games
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
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
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
For Example:
$cd dir-name
To change to any sub-directory under the current directory.
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?
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.
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.
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).
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.
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?
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
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);
}
}
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
When the above code is compiled and executed with a single argument separated by space but
inside double quotes, it produces the following result.
Program 1. Write a program that accepts a number through CLI and generate Fibonacci series in
child process.
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
Objectives
Learn to use pipes for inter process communication.
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:
In-Lab Exercises
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.
Lab 5
4: File Permissions and Named Pipes
Objectives
• Learn about file and directories permissions in Linux.
• Learn to use pipe operator (|) in Linux.
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.
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";
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.
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
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 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
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:
3. Round Robin
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
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:
#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
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
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
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
Objectives
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:
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);
Objectives
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;
Example of use:
sem_init(&sem_name, 0, 10);
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);
Example of use:
sem_destroy(&sem_name);
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).
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.
Objectives
• 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.
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.
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 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.
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.
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.
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 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.
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:
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.
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.