Академический Документы
Профессиональный Документы
Культура Документы
CS 2257
0 0 3 2
(Implement the following on LINUX or other Unix like platform. Use C for high level
language implementation)
Write programs using the following system calls of UNIX operating system:
fork, exec, getpid, exit, wait, close, stat, opendir, readdir
2.
Write programs using the I/O system calls of UNIX operating system (open, read,
write, etc)
3.
4.
Given the list of processes, their CPU burst times and arrival times, display/print
the Gantt chart for FCFS and SJF. For each of the scheduling policies, compute
and print the average waiting time and average turnaround time. (2 sessions)
5.
Given the list of processes, their CPU burst times and arrival times, display/print
the Gantt chart for Priority and Round robin. For each of the scheduling policies,
compute and print the average waiting time and average turnaround time. (2
sessions)
6.
7.
8.
9.
10.
ht
tp
://
cs
et
ub
e.c
o.
nr
1.
Lab Manual
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
Lab Manual
http://csetube.co.nr/
cs
et
ub
e.c
o.
nr
A system call is just what its name implies - a request for the operating system to do
something on behalf of the user's program. The system calls are functions used in the kernel
itself. To the programmer, the system call appears as a normal C function call. However
since a system call executes code in the kernel, there must be a mechanism to change the
mode of a process from user mode to kernel mode. The C compiler uses a predefined library
of functions (the C library)
that have the names of the system calls. The library functions typically invoke an instruction
that changes the process execution mode to kernel mode and causes the kernel to start
executing code for system calls. The instruction that causes the mode change is often
referred to as an "operating system trap" which is a software generated interrupt.
The library routines execute in user mode, but the system call interface is a special case of
an interrupt handler. The library functions pass the kernel a unique number per system call in
a machine dependent way
General Syntax:
ht
tp
://
getpid, getppid
To get the process and parent process identification number.
pid_t getpid(void);
pid_t getppid(void);
Description
getpid returns the process ID of the current process. (This is often used by routines that
generate unique temporary file names.)
getppid returns the process ID of the parent of the current process.
fork()
causes the UNIX system to create a new process, called the "child process", with a new
process ID. The contents of the child process are identical to the contents of the parent
process.
The prototype for the fork() system call is:
int fork()
Lab Manual
http://csetube.co.nr/
e.c
o.
nr
The UNIX system calls that transform a executable binary file into a process are the
"exec" family of system calls. The prototypes for these calls are:
://
wait()
cs
et
ub
ht
tp
You can control the execution of child processes by calling wait() in the parent. wait()
forces the parent to suspend execution until the child is finished. wait() returns the process
ID of a child process that finished.
If the child finishes before the parent gets around to calling wait(), then when wait() is
called by the parent, it will return immediately with the child's process ID. (It is possible to
have more that one child process by simply calling fork() more than once.). The prototype
for the wait() system call is:
int wait(status)
int *status;
where status is a pointer to an integer where the UNIX system stores the value returned by
the child process. wait() returns the process ID of the process that ended.
exit()
The exit() system call ends a process and returns a value to it parent. The prototype for
the exit() system call is:
void exit(status)
int status;
where status is an integer between 0 and 255.
Lab Manual
http://csetube.co.nr/
Note: since wait() returns the exit status multiplied by 256 (contained in
the upper 8 bits), the status value is shifted right 8 bits (divided by 256)
to obtain the correct value.
File Status
stat() ,fstat() , lstat()
The i-node data structure holds all the information about a file except the file's name and
its contents. Sometimes your programs need to use the information in the i-node structure to
do some job. You can access this information with the stat(), lstat() and fstat() system calls.
opendir - open a directory
o.
nr
SYNOPSIS
#include <sys/types.h>
#include <dirent.h>
ub
e.c
ht
tp
://
cs
et
DESCRIPTION
The opendir() function opens a directory stream corresponding to the directory name,
and returns a pointer to the directory stream. The stream is positioned at the first entry in
the directory.
RETURN VALUE
The opendir() function returns a pointer to the directory stream or NULL if an error
occurred.
readdir - read directory entry
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.
int readdir(unsigned int fd, struct dirent *dirp, unsigned int count);
closedir - close a directory
int closedir(DIR *dir);
DESCRIPTION
The closedir() function closes the directory stream associated with dir. The directory
stream descriptor dir is not available after this call.
Lab Manual
http://csetube.co.nr/
e.c
ub
ht
tp
://
cs
et
o.
nr
main()
{
int pid,ppid;
pid=getpid();
ppid=getppid();
http://csetube.co.nr/
ub
et
cs
://
/* 4. orphan process */
#include <sys/types.h>
#include <unistd.h>
#include<stdio.h>
e.c
o.
nr
{
int pid;
pid=fork();
if(pid==0)
{
printf("\n I am the child, my process ID is %d ",getpid());
printf("\n I am the child's parent process ID is %d ",getppid());
}
else
{
printf("\n I am the parent, my process ID is %d ",getpid());
printf("\n I am the parent's parent process ID is %d ",getppid());
}
}
OUTPUT
i am the parent, my process ID is 5273
i am the parent's parent,process ID is 5129
I am the child, my process ID is 5274
I am the child's parent, process ID is 1
ht
tp
main()
{
int pid;
pid=fork();
if(pid==0)
{
printf("\n I am the child, my process ID is %d ",getpid());
printf("\n I am the child's parent process ID is %d ",getppid());
sleep(10);
printf("\n I am the child, my process ID is %d ",getpid());
printf("\n I am the child's parent process ID is %d ",getppid());
}
else
{
printf("\n I am the parent, my process ID is %d ",getpid());
printf("\n I am the parent's parent process ID is %d ",getppid());
}
}
OUTPUT
I am the child, my process ID is 5301
I am the parent, my process id is 5300
Lab Manual
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
Lab Manual
http://csetube.co.nr/
://
tp
ht
cs
et
ub
e.c
o.
nr
http://csetube.co.nr/
nr
#include <sys/types.h>
#include <unistd.h>
#include<stdddio.h>
main()
{
e.c
o.
ht
tp
://
cs
et
ub
if ( fork () == 0 ) {
/* == 0 means in child */
scanf ("%d", &status);
exit (status);
}
else {
/* != 0 means in parent */
wait (&status);
printf("child exit status = %d\n", status > 8);
}
}
OUTPUT
child exit status=1
10
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
}
OUTPUT
./a.out
grep.c 1387273
simu.c 1387274
a.out 1387265
. 1387247
hi 1387233
.. 1387211
rem.c 1387276
Result :
Thus C program was written programs using the fork, exec, getpid, exit, wait, stat,
opendir, readdir system calls of UNIX operating system.
Lab Manual
11
http://csetube.co.nr/
To write a C program using open(), read(), write and close system calls.
Description
open()
open() lets you open a file for reading, writing, or reading and writing. The prototype for the
open() system call is:
int open(char *file_name, int option_flags int [, mode])
where file_name is a pointer to the character string that names the file, option_flags represent
the type of channel, and mode defines the file's access permissions if the file is being created.
read() write()
The read() system call does all input and the write() system call does all output.When used
together, they provide all the tools necessary to do input and output sequentially.
o.
nr
Both read() and write() take three arguments. Their prototypes are:
et
ub
e.c
ht
tp
://
cs
where file_descriptor identifies the I/O channel, buffer_pointer points to the area in memory
where the data is stored for a read() or where the data is taken for a write(), and transfer_size
defines the maximum number of characters transferred between the file and the buffer. read()
and write() return the number of bytes transferred.
close()
To close a channel, use the close() system call. The prototype for the close() system call is:
int close(int file_descriptor)
where file_descriptor identifies a currently open channel. close() fails if file_descriptor does
not identify a currently open channel.
Exercises
/* 1. using creat system call */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main()
{
int fd;
fd = creat("datafile.dat", S_IREAD | S_IWRITE);
if (fd == -1)
printf("Error in opening datafile.dat\n");
else
Lab Manual
12
http://csetube.co.nr/
{
printf("datafile.dat opened for read/write access\n");
printf("datafile.dat is currently empty\n");
}
close(fd);
exit (0);
://
cs
et
ub
e.c
o.
nr
ht
tp
13
http://csetube.co.nr/
nr
o.
e.c
ub
et
cs
ht
tp
://
Lab Manual
14
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
main()
{
char buf[100],fn[10];
int fd,n;
printf("enter file name");
scanf("%s",fn);
printf("\n enter text\n");
scanf("%s",buf);
fd=open(fn,O_CREAT|O_WRONLY,0666);
n=write(fd,buf,strlen(buf));
close(fd);
}
Result :
Thus C program was written using open(), read(), write() and close() system calls.
Lab Manual
15
http://csetube.co.nr/
Aim :
Description :
UNIX commands can be simulated in the high level language using Unix system calls
and APIs available in the language. In addition, programming language construct can also
be used to avail the UNIX commands.
ub
et
cs
ht
tp
://
/* 1. Siumulation of ls command */
#include<dirent.h>
#include<stdio.h>
main()
{
char dirname[10];
DIR *p;
struct dirent *d;
printf("Enter directory name ");
scanf("%s",dirname);
p=opendir(dirname);
if(p==NULL)
{
perror("Cannot find dir.");
exit(-1);
}
while(d=readdir(p))
printf("%s\n",d->d_name);
}
OUTPUT:
enter directory name iii
.
..
f2
f1
e.c
o.
nr
Exercises :
1. Siumulation of ls command
Algorithm :
1. Include necessary header files for manipulating directory.
2. Declare and initialize required objects.
3. Read the directory name form the user
4. Open the directory using opendir() system call and report error if the directory is
not available
5. Read the entry available in the directory
6. Display the directory entry (ie., name of the file or sub directory.
7. Repeat the step 6 and 7 until all the entries were read.
Lab Manual
16
http://csetube.co.nr/
nr
o.
e.c
ub
ht
tp
://
cs
et
3. Simulation of cp command
Algorithm:
1. Include required header file
2. Make necessary declarations
3. Read the source and destination file names from the user.
4. Using read() system call, read the content of the file to the buffer.
5. Uing write() system call, write the buffer content to the destination file.
6. Close the opened files.
Lab Manual
17
http://csetube.co.nr/
nr
o.
e.c
ub
et
cs
://
tp
ht
OUTPUT:
enter source file name
ls.c
enter destination file name
file8
[it2-20@localhost ~]$ cat file8
#include<dirent.h>
#include<stdio.h>
main()
{
char dirname[10];
DIR *p;
struct dirent *d;
printf("enter directory name");
scanf("%s",dirname);
p=opendir(dirname);
if(p==NULL)
{
perror("cannot find directory");
exit(-1);
}
while(d=readdir(p))
printf("%s\n",d->d_name);
}
Lab Manual
18
http://csetube.co.nr/
et
ub
e.c
o.
nr
#include<stdio.h>
#include<fcntl.h>
main()
{
char fn[10];
printf("Enter source file name ");
scanf("%s",fn);
if(remove(fn)==0)
printf("\nFile/Dir removed");
else
printf("\nCannot be removed");
}
OUTPUT:
enter source file name
file10
ht
tp
://
cs
file/directory removed
Result :
Thus C program was written to simulate some Unix Commands
Lab Manual
19
http://csetube.co.nr/
CPU/Process Scheduling
The assignment of physical processors to processes allows processors to accomplish work.
The problem of determining when processors should be assigned and to which processes is
called processor scheduling or CPU scheduling.
When more than one process is runable, the operating system must decide which one first.
The part of the operating system concerned with this decision is called the scheduler, and
algorithm it uses is called the scheduling algorithm.
nr
First-In-First-Out (FIFO)
Run-to-Completion
Run-Until-Done
o.
e.c
ht
tp
://
cs
et
ub
Lab Manual
20
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
#include<stdio.h>
struct process
{
char pName[10];
int ex_time,wt_time,st_time,end_time;
}p[10];
main()
{
int n,i,j,k;
float avgwaittime=0.0,avgTurnAroundTime=0.0;
float totalWaitTime=0.0;
int totalExecTime=0,totalTurnAroundTime=0;
printf("\n enter number of process");
scanf("%d",&n);
p[0].st_time=0;
p[0].wt_time=0;
printf("\n enter process name");
scanf("%s",p[i].pName);
printf("enter Burst time");
scanf("%d",&p[i].ex_time);
if(i==0) p[i].end_time=p[i].ex_time;
else
{
p[i].wt_time=p[i-1].end_time;
p[i].st_time=p[i-1].end_time;
p[i].end_time=p[i].st_time+p[i].ex_time;
}
}
for(j=0;j<n;j++)
{
totalExecTime+=p[j].ex_time;
totalWaitTime+=p[j].wt_time;
}
totalTurnAroundTime=totalExecTime+totalWaitTime;
avgwaittime=(float)totalWaitTime/n;
avgTurnAroundTime=(float)totalTurnAroundTime/n;
printf("\n\n Name Burst Start End Wait Time\n");
for(k=0;k<n;k++)
printf("\n%s \t%d \t%d \t%d \t%d",p[k].pName,p[k].ex_time,p[k].st_time,p[k
].end_time,p[k].wt_time);
printf("\nAverage Waiting Time %f",avgwaittime);
Lab Manual
21
http://csetube.co.nr/
o.
nr
ub
et
cs
://
e.c
ht
tp
p1
3
0
3
0
p2
2
3
5
3
p3
1
5
6
5
p4
4
6
10
6
p5
2
10
12
10
Average Waiting Time 4.800000
Average Turn Around Time 7.200000
22
http://csetube.co.nr/
nr
o.
e.c
ub
://
cs
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
temp=p[i];p[i]=p[j];p[j]=temp;
}
}
p[0].wt_time=0;
p[0].st_time=0;
p[0].end_time=p[0].ex_time;
for(j=0;j<n;j++)
{
if(j>0)
et
int totalexectime=0,totalturnaroundtime=0;
printf("\n enter the number of process");
scanf("%d",&n);
p[0].st_time=0;
p[0].wt_time=0;
for(i=0;i<n;i++)
ht
tp
{
p[j].wt_time=p[j-1].end_time;
p[j].st_time=p[j-1].end_time;
p[j].end_time=p[j].st_time+p[j].ex_time;
}
totalexectime+=p[j].ex_time;
totalwaittime+=p[j].wt_time;
}
avgwaittime=(float)totalwaittime/n;
totalturnaroundtime=totalexectime+totalwaittime;
avgturnaroundtime=(float)totalturnaroundtime/n;
printf("\n\nname brust start endwaittime\n");
for(k=0;k<n;k++)
printf("\n%s\t%d\t%d\t%d\t%d",p[k].pname,p[k].ex_time,p[k].st_time,p[k].end_time
,p[k].wt_time);
printf("\naverage waiting time %f",avgwaittime);
printf("\n average turnaroundtime %f",avgturnaroundtime);
}
Lab Manual
23
http://csetube.co.nr/
nr
0
2
5
9
o.
2
5
9
15
e.c
0
2
5
9
ub
2
3
4
6
ht
tp
://
cs
et
p4
p1
p3
p2
Result :
Thus C program was written for simulating FCFS and SJF scheduling algorithms.
Lab Manual
24
http://csetube.co.nr/
Priority Scheduling
The basic idea is straightforward: each process is assigned a priority, and priority is allowed
to run. Equal-Priority processes are scheduled in FCFS order. The shortest-Job-First (SJF)
algorithm is a special case of general priority scheduling algorithm.
An SJF algorithm is simply a priority algorithm where the priority is the inverse of the
(predicted) next CPU burst. That is, the longer the CPU burst, the lower the priority and vice
versa.
Priority can be defined either internally or externally. Internally defined priorities use some
measurable quantities or qualities to compute priority of a process.
nr
o.
e.c
ub
Time limits.
Memory requirements.
File requirements,
for example, number of open files.
CPU Vs I/O requirements.
et
cs
://
Externally defined priorities are set by criteria that are external to operating system such as
tp
ht
A preemptive priority algorithm will preemptive the CPU if the priority of the newly
arrival process is higher than the priority of the currently running process.
A non-preemptive priority algorithm will simply put the new process at the head of
the ready queue.
25
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
Priority Scheduling
#include<stdio.h>
struct process
{
char pname[10];
int ex_time,wt_time,st_time,end_time,turn_time,priority;
}p[10],temp;
main()
{
int n,i,j,k;
float avgwaittime=0.0,avgturnaroundtime=0.0;
float totalwaittime=0.0;
int totalexectime=0,totalturnaroundtime=0;
printf("\nenter number of process");
scanf("%d",&n);
p[0].st_time=0;
p[0].wt_time=0;
for(i=0;i<n;i++)
{
printf("\nenter process name");
scanf("%s",p[i].pname);
printf("\nenter process priority 0 with highest priority");
scanf("%d",&p[i].priority);
printf("enter burst time");
scanf("%d",&p[i].ex_time);
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(p[i].priority<p[j].priority)
{
temp=p[i];
p[i]=p[j];
p[j]=temp;
}
}
Lab Manual
26
http://csetube.co.nr/
OUTPUt:
ht
tp
://
cs
et
ub
e.c
o.
nr
if(j==0)
{
p[j].wt_time=0;
p[j].st_time=0;
p[j].end_time=p[j].ex_time;
p[j].turn_time=p[j].ex_time+p[j].wt_time;
}
if(j>0)
{
p[j].wt_time=p[j-1].end_time;
p[j].st_time=p[j-1].end_time;
p[j].end_time=p[j].st_time+p[j].ex_time;
p[j].turn_time=p[j].ex_time+p[j].wt_time;
}
totalexectime+=p[j].ex_time;
totalwaittime+=p[j].wt_time;
totalturnaroundtime+=p[j].turn_time;
}
avgwaittime=(float)totalwaittime/n;
avgturnaroundtime=(float)totalturnaroundtime/n;
printf("\n\nname burst start end waittime\n");
for(k=0;k<n;k++)
printf("\n%s\t%d\t%d\t%d\t%d\t%d",p[k].pname,p[k].ex_time,p[k].st_time,p[k].end_
time,p[k].wt_time);
37,1
87%
printf("\naveragewaitingtime%f",avgwaittime);
printf("\naverageturnaroundtime%f",avgturnaroundtime);
}
Lab Manual
27
http://csetube.co.nr/
4
3
2
6
0
4
7
9
4
7
9
15
0
4
7
9
nr
o.
ht
tp
://
cs
et
ub
e.c
for(i=0;i<n;i++)
{
printf("\nEnter process name");
scanf("%s",p[i].PName);
printf("Enter Burst time ");
scanf("%d",&p[i].ex_time);
p[i].rem_time=p[i].ex_time;
p[i].completed_time=0;
}
printf("\nEnter quantum time ");
scanf("%d",&quant_time);
printf("\n name start end busrt rem compl");
/* for first process start and the wait time to be 0 */
j=0;
fs=p[j].st_time=0;
p[j].wt_time=0;
if(p[j].ex_time>quant_time)
{ p[j].end_time=quant_time;
p[j].completed_time=quant_time;
}
Lab Manual
28
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
fe=p[j].end_time;
j++;
while(j<n)
{
p[j].st_time=fe;
if(p[j].rem_time>quant_time)
{
p[j].end_time=p[j].st_time+quant_time;
p[j].rem_time-=quant_time;
p[j].completed_time+=quant_time;
fe+=quant_time;
printf("\n%s\t%d\t%d\t%d\t%d\t%d",p[j].PName,p[j].st_time,p[j].end_time,p[j].ex_time,p[j].
rem_time,p[j].completed_time);
}
else if(p[j].rem_time>0)
{
p[j].end_time=p[j].st_time+p[j].rem_time;
p[j].wt_time=fe-p[j].completed_time;
p[j].completed_time+=p[j].rem_time;
p[j].turn_time=p[j].wt_time+p[j].ex_time;
fe+=p[j].rem_time;
p[j].rem_time=0;
printf("\n%s\t%d\t%d\t%d\t%d\t%d",p[j].PName,p[j].st_time,p[j].end_time,p[j].ex_time,p[j].
rem_time,p[j].completed_time);
}
j++;
if(j==n)
{
for(k=0;k<n;k++)
{
if(p[k].rem_time>0) /*break for the inner for loop */
{ j=k;
break; }
}
if(k>n) /* breaks from the outer while loop */
break;
}
}
Lab Manual
29
http://csetube.co.nr/
nr
e.c
o.
et
ub
://
cs
ht
tp
Result :
Thus C program was written for simulating FCFS and SJF scheduling algorithms.
Lab Manual
30
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
1. Signals - Sent by other processes or the kernel to a specific process to indicate various
conditions.
2. Pipes - Unnamed pipes set up by the shell normally with the "|" character to route
output from one program to the input of another.
3. FIFOS - Named pipes operating on the basis of first data in, first data out.
4. Message queues - Message queues are a mechanism set up to allow one or more
processes to write messages that can be read by one or more other processes.
5. Semaphores - Counters that are used to control access to shared resources. These
counters are used as a locking mechanism to prevent more than one process from
using the resource at a time.
6. Shared memory - The mapping of a memory area to be shared by multiple processes.
Message queues, semaphores, and shared memory can be accessed by the processes if they
have access permission to the resource as set up by the object's creator. The process must
pass an identifier to the kernel to be able to get the access.
PIPES
The Linux IPC (Inter-process communication) facilities provide a method for multiple
processes to communicate with one another. There are several methods of IPC available to
Linux.
Simply put, a pipe is a method of connecting the standard output of one process to the
standard input of another. Pipes are the eldest of the IPC tools, having been around since the
earliest incarnations of the UNIX operating system. They provide a method of one-way
communications (hence the term half-duplex) between processes.
To create a simple pipe with C, we make use of the pipe() system call. It takes a single
argument, which is an array of two integers, and if successful, the array will contain two new
file descriptors to be used for the pipeline. After creating a pipe, the process typically spawns
a new process (remember the child inherits open file descriptors).
PROTOTYPE: int pipe( int fd[2] );
RETURNS: 0 on success
-1 on error
Lab Manual
31
http://csetube.co.nr/
o.
nr
cs
et
ub
e.c
The function shmat attaches the shared memory segment identified by shmid to the
address space of the calling process. The attaching address is specified by shmaddr with
one of the following criteria:
int shmdt(const void *shmaddr);
at
the address
Message Queues
ht
tp
://
Message queues can be best described as an internal linked list within the kernel's addressing
space. Messages can be sent to the queue in order and retrieved from the queue in several
different ways. Each message queue (of course) is uniquely identified by an IPC identifier.
Message queues allow one or more processes to write messages, which will be read by one or
more reading processes. Linux maintains a list of message queues, the msgque vector; each
element of which points to a msqid_ds data structure that fully describes the message queue.
When message queues are created a new msqid_ds data structure is allocated from system
memory and inserted into the vector.
NAME
msgget - get a message queue identifier
SYNOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
Lab Manual
32
http://csetube.co.nr/
o.
nr
#include <sys/msg.h>
e.c
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
://
cs
et
ub
The msgsnd system call appends a copy of the message pointed to by msgp to the
message queue whose identifier is specified by msqid.
ht
tp
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msg-
The system call msgrcv reads a message from the message queue specified by msqid
into the msgbuf pointed to by the msgp argument, removing the read message from the
queue.
Exercise Programs :
/* 1. IPC USING PIPES */
#include<stdio.h>
main()
{
int fd[2],child;
char a[10];
printf("\nEnter the string to enter into the pipe ");
scanf("%s",a);
pipe(fd);
child=fork();
if(!child)
{
Lab Manual
33
http://csetube.co.nr/
nr
o.
e.c
ub
et
cs
://
tp
ht
main()
{
int child, shmid,i;
char *shmptr;
child=fork();
if(!child)
{
shmid=shmget(2041,32,0666|IPC_CREAT);
shmptr=shmat(shmid,0,0);
printf("\nParent writing.........\n");
for(i=0;i<10;i++)
{
shmptr[i]='a'+i;
putchar(shmptr[i]);
}
printf("\n%s",shmptr);
wait(NULL);
}
else
{
shmid=shmget(2041,32,0666|IPC_CREAT);
shmptr=shmat(shmid,0,0);
printf("\nReading from child.........\n");
for(i=0;i<10;i++)
putchar(shmptr[i]);
Lab Manual
34
http://csetube.co.nr/
nr
o.
128
e.c
#define MSGSZ
et
cs
://
tp
ht
ub
main()
{
int msqid;
int msgflg = IPC_CREAT | 0666;
key_t key;
message_buf sbuf;
size_t buf_length;
/* Get the message queue id for the "name" 1234, which was created by
* the server. */
key = 1234;
msqid = msgget(key, msgflg );
/* We'll send message type 1 */
sbuf.mtype = 1;
(void) strcpy(sbuf.mtext, "Did you get this?");
buf_length = strlen(sbuf.mtext) ;
/* Send a message. */
msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT);
Lab Manual
35
http://csetube.co.nr/
}
OUTPUT:
message:"did you get there?" sent
e.c
o.
nr
ht
tp
://
cs
et
ub
main()
{
int msqid;
key_t key;
message_buf rbuf;
/* Get the message queue id for the "name" 1234, which was created by the server. */
key = 1234;
msqid = msgget(key, 0666);
/* Receive an answer of message type 1
msgrcv(msqid, &rbuf, MSGSZ, 1, 0);
*/
}
OUTPUT:
message:"did you get there?" received
Result :
Thus C program was program written to implement IPC using pipes, shared memory and
message queues.
Lab Manual
36
http://csetube.co.nr/
Aim :
To write a C program to implement producer consumer problem using semaphore.
Semaphores
Semaphore is a location in memory whose value can be tested and set by more than one
process. The test and set operation is, so far as each process is concerned, uninterruptible or
atomic; once started nothing can stop it. The result of the test and set operation is the addition
of the current value of the semaphore and the set value, which can be positive or negative.
Depending on the result of the test and set operation one process may have to sleep until the
semphore's value is changed by another process. Semaphores can be used to implement
critical regions, areas of critical code that only one process at a time should be executing.
et
ub
e.c
o.
nr
Say you had many cooperating processes reading records from and writing records to a single
data file. You would want that file access to be strictly coordinated. You could use a
semaphore with an initial value of 1 and, around the file operating code, put two semaphore
operations, the first to test and decrement the semaphore's value and the second to test and
increment it. The first process to access the file would try to decrement the semaphore's value
and it would succeed, the semaphore's value now being 0. This process can now go ahead and
use the data file but if another process wishing to use it now tries to decrement the
semaphore's value it would fail as the result would be -1. That process will be suspended until
the first process has finished with the data file. When the first process has finished with the
data file it will increment the semaphore's value, making it 1 again. Now the waiting process
can be woken and this time its attempt to increment the semaphore will succeed.
://
cs
ht
tp
37
http://csetube.co.nr/
ub
e.c
o.
nr
DESCRIPTION
The function semctl performs the control operation specified by cmd on the semaphore
set identified by semid, or on the semnum-th semaphore of that set. (Semaphores are
numbered starting at 0.)
cs
et
ht
tp
://
#include <stdio.h>
/* standard I/O routines.
*/
#include <stdlib.h> /* rand() and srand() functions
*/
#include <unistd.h> /* fork(), etc.
*/
#include <time.h>
/* nanosleep(), etc.
*/
#include <sys/types.h> /* various type definitions.
*/
#include <sys/ipc.h> /* general SysV IPC structures
*/
#include <sys/sem.h> /* semaphore functions and structs. */
#define NUM_LOOPS
10
38
http://csetube.co.nr/
ub
e.c
o.
nr
child_pid = fork();
switch (child_pid) {
case 0:
/* child process here */
for (i=0; i<NUM_LOOPS; i++) {
/* block on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
printf("consumer: '%d'\n", i);
fflush(stdout);
}
break;
default:
/* parent process here */
for (i=0; i<NUM_LOOPS; i++) {
printf("producer: '%d'\n", i);
fflush(stdout);
/* increase the value of the semaphore by 1. */
sem_op.sem_num = 0;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
ht
tp
://
cs
et
}
break;
return 0;
}
OUTPUT:
Semaphore set created ,semaphore set id '2588751'
Producer:0
Consumer:0
Producer:1
Producer:2
Consumer:1
Consumer:2
Producer:3
Consumer:3
Producer:4
Consumer:4
Producer:5
Lab Manual
39
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
Producer:6
Producer:7
Consumer:5
Consumer:6
Consumer:7
Producer:8
Producer:9
Consumer:8
Consumer:9
Result :
Thus C program was written to implement producer consumer problem using semaphores.
Lab Manual
40
http://csetube.co.nr/
nr
In an environment that supports dynamic memory allocation, the memory manager must keep
a record of the usage of each allocatable block of memory. This record could be kept by using
almost any data structure that implements linked lists. An obvious implementation is to
define a free list of block descriptors, with each descriptor containing a pointer to the next
descriptor, a pointer to the block, and the length of the block. The memory manager keeps a
free list pointer and inserts entries into the list in some order conducive to its allocation
strategy. A number of strategies are used to allocate space to the processes that are competing
for memory.
e.c
o.
Best Fit
et
ub
The allocator places a process in the smallest block of unallocated memory in which it will
fit.
://
tp
It requires an expensive search of the entire free list to find the best hole.
More importantly, it leads to the creation of lots of little holes that are not big enough
to satisfy any requests. This situation is called fragmentation, and is a problem for all
memory-management strategies, although it is particularly bad for best-fit.
ht
cs
Problems:
Solution: One way to avoid making little holes is to give the client a bigger block than it
asked for. For example, we might round all requests up to the next larger multiple of 64
bytes. That doesn't make the fragmentation go away, it just hides it.
Worst Fit
The memory manager places process in the largest block of unallocated memory available.
The idea is that this placement will create the largest hole after the allocations, thus
increasing the possibility that, compared to best fit, another process can use the hole created
as a result of external fragmentation.
First Fit
Lab Manual
41
http://csetube.co.nr/
Small holes tend to accumulate near the beginning of the free list, making the memory
allocator search farther and farther each time.
ub
e.c
o.
nr
The first fit approach tends to fragment the blocks near the beginning of the list without
considering blocks further down the list. Next fit is a variant of the first-fit strategy. The
problem of small holes accumulating is solved with next fit algorithm, which starts each
search where the last one left off, wrapping around to the beginning when the end of the list
is reached (a form of one-way elevator)
ht
tp
://
cs
et
Result:
Thus C program was written to implement first fit and best fit allocation strategies.
Basic idea: allocate physical memory to processes in fixed size chunks called page
frames. Present abstraction to application of a single linear address space. Inside machine,
break address space of application up into fixed size chunks called pages. Pages and page
frames are same size. Store pages in page frames. When process generates an address,
dynamically translate to the physical page frame which holds data for that page.
So, a virtual address now consists of two pieces: a page number and an offset within that
page. Page sizes are typically powers of 2; this simplifies extraction of page numbers and
offsets. To access a piece of data at a given address, system automatically does the
following:
o Extracts page number.
o Extracts offset.
o Translate page number to physical page frame id.
Lab Manual
42
http://csetube.co.nr/
ht
tp
://
cs
et
ub
e.c
o.
nr
Lab Manual
43
http://csetube.co.nr/