Os Lab Manual PDF
Os Lab Manual PDF
LIST OF EXPERIMENTS:
1. Write C programs to simulate the following CPU Scheduling algorithms
Prevention.
4. Write a C program to implement the Producer – Consumer problem using
a) Paging b) Segmentation
TEXT BOOKS:
1. Operating System Principles- Abraham Silberchatz, Peter B. Galvin, Greg Gagne 7th
REFERENCE BOOKS:
1. Operating Systems – Internals and Design Principles, William Stallings, Fifth
LAB PROGRAMS
Program
Program Aim Page No
No.
SJF CPU SCHEDULING ALGORITHM: For SJF scheduling algorithm, read the number
of processes/jobs in the system, their CPU burst times. Arrange all the jobs in order with
respect to their burst times. There may be two jobs in queue with the same execution time,
and then FCFS approach is to be performed. Each process will be executed according to the
length of its burst time. Then calculate the waiting time and turnaround time of each of the
processes accordingly.
ALGORITHM:
Step 1: Input the processes along with their processid(pid),arrival time(at) and burst time
(bt).
Step 3: Find the completion time for all other processes i.e.
Step 5: As first process that comes need not to wait so waiting time for process 1 will be 0
i.e. wt[0] = 0.
Step 6: Find waiting time for all other processes i.e. for process i ->
no_of_processes.
SOURCE CODE:
#include<stdio.h>
int main()
{
int pid[10]={0},bt[10]={0},at[10]={0},tat[10]={0},wt[10]={0},ct[10]={0};
int n,sum=0,temp,temp1,i,j,k,temp2;
float totalTAT=0,totalWT=0;
printf("Enter number of processes ");
scanf("%d",&n);
printf("Enter the processes details\n\n");
for(i=0;i<n;i++)
{
printf("Enter processid");
scanf("%d",&pid[i]);
printf("Arrival time of process[%d] ",i+1);
scanf("%d",&at[i]);
printf("Burst time of process[%d] ",i+1);
scanf("%d",&bt[i]);
printf("\n");
}
for (i=0; i<n-1; i++)
{
for (j=0; j<n-i-1; j++)
{
if (at[j]>at[j+1])
{
// sorting the arrival times
temp = at[j];
at[j] = at[j+1];
at[j+1] = temp;
// sorting the burst times
temp1 = bt[j];
bt[j] = bt[j+1];
bt[j+1] = temp1;
// sorting the process numbers
temp2=pid[j];
pid[j]=pid[j+1];
pid[j+1]=temp2;
}
}
}
//calculate completion time of processes
for(j=0;j<n;j++)
{
sum+=bt[j];
ct[j]+=sum;
}
//calculate turnaround time and waiting times
for(k=0;k<n;k++)
{
tat[k]=ct[k]-at[k];
totalTAT+=tat[k];
}
wt[0]=0;
for(k=0;k<n;k++)
{
wt[k]=0;
for(j=0;j<k;j++)
wt[k]+=bt[j];
totalWT+=wt[k];
}
printf("Solution: \n\n");
printf("P#\t AT\t BT\t CT\t TAT\t WT\t\n\n");
for(i=0;i<n;i++)
{
printf("P%d\t %d\t %d\t %d\t %d\t %d\n",pid[i],at[i],bt[i],ct[i],tat[i],wt[i]);
}
printf("\n\nAverage Turnaround Time = %f\n",totalTAT/n);
printf("\nAverage Waiting Time = %f\n\n",totalWT/n);
return 0;
}
OUTPUT:
Enter number of processes 5
Enter the processes details
Enter processid1
Enter processid2
Arrival time of process[2] 5
P# AT BT CT TAT WT
P3 1 5 5 4 0
P1 2 3 8 6 5
P4 3 3 11 8 8
P5 4 2 13 9 11
P2 5 4 17 12 13
Step 3: Find the completion time for all other processes i.e.
Step 5: As first process that comes need not to wait so waiting time for process 1 will be 0
i.e. wt[0] = 0.
Step 6: Find waiting time for all other processes i.e. for process i ->
no_of_processes.
SOURCE CODE:
#include<stdio.h>
int main()
{
int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;
float avg_wt,avg_tat;
printf("\nEnter number of process:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nEnter Burst Time for process%d:",i+1);
scanf("%d",&bt[i]);
p[i]=i+1;
}
temp=bt[i];
bt[i]=bt[pos];
bt[pos]=temp;
temp=p[i];
p[i]=p[pos];
p[pos]=temp;
}
wt[0]=0;
for(i=1;i<n;i++)
{
wt[i]=0;
for(j=0;j<i;j++)
wt[i]+=bt[j];
total+=wt[i];
}
avg_wt=(float)total/n;
total=0;
OUTPUT:
Enter number of process:3
Enter Burst Time for process1:5
Enter Burst Time for process2:4
Enter Burst Time for process3:3
Process Burst Time Waiting Time Turnaround Time
p3 3 0 3
p2 4 3 7
p1 5 7 12
Average Waiting Time=3.333333
Average Turnaround Time=7.333333
c) ROUND ROBIN
ALGORITHM:
Step 1: Input the processes along with their burst time (bt).
Step 2: Input the time quantum (or) time slice
Step 3: Create an array rem_bt[] to keep track of remaining burst time of processes. This
array is
initially a copy of bt[] (burst times array)
Step 4:Create another array wt[] to store waiting times of processes. Initialize this array as 0.
Step 5:Initialize time : t = 0
Step 6: Keep traversing the all processes while all processes are not done. Do following for
i'th process if it is not done yet.
a- If rem_bt[i] > quantum
(i) t = t + quantum
(ii) bt_rem[i] -= quantum;
b- Else // Last cycle for this process
(i) t = t + bt_rem[i];
(ii) wt[i] = t - bt[i]
(ii) bt_rem[i] = 0; // This process is over
Step 8: Find average waiting time = total_waiting_time / no_of_processes.
{
// Increase the value of t i.e. shows how much time a process has been processed
t += time_quantum;
// Decrease the burst_time of current process by quantum
rem_bt[i] -= time_quantum;
}
// If burst time is smaller than or equal to quantum. Last cycle for this process
else
{
// Increase the value of t i.e. shows how much time a process has been processed
t = t + rem_bt[i];
// Waiting time is current time minus time used by this process
wt[i] = t - bt[i];
// As the process gets fully executed make its remaining burst time = 0
rem_bt[i] = 0;
}
}
}
if (flag==1)
break;
}
for (i = 0; i < n ; i++)
tat[i] = bt[i] + wt[i];
printf("\n Process BT\t WT\t TAT \n");
for(i=0;i<n;i++)
printf("\n %d \t %d \t %d \t %d \t",i+1,bt[i],wt[i],tat[i]);
for (i = 0; i < n ; i++)
{
total_wt= total_wt+wt[i];
total_tat= total_tat+tat[i];
}
printf("\nAverage waiting time = %f", total_wt/n);
printf ("\nAverage turn around time = %f",total_tat/n);
}
OUTPUT:
1 3 4 7
2 6 7 13
3 5 9 14
Average waiting time = 6.666667
Average turn around time = 11.333333
d) PRIORITY NON-PREEMPTIVE
ALGORITHM:
Step 1: Input the processes along with their processnumber(p),burst time (bt) and
priority(pr)
Step 3: Find the completion time for all other processes i.e.
Step 5: As first process that comes need not to wait so waiting time for process 1 will be 0
i.e. wt[0] = 0.
Step 6: Find waiting time for all other processes i.e. for process i ->
no_of_processes.
SOURCE CODE:
// Online C compiler to run C program online
#include<stdio.h>
#define max 30
void main()
{
int i,j,n,t,p[max],bt[max],pr[max],wt[max],tat[max],Total_wt=0,Total_tat=0;
float awt=0,atat=0;
printf("Enter the number of processes\n");
scanf("%d",&n);
//Enter the processes according to their arrival times
for(i=0;i<n;i++)
{
printf("Enter the process number\n");
scanf("%d",&p[i]);
printf("Enter the burst time of the process\n");
scanf("%d",&bt[i]);
printf("Enter the priority of the process\n");
scanf("%d",&pr[i]);
}
//Apply the bubble sort technique to sort the processes according to their priorities times
for(i=0;i<n;i++)
{
for(j=0;j<n-i-1;j++)
{
if(pr[j]>pr[j+1])
{
// Sort according to priorities
t=pr[j];
pr[j]=pr[j+1];
pr[j+1]=t;
// Sorting burst times
t=bt[j];
bt[j]=bt[j+1];
bt[j+1]=t;
// Sorting Process numbers
t=p[j];
p[j]=p[j+1];
p[j+1]=t;
}
}
}
printf("Process\t Burst Time\t Priority\tWaiting Time\t Turn Around Time\n");
for(i=0;i<n;i++)
{
wt[i]=0;
tat[i]=0;
for(j=0;j<i;j++)
wt[i]=wt[i]+bt[j];
tat[i]=wt[i]+bt[i];
Total_wt=Total_wt+wt[i];
Total_tat=Total_tat+tat[i];
printf("P%d\t %d\t\t%d\t\t %d\t\t %d\n",p[i],bt[i],pr[i],wt[i],tat[i]);
}
awt=(float)Total_wt/n;
atat=(float)Total_tat/n;
printf("The average waiting time = %f\n",awt);
printf("The average turn aroud time = %f\n",atat);
}
OUTPUT:
Write programs using the I/O system calls of UNIX/LINUX operating system
(open, read, write, close, fcntl, seek, stat, opendir, readdir)
DESCRIPTION
The interface between a process and an operating system is provided by system calls. In
general, system calls are available as assembly language instructions. They are also included
in the manuals used by the assembly level programmers. System calls are usually made when
a process in user mode requires access to a resource. Then it requests the kernel to provide
the resource via a system call.
In general, system calls are required in the following situations:
If a file system requires the creation or deletion of files. Reading and writing from files also
require a system call.
Creation and management of new processes.
Network connections also require system calls. This includes sending and receiving packets.
Access to a hardware devices such as a printer, scanner etc. requires a system call.
Types of System Calls
There are mainly five types of system calls. These are explained in detail as follows:
Process Control
These system calls deal with processes such as process creation, process termination etc.
File Management
These system calls are responsible for file manipulation such as creating a file, reading a file,
writing into a file etc.
Device Management
These system calls are responsible for device manipulation such as reading from device
buffers, writing into device buffers etc.
Information Maintenance
These system calls handle information and its transfer between the operating system and the
user program.
Communication
These system calls are useful for interprocess communication. They also deal with creating
and deleting a communication connection.
open() Used to Create a new empty file.
int open (const char* Path, int flags [, int mode ]);
Parameters
Path : is the name to the file to open.
flags : is used to define the file opening modes such as create, read, write modes.
mode : is used to define the file permissions.
Upon successful completion, the function shall open the file and return a non-negative integer
representing the lowest numbered unused file descriptor. Otherwise, -1 shall be returned
and errno set to indicate the error. No files shall be created or modified if the function returns
-1.
Parameters
fd: file descripter
buf: buffer to read data from
cnt: length of buffer
Returns how many bytes were actually read or -1 in case of error.
write() is used to write the content to the file.
int close(intfd);
Parameter
fd :file descriptor
Returns 0 on success or -1 on error.
lseek() System call that is used to change the location of the read/write pointer of a file
descriptor. The location can be set either in absolute or relative terms.
SEEK_CUR
The current file position of fd is set to its current value plus pos, which can be negative, zero,
or positive. A pos of zero returns the current file position value
SEEK_END
The current file position of fd is set to the current length of the file plus pos,which can be
negative, zero, or positive. A pos of zero sets the offset to the endof the file.
SEEK_SET
The current file position of fd is set to pos.the offset is measured from the beggining of the
file. A pos of zero sets the offset to the beginning of the file.
The call returns the new file position on success. On error, it returns -1 and errno is set
asappropriate.
ALGORITHM:
Step 2: open a file for O_RDWR for R/W,O_CREATE for creating a file , O_TRUNC for
truncate a file
Step 3: Using write command, write the msg array contents file.
Step 4:Using lseek command to position the pointer to the specified location.
Step 5: Then the file is opened for read only mode and read the characters and displayed
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
int fd;
char buffer[80]; char msg[50]="Hello PEC";
fd=open("ss.txt",O_RDWR|O_CREAT); printf("fd=%d",fd);
if(fd!=-1)
{
printf("\n ss.txt opened with read write access\n"); write(fd,msg,sizeof(msg)); lseek(fd,0,SEEK_SET);
read(fd,buffer,sizeof(msg));
printf("\n %s was written to my file\n",buffer); close(fd);
}
return 0;
}
OUTPUT:
fd=3
ss.txt opened with read write access
ALGORITHM:
Step 2:Use the stat command to display information regarding the root folder.
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
main()
{
struct stat info;
if (stat("/", &info) != 0)
perror("stat() error");
else
{
puts("stat() returned the following information about root f/s:"); printf(" inode: %d\n", (int) info.st_ino);
printf(" dev id: %d\n", (int) info.st_dev); printf(" mode: %08x\n", info.st_mode); printf(" links:
%d\n", info.st_nlink); printf(" uid: %d\n", (int) info.st_uid); printf(" gid: %d\n", (int) info.st_gid);
}
}
OUTPUT:
stat() returned the following information about root f/s:
inode: 2
dev id: 1048618
mode: 000041ed
links: 1
uid: 0
gid: 0
opendir()
#include <sys/types.h>
#include <dirent.h>
Parameters
dirname
(Input) A pointer to the null-terminated path name of the directory to be opened.
Return Value
value
opendir() was successful. The value returned is a pointer to a DIR, representing an
open directory stream. This DIR describes the directory and is used in subsequent
operations on the directory using the readdir(), rewinddir(), and closedir() functions.
NULL pointer
opendir() was not successful. The errno global variable is set to indicate the error.
readdir()
#include <sys/types.h>
#include <dirent.h>
readdir()reads one dirent structure from the directory pointed at by fd into the memory area
pointed to by dirp. The parameter count is ignored; at most one dirent structure is read.
d_ino is an inode number. d_off is the distance from the start of the directory to
this dirent. d_reclen is the size of d_name, not counting the null terminator. d_name is a
null-terminated filename.
Parameters
dirp
(Input) A pointer to a DIR that refers to the open directory stream to be read.
Return Value
value
readdir() was successful. The value returned is a pointer to a dirent structure describing the
next directory entry in the directory stream.
ALGORITHM:
Step 3: The opendir() function shall open a directory stream corresponding to the
Step 4: The readdir() function returns a pointer to a dirent structure representing the next
Step 5: The closedir() function closes the directory stream associated with dir. The
/tmp/269hpPcQU1.o
.bash_logout
.bashrc
.profile
.
sample.txt
MST2.out
ss.txt
MST1.out
..
Parking_data.txt
test.txt
EXPERIMENT 3
OBJECTIVE
need[i][j]=max[i][j]-alloc[i][j]
Step 8: else the process getsexecuted and add the process to safe sequence and
avail[j]+=alloc[process][j];
Step 9: If all the processes are completed the system is in safe sequence
ALGORITHM:
Step 1: The Semaphore full & empty are initialized.
ii) If there is empty space in the buffer check the mutex value for enter into the critical
section.
iii) If the mutex value is 0, allow the producer to add value in the temporary variable
to the buffer.
ii) If there is any item in the buffer check for mutex value, if the mutex==0, remove
item from buffer
iii) Signal the mutex value and reduce the empty value by 1.
#include<stdio.h>
#include<stdlib.h>
int full=0,empty=3,x=0;
main()
{
int n;
void producer();
void consumer();
int wait(int);
int signal(int);
printf("\n1.PRODUCER\n2.CONSUMER\n3.EXIT\n");
while(1)
{
printf("\nENTER YOUR CHOICE\n");
scanf("%d",&n);
switch(n)
{
case 1:
if(empty!=0)
producer();
else
printf("BUFFER IS FULL");
break;
case 2:
if(full!=0)
consumer();
else
printf("BUFFER IS EMPTY");
break;
case 3:
exit(0);
break;
}
}
}
int wait(int s)
{
return(--s);
}
int signal(int s)
{
return(++s);
}
void producer()
{
full=signal(full);
empty=wait(empty);
x++;
printf("\n Producer produces the item%d \n",x);
}
void consumer()
{
full=wait(full);
empty=signal(empty);
printf("\n Consumer consumes item%d \n",x);
x--;
}
OUTPUT:
1. PRODUCER
2. CONSUMER
3. EXIT
a) PIPES
Pipes are unidirectional byte streams which connect the standard output from one process
into the standard input of another process. A pipe is created using the system call pipe that
returns a pair of file descriptors.
Once you have created a FIFO special file in this way, any process can open it for reading or
writing, in the same way as an ordinary file. However, it has to be open at both ends
simultaneously before you can proceed to do any input or output operations on it.
Opening a FIFO for reading normally blocks until some other process opens the same FIFO
for writing, and vice versa.
Return Value
On success mkfifo() returns 0. In the case of an error, -1 is returned (in which case, errno is
set appropriately).
c) MESSAGE QUEUES
Message queues provide a form of message passing in which any process (given that it has
the necessary permissions) can read a message from or write a message to any IPC message
queue on the system. There are no requirements that a process be waiting to receive a
message from a queue before another process sends one, or that a message exist on the queue
before a process requests to receive one.
ftok()
This generates an IPC key on the basis of supplied filename and ID. The filename can be
provided along with its complete path. The file name must refer to an existing file.
Synopsis
ket_t ftok(const char *filename,int id);
Description
This function will generate the same key value if the same filebame and the same ID is
supplied. Upon successful completion ftok will return a key, Otherwise it will return -1.
msgget()
This is used for creating a new message queue and for accessing an existing queue that is
related to the specified key. If this is executed successfully, the function returns the identifier
of the message queue.
Synopsis
int msggt(key_t,int flag)
Description
key: this is a uniquekey value that is retrieved by invoking the ftok function
flag: this can be any of the following constants;
IPC_CREAT: Creates the message queue if it doesn’t already exist and returns the message
queue identifier for the newly created message queue. If the message queue already exists
with the supplied key value, it returns its identifier.
IPC_EXCL: If both IPC_CREAT and IPC_EXCL are specified and the message queue does
not exist, then it is created. However, if it already exists then function will fail.
msgrcv()
This is used for reading a message form the specified message queue whose identifier is
supplied.
Synopsis
int msgrcv(int msqid,void *msgstruc,int msgsize,long typemsg,int flag);
Description
msqid: Represents the message queue identifier of the queue from which the message needs
to be read.
msgstruc: This is the user-defined structure into which the read message is placed. The user-
defined structure must contain two members. One is usually named mtype, which must be of
type long int that specifies the type of message and the second is usually called mesg, which
should be of char type to store message.
msgsize: Represents the size of the text to be read from the message queue in terms of bytes.
If the message that is read is larger than msgsize then it will be truncated to msgsize bytes.
typemesg: Specifies which message on the queue needs to be received:
If typemsg is 0, the first message o the queue needs to be received.
If typemsg is greater than 0, the first message whose mtype field is equal to the
typemsg is received
If typemsg is less than 0, a message whose mtype field is less than or equal to the
typemsg is received
flag: Determines the action to be taken if the desired message is not found in the queue. It
keeps its value of 0 if you don’t want to specify the flag.
The flag can have any of the following values:
IPC_NOWAIT : This makes the msgrcv function fail if there is no desired message in the
queue, that it will not make the caller wait for the appropriated message on the queue. If flag
is not set to IPC_NOWAIT, it will make the caller wait for an appropriate message on the
queue instead of failing the function.
MSG_NOERROR: This allows you to receive text that is larger than the size that’s specified
in the msgsize argument It simply truncates the text and receives it. If the flag is not set, on
receiving the larger text, the function will not receive it and will fail the function.
If the function is executed successfully, the function returns the number of bytes that were
placed into the text field of he structure that is pointed to by msgstruc. On failure the function
returns a value of -1.
msgsnd()
This is used for sending or delivering a message to the queue.
Synopsis
int msgsnd(int msqid,struct msgbuf &msgstruc,in msgsize,int flag);
Description
msqid: Represent the queue identifier of the message that we want to send. The queue
identifier is usually retrieved by invoking msgget function.
msgstruc: This is a pointer to the user-defined structure. It is the mesg member that contains
the message that wee want to send to the queue.
msgsize: Represents the size of the message in bytes.
flag: Determines the action to be taken on the message. If the flag value is set to IPC_NOAIT
and if the message queue is full the message will not be written to the queue and the control
is returned to the calling process. But if flag is not set and the message queue is full, then the
calling process will suspend until a space becomes available in the queue. Usually the value
of flag is set to 0
If this is executed successfully, the function returns 0, otherwise it returns -1.
d) SHARED MEMORY
Inter Process Communication through shared memory is a concept where two or more
process can access the common memory. And communication is done via this shared
memory where changes made by one process can be viewed by another process.
The problem with pipes, fifo and message queue – is that for two process to exchange
information.
The information has to go through the kernel.
Server reads from the input file.
The server writes this data in a message using either a pipe, fifo or message queue.
The client reads the data from the IPC channel,again requiring the data to be copied
from kernel’s IPC buffer to the client’s buffer.
Finally the data is copied from the client’s buffer.
A total of four copies of data are required (2 read and 2 write). So, shared memory provides a
way by letting two or more processes share a memory segment. With Shared Memory the
data is only copied twice – from input file into shared memory and from shared memory to
the output file.
ftok(): is used to generate a unique key.
shmget()
The above system call creates or allocates a shared memory segment.
Synopsis
int shmget(key_t key,size_tsize,intshmflg);
Description
key: It recognizes the shared memory segment. The key can be either an arbitrary value or
one that can be derived from the library function ftok(). The key can also be IPC_PRIVATE,
means, running processes as server and client (parent and child relationship) i.e., inter-
related process communication. If the client wants to use shared memory with this key, then
it must be a child process of the server. Also, the child process needs to be created after the
parent has obtained a shared memory.
Upon successful completion, shmget() returns an identifier for the shared memory segment.
shmat():
The above system call performs shared memory operation for System V shared memory
segment i.e., attaching a shared memory segment to the address space of the calling process.
Before you can use a shared memory segment, you have to attach yourself
to it using shmat().
Synopsis
void *shmat (int shmid, void *shmaddr,int shmflg);
Description
shmid :Itis the identifier of the shared memory segment. This id is the shared memory
identifier, which is the return value of shmget() system call.
shmaddr : It is to specify the attaching address. If shmaddr is NULL, the system by default
chooses the suitable address to attach the segment. If shmaddr is not NULL and SHM_RND
is specified in shmflg, the attach is equal to the address of the nearest multiple of SHMLBA
(Lower Boundary Address). Otherwise, shmaddr must be a page aligned address at which the
shared memory attachment occurs/starts.
shmflg: specifies the required shared memory flag/s such as SHM_RND (rounding off
address to SHMLBA) or SHM_EXEC (allows the contents of segment to be executed) or
SHM_RDONLY (attaches the segment for read-only purpose, by default it is read-write) or
SHM_REMAP (replaces the existing mapping in the range specified by shmaddr and
continuing till the end of segment).
This call would return the address of attached shared memory segment on success and -1 in
case of failure. To know the cause of failure, check with errno variable or perror() function.
shmdt():
This system call performs shared memory operation for shared memory segment of detaching
the shared memory segment from the address space of the calling process.
When you’re done with the shared memory segment, your program should
detach itself from it using shmdt().
Synopsis
Description
The argument, shmaddr, is the address of shared memory segment to be detached. The to-be-
detached segment must be the address returned by the shmat() system call.
This call would return 0 on success and -1 in case of failure. To know the cause of failure,
check with errno variable or perror() function.
shmctl()
This system call performs control operation for a shared memory segment.
when you detach from shared memory,it is not destroyed. So, to destroy
shmctl() is used.
Synopsis
shmctl(int shmid,IPC_RMID,NULL);
Description
shmid: This is the identifier of the shared memory segment. This id is the shared memory
identifier, which is the return value of shmget() system call.
cmd:This is the command to perform the required control operation on the shared memory
segment.
IPC_STAT − Copies the information of the current values of each member of struct shmid_ds
to the passed structure pointed by buf. This command requires read permission to the shared
memory segment.
IPC_SET − Sets the user ID, group ID of the owner, permissions, etc. pointed to by structure
buf.
IPC_RMID − Marks the segment to be destroyed. The segment is destroyed only after the last
process has detached it.
IPC_INFO − Returns the information about the shared memory limits and parameters in the
structure pointed by buf.
buf : Thus is a pointer to the shared memory structure named struct shmid_ds. The values of
this structure would be used for either set or get as per cmd.
This call returns the value depending upon the passed command. Upon success of IPC_INFO
and SHM_INFO or SHM_STAT returns the index or identifier of the shared memory
segment or 0 for other operations and -1 in case of failure. To know the cause of failure,
check with errno variable or perror() function.
a) Pipes
ALGORITHM:
Step 1: Start the program
Step 2: Create a pipe using pipe() system call
Step 3: Create a child process.If the child process is created successfully then write the
message into the pipe otherwise goto step2
Step 4: Read the message from the pipe and display the message
Step 5: Stop the program
SOURCE CODE:
#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
int main()
{
intfd[2],child;
char a[]=” Hello PEC\n”;
pipe(fd);
child=fork();
if(! child)
{
close(fd[0]);
write(fd[1],a,strlen(a));
wait(0);
}
else
{
close(fd[1]);
read(fd[0],a,sizeof(a));
printf("\n\n The string retrieved from the pipe is %s",a);
}
return 0;
}
b) FIFOs
ALGORITHM:
Step 1: Create two processes, one is fifowriter and another one is fiforeader.
Step 2: Writer process performs the following −
Creates a named pipe (using system call mkfifo()) with name “MYFIFO”, if
not created.
Opens the named pipe for write only purposes.
Writes the data into the FIFO
Step 3: Reader process performs the following −
Opens the named pipe for read only purposes.
Reads the content from the FIFO and put in to the buffer.
Writes the content out from the buffer on the screen.
SOURCE CODE:
/* Filename: fifowrite.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
/* Filename: fiforead.c */
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
struct msgstruc
{
long mtype;
char mesg[MSGSIZE];
};
int main()
{
int msqid;
key_t key;
struct msgstruc rcvbuffer;
if((key= ftok(“messagefile”,’a’))==-1)
{
perror(“ftok”);
exit(1);
}
if((msqid=msgget(key,0666))<0)
{
perror(“msgget”);
exit(1);
}
if(msgrcv(msqid,&rcvbuffer,MSGSIZE,1,0)<0)
{
perror(“msgrcv”);
exit(1);
}
int main()
{
char *str;
int shmid;
int main()
{
int shmid;
char * str;
OBJECTIVE
SEGMENTATION
Like Paging, Segmentation is also a memory management scheme. It supports the user’s view
of the memory. The process is divided into the variable size segments and loaded to the
logical memory address space.
The logical address space is the collection of variable size segments. Each segment has
its name and length. For the execution, the segments from logical memory space are loaded
to the physical memory space.The address specified by the user contain two quantities
the segment name and the Offset. The segments are numbered and referred by the segment
number instead of segment name. This segment number is used as an index in the segment
table, and offset value decides the length or limit of the segment. The segment number and
the offset together generates the address of the segment in the physical memory space.
ALGORITHM:
Step 1: Read the logical address, page size and physical address.
Step 2: calculate the number of pages and number of frames and display.
Step 3: Create the page table with the page number page and page address.
Step 4: Read the page number and offset value.
Step 5: If the page number and offset value is valid, add the offset value with the address
corresponding to the page number and display the result.
Step 6: Display the page is not found or error message.
SOURCE CODE:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
main()
{
int page_size,no_of_pages,no_of_frames,logical_add;
int alloc[50],base[50],frame[50],page[50];
int i,f,n,physical_add,frame_sizes,pg_no,add,offset;
int temp;
int f1;
clrscr();
printf("\n\t\t PAGING\n");
printf("\n\t Enter the logical address space:");
scanf("%d",&logical_add);
printf("\n\t Enter the page size:");
scanf("%d",&page_size);
printf("\n\t Enter the physical address space:");
scanf("%d",&physical_add);
frame_sizes =page_size;
no_of_pages=logical_add/page_size;
no_of_frames=physical_add/frame_sizes;
printf("\n\t Number of pages = %d",no_of_pages);
printf("\n\t Number of frames = %d",no_of_frames);
for(i=0;i<no_of_frames;i++)
alloc[i]=0;
for(i=0;i<no_of_pages;i++)
{
temp=rand()%no_of_frames;
while(alloc[temp]==1)
temp=rand()%no_of_frames;
alloc[temp]=1;
frame[i]=temp;
}
printf("\n Page No \t Frame No \t Base address ");
for(i=0;i<no_of_pages;i++)
{
base[i]=frame[i]*page_size;
page[i]=i;
printf("%d\t %d\t %d\t",i,frame[i],base[i]);
}
printf("\n\t Enter the Page num and Offset : ");
scanf(" %d %d",&pg_no,&offset);
for(i=0;i<no_of_pages;i++)
{
if(pg_no ==page[i])
{
add=base[i]+offset;
f=1;
break;
}
}
if(offset>=page_size)
printf("\n\t Trying to access other page");
else
{
if(f==1)
printf("\n\t Physical Address = %d",physical_add);
else
printf("\n\t Page not found");
getch();
}
}
}
Enter the logical address space:500
Enter the page size:100
Number of pages =5
Number of frames=10