You are on page 1of 50

S.K.

P INSTITUTE OF TECHNOLOGY Tiruvannamalai 606 611

CS2257

Operating System Lab


II YEAR / SEMESTER-IV

PREPARED BY R.DEVI Assistant Professor/CSE

List of Experiments
EX.NO DATE NAME OF THE EXPREMENTS
Write programs using the following system calls of UNIX operating system:fork, exec, getpid, exit, wait, close, stat, opendir, readdir Write programs using the I/O system calls of UNIX operating system (open, read, write, etc) Write C programs to simulate UNIX commands like ls, grep, etc. 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) 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) Developing Application using Inter Process communication (using shared memory, pipes or message queues) Implement the Producer Consumer problem using semaphores (using UNIX system calls). Implement some memory management schemes I Implement some memory management schemes II Implement any file allocation technique (Linked, Indexed or Contiguous)

MARK

SIGNATURE

2 3

7 8 9 10

1. Process , Directory & File Management system calls


Aim : To write C programs for the fork, exec, getpid, exit, wait, stat, opendir, readdir system calls of UNIX operating system. Description 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 getpid, getppid To get the process and parent process identification number. General Syntax: 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() The new process inherits several characteristics of the old process. Among the characteristics inherited are:

The environment. All signal settings. The set user ID and set group ID status. The time left until an alarm clock signal. The current working directory and the root directory. The file creation mask as established with umask(). The child process begins executing and the parent process continues executing at the return from the fork() system call. This is difficult to understand at first because you only call fork() once, yet it returns twice -- once per process. To differentiate which process is which, fork() returns zero in the child process and non-zero (the child's process ID) in the parent process. exec system call 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: int execl(file_name, arg0 [, arg1, ..., argn], NULL) char *file_name, *arg0, *arg1, ..., *argn; wait() 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. 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 SYNOPSIS #include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); 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. Exercises: /* 1. Program to print the process id */ Algorithm: 1. Include necessary header files for using systems calls. 2. Make necessary declaration. 3. Get the process identification number and parent process identification number using getpid() and getppid() system calls 4. Display the process ids

#include <sys/types.h> #include <unistd.h> #include<stdio.h> main() { int pid,ppid; pid=getpid(); ppid=getppid(); printf("\n Process Id is %d\n",pid); printf("\n Parent Process Id is %d\n",ppid); } OUTPUT process ID is 5198 parent process ID is 5129 /* 2. Program using fork system call */ #include <sys/types.h> #include <unistd.h> #include<stdio.h> main() { printf("\n This is to demonstrate the fork()"); fork(); printf("\nAfter fork()"); } OUTPUT this is to demonstrate fork() after fork() /* 3. fork and pid */ #include <sys/types.h> #include <unistd.h> #include<stdio.h> 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()); } 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 /* 4. orphan process */ #include <sys/types.h> #include <unistd.h> #include<stdio.h> 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 I am the parent's parent, my process ID is 5129 [it2-21@localhost ~]$ I am the child's parent, my process ID is 5300 I am the child, my process Id is 5301 I am the child's parent, my process ID is 1 /* 5. exec system call */ #include <sys/types.h> #include<stdio.h> #include <unistd.h> main() { execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0); } OUTPUT total 384 -rw-rw-r-- 1 it2-21 it2-21 359 Oct 14 08:24 pol.cpp

-rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 -rw-rw-r-- 1 it2-21 it2-21 ---------x 1 it2-21 it2-21 /* 6. exec system call */ #include <unistd.h> #include <sys/types.h> #include<stdio.h>

200 Dec 8 11:35 forks.c 102 Dec 14 10:48 exec1.c 283 Dec 14 11:06 wait.c 246 Dec 14 11:22 exit.c 214 Dec 14 11:25 exit1.c 393 Dec 14 12:12 opre.c 367 Dec 14 12:13 fileinfo.c 0 Dec 14 12:20 read.cpp 1786 Dec 18 09:50 poly.cpp 153 Dec 21 11:31 op.c 0 Dec 21 11:32 buf,c 197 Dec 21 11:32 buf.c 0 Dec 21 11:33 fn

main() { execl("/bin/date", "date", NULL); } OUTPUT Mon Jan 11 11:08:50 UTC 2010 /* 7. wait system call */ /* process synchronization */ #include <sys/types.h> #include <unistd.h> #include<stdio.h> main() { int pid,i=0; printf("\n Ready to fork"); pid=fork(); if(pid==0) { printf("\n Child starts "); for(i=0;i<1000;i++); printf("\n Child ends "); } else { wait(0); for(i=0;i<1000;i++); printf("\n Parent process ends ");

} } OUTPUT ready to fork child starts child ends ready to fork parent process ends /* 8. Program using exit system call */ #include <sys/types.h> #include <unistd.h> #include<stdio.h> main() { int p; p=fork(); if(p==0) { printf("\n Child created "); exit(0); printf("\n Process ended "); } if(p<0) { printf("\n Cannnot create child "); exit(-1); printf("\n Process ended "); } } OUTPUT child created

/* 9. Program using exit and wait system call */ #include <sys/types.h> #include <unistd.h> #include<stdddio.h> main() { unsigned int status; 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. Program using lstat() system call */ #include<stdio.h> #include<sys/stat.h> main(int argc,char **argv) { struct stat statbuf; if(lstat(argv[1],&statbuf)==-1) printf("Error : cannot find file information "); else { printf("\n File %s ", argv[1]); printf("\n Inode number %d",statbuf.st_ino); printf("\n UID %d",statbuf.st_uid); printf("\n GID %d",statbuf.st_gid); printf("\n File size in bytes %d",statbuf.st_size); } } OUTPUT ./a.out opre.c file opre.cI node number 1387260UID 998GID 999file size in bytes 393 /* 11. Program using opendir and readdir system call */ #include<stdio.h> #include <sys/types.h> #include <dirent.h> int main(int argc, char *argv[]) { DIR *dp; struct dirent *dirp; if (argc != 2) { printf("a single argument (the directory name) is required\n"); exit(1); } if ( (dp = opendir(argv[1])) == NULL) { printf("can't open %s\n",argv[1]); exit(1); } while ( (dirp = readdir(dp)) != NULL) printf("%s %d\n",dirp->d_name,dirp->d_ino); closedir(dp);

exit(0); }

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.

2. File related system call open(), read(), write()


Aim : 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. Both read() and write() take three arguments. Their prototypes are: int read(int file_descriptor, char * buffer_pointer,unsigned transfer_size) int write(int file_descriptor,char * buffer_pointer, unsigned transfer_size) where file_descriptor identifies the I/O channel, buffer_pointer points to the area in memory where the data is stored for a read() or where the data is taken for a write(), and transfer_size defines the maximum number of characters transferred between the file and the buffer. read() and write() return the number of bytes transferred. 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> /* defines types used by sys/stat.h */ /* defines S_IREAD & S_IWRITE */

int main() { int fd; fd = creat("datafile.dat", S_IREAD | S_IWRITE); if (fd == -1) printf("Error in opening datafile.dat\n"); else { printf("datafile.dat opened for read/write access\n");

printf("datafile.dat is currently empty\n"); } close(fd); exit (0); } /* 2. using open, write system call */ #include<fcntl.h> #include<unistd.h> main() { int fd,i; fd=open("test",O_CREAT|O_RDWR|O_APPEND,0666); for(i=0;i<100;i++) write(fd,"A",1); close(fd); } OUTPUT: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /* 3. using - open ,read and write system calls */ /* reading a content from file and displaying it to monitor */ #include<stdio.h> #include<fcntl.h> main() { char buf[100],fn[10]; int fd,n; printf("Enter file name "); scanf("%s",fn); fd=open(fn,O_RDONLY); n=read(fd,buf,100); n=write(1,buf,n);//write to monitor close(fd); } OUTPUT enter file name open.c #include<stdio.h> #include<fcntl.h> main() { char buf[1000],fn1[10],fn2[10]; int fd1,fd2,n;

/* 4. using - write system calls writing line of text the file */ #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("\nEnter text "); gets(buf); fd=open(fn,O_CREAT|0666); n=write(fd,buf,strlen(buf));//write file close(fd); } OUTPUT: enter file name open.c enter text HI ! HInclude<stdio.h> #include<fcntl.h> main() { char buf[1000],fn1[10],fn2[10]; }

/* 5. using - open ,read and write system calls file copy operation*/ #include<stdio.h> #include<fcntl.h> main() { char buf[1000],fn1[10],fn2[10]; int fd1,fd2,n; printf("Enter source file name "); scanf("%s",fn1); printf("Enter destination file name "); scanf("%s",fn2); fd1=open(fn1,O_RDONLY); n=read(fd1,buf,1000); fd2=open(fn2,O_CREAT|0666); n=write(fd2,buf,n);//write file close(fd1); close(fd2); }

OUTPUT enter source file name write.c enter destination file name read.c #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.

3. Simulation of Unix Commands


Aim : To write a C program to simulate basic Unix commands like ls,grep, cp,rm 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. 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. /* 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

2. Simulation of grep command. Algorithm : 1. Include necessary header files 2. Make necessary declarations 3. Read the file name from the user and open the file in the read only mode. 4. Read the pattern from the user. 5. Read a line of string from the file and search the pattern in that line. 6. If pattern is available, print the line. 7. Repeat the step 4 to 6 till the end of the file. /* 2. Simulation of grep command */ #include<stdio.h> #include<string.h> main() { char fn[10],pat[10],temp[200]; FILE *fp; printf("\n Enter file name : "); scanf("%s",fn); printf("Enter the pattern to be searched : "); scanf("%s",pat); fp=fopen(fn,"r"); while(!feof(fp)) { fgets(temp,1000,fp); if(strstr(temp,pat)) printf("%s",temp); } fclose(fp); } OUTPUT: enter file name: file4 enter the pattern to be searched: roll roll no percentage grade 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.

/* using - open ,read and write system calls file copy operation*/ #include<stdio.h> #include<fcntl.h> main() { char buf[1000],fn1[10],fn2[10]; int fd1,fd2,n; printf("Enter source file name "); scanf("%s",fn1); printf("Enter destination file name "); scanf("%s",fn2); fd1=open(fn1,O_RDONLY); n=read(fd1,buf,1000); fd2=open(fn2,O_CREAT|0666); n=write(fd2,buf,n);//write file close(fd1); close(fd1); } 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); }

/* 4. to remove file or dir. */ Algorithm: 1. Include required header file 2. Make necessary declarations 3. Read the file name from the user. 4. Using remove () system call remove the file from the user. #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 file/directory removed

Result : Thus C program was written to simulate some Unix Commands

4. Process Scheduling FCFS, SJF


Aim : To write C program to simulate FCFS and SJF scheduling algorithms.

CPU/ProcessScheduling
Theassignmentofphysicalprocessorstoprocessesallowsprocessorstoaccomplishwork.The problemofdeterminingwhenprocessorsshouldbeassignedandtowhichprocessesiscalled processorschedulingorCPUscheduling. Whenmorethanoneprocessisrunable,theoperatingsystemmustdecidewhichonefirst.The partoftheoperatingsystemconcernedwiththisdecisioniscalledthescheduler,andalgorithmit usesiscalledtheschedulingalgorithm.

FirstComeFirstServed(FCFS)Scheduling
Othernamesofthisalgorithmare:

FirstInFirstOut(FIFO) RuntoCompletion RunUntilDone

Perhaps,FirstComeFirstServedalgorithmisthesimplestschedulingalgorithmisthesimplest schedulingalgorithm.Processesaredispatchedaccordingtotheirarrivaltimeonthereadyqueue. Beinganonpreemptivediscipline,onceaprocesshasaCPU,itrunstocompletion.TheFCFS schedulingisfairintheformalsenseorhumansenseoffairnessbutitisunfairinthesensethat longjobsmakeshortjobswaitandunimportantjobsmakeimportantjobswait. FCFSismorepredictablethanmostofotherschemessinceitofferstime.FCFSschemeisnot usefulinschedulinginteractiveusersbecauseitcannotguaranteegoodresponsetime.Thecode forFCFSschedulingissimpletowriteandunderstand.Oneofthemajordrawbackofthis schemeisthattheaveragetimeisoftenquitelong.

ShortestJobFirst(SJF)Scheduling
OthernameofthisalgorithmisShortestProcessNext(SPN). ShortestJobFirst(SJF)isanonpreemptivedisciplineinwhichwaitingjob(orprocess)withthe smallestestimatedruntimetocompletionisrunnext.Inotherwords,whenCPUisavailable,it isassignedtotheprocessthathassmallestnextCPUburst. TheSJFschedulingisespeciallyappropriateforbatchjobsforwhichtheruntimesareknownin advance.SincetheSJFschedulingalgorithmgivestheminimumaveragetimeforagivensetof processes,itisprobablyoptimal. TheSJFalgorithmfavorsshortjobs(orprocessors)attheexpenseoflongerones. TheobviousproblemwithSJFschemeisthatitrequirespreciseknowledgeofhowlongajobor

processwillrun,andthisinformationisnotusuallyavailable. ThebestSJFalgorithmcandoistorelyonuserestimatesofruntimes. Intheproductionenvironmentwherethesamejobsrunregularly,itmaybepossibletoprovide reasonableestimateofruntime,basedonthepastperformanceoftheprocess.Butinthe developmentenvironmentusersrarelyknowhowtheirprogramwillexecute. LikeFCFS,SJFisnonpreemptivetherefore,itisnotusefulintimesharingenvironmentinwhich reasonableresponsetimemustbeguaranteed. FCFS SCHEDULING #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); printf("\n Average Turn Around Time %f",avgTurnAroundTime); }

SAMPLE INPUT/ OUTPUT: enter number of process 5 enter process name p1 enter Burst time3 enter process name p2 enter Burst time2 enter process name p3 enter Burst time1 enter process name p4 enter Burst time4 enter process namep5 enter Burst time2 Name Burst Start End Wait Time

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

Shortest Job First Scheduling #include<stdio.h> struct process { char pname[10]; int ex_time,wt_time,st_time,end_time; }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("\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++) { printf("\n enter process name"); scanf("%s",p[i].pname); printf("enter burst time"); scanf("%d",&p[i].ex_time); } 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) { 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); } SAMPLE INPUT / OUTPUT: enter the number of process4 enter process namep1 enter burst time3 enter process namep2 enter burst time6 enter process namep3 enter burst time4 enter process namep4 enter burst time2

name burst start end waittime p4 p1 p3 p2 2 3 4 6 0 2 5 9 2 5 9 15 0 2 5 9

average waiting time 4.000000 average turnaroundtime 7.750000

Result : Thus C program was written for simulating FCFS and SJF scheduling algorithms.

5. CPU SCHEDULING PRIPORITY, ROUND ROBIN


Aim : To write a C program for simulating Priority and Round Robin scheduling algorithms.

PriorityScheduling
Thebasicideaisstraightforward:eachprocessisassignedapriority,andpriorityisallowedto run.EqualPriorityprocessesarescheduledinFCFSorder.TheshortestJobFirst(SJF)algorithm isaspecialcaseofgeneralpriorityschedulingalgorithm. AnSJFalgorithmissimplyapriorityalgorithmwherethepriorityistheinverseofthe(predicted) nextCPUburst.Thatis,thelongertheCPUburst,thelowerthepriorityandviceversa. Prioritycanbedefinedeitherinternallyorexternally.Internallydefinedprioritiesusesome measurablequantitiesorqualitiestocomputepriorityofaprocess. ExamplesofInternalprioritiesare

Timelimits. Memoryrequirements. Filerequirements, forexample,numberofopenfiles. CPUVsI/Orequirements. Theimportanceofprocess. Typeoramountoffundsbeingpaidforcomputeruse. Thedepartmentsponsoringthework. Politics. ApreemptivepriorityalgorithmwillpreemptivetheCPUifthepriorityofthenewly arrivalprocessishigherthanthepriorityofthecurrentlyrunningprocess. Anonpreemptivepriorityalgorithmwillsimplyputthenewprocessattheheadofthe readyqueue.

Externallydefinedprioritiesaresetbycriteriathatareexternaltooperatingsystemsuchas

Priorityschedulingcanbeeitherpreemptiveornonpreemptive

Amajorproblemwithpriorityschedulingisindefiniteblockingorstarvation.Asolutiontothe problemofindefiniteblockageofthelowpriorityprocessisaging.Agingisatechniqueof

graduallyincreasingthepriorityofprocessesthatwaitinthesystemforalongperiodoftime.

RoundRobinScheduling
Oneoftheoldest,simplest,fairestandmostwidelyusedalgorithmisroundrobin(RR). Intheroundrobinscheduling,processesaredispatchedinaFIFOmannerbutaregivenalimited amountofCPUtimecalledatimesliceoraquantum. IfaprocessdoesnotcompletebeforeitsCPUtimeexpires,theCPUispreemptedandgivento thenextprocesswaitinginaqueue.Thepreemptedprocessisthenplacedatthebackoftheready list. RoundRobinSchedulingispreemptive(attheendoftimeslice)thereforeitiseffectiveintime sharingenvironmentsinwhichthesystemneedstoguaranteereasonableresponsetimesfor interactiveusers. Theonlyinterestingissuewithroundrobinschemeisthelengthofthequantum.Settingthe quantumtooshortcausestoomanycontextswitchesandlowertheCPUefficiency.Ontheother hand,settingthequantumtoolongmaycausepoorresponsetimeandappoximatesFCFS. Inanyevent,theaveragewaitingtimeunderroundrobinschedulingisoftenquitelong. 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; } } 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); } OUTPUT: Enter the number of processes 4 Enter process name p1 Enter process priority 0 with highest priority 2 Enter burst time 3 Enter process name p2 Enter process priority 0 with highest priority 4 Enter burst time 6

Enter process name p3 Enter process priority 0 with highest priority 1 Enter burst time4 Enter process name p4 Enter process priority 0 with highest priority3 Enter burst time2 name burst start end waittime p3 p1 p4 p2 4 3 2 6 0 4 7 9 4 7 9 15 0 4 7 9

average waiting time 5.000000 average turnaroundtime 8.750000 // ROUND ROBIN SCHEDULING #include<stdio.h> struct process { char PName[10]; int ex_time,wt_time,st_time,end_time,turn_time; int rem_time,completed_time; }p[10],temp; int quant_time; main() { int n,i,j,k; float avgWaitTime=0.0,avgTurnAroundTime=0.0; float totalWaitTime=0.0; int totalExecTime=0,totalTurnAroundTime=0; int fs,fe; printf("\nEnter number of process"); scanf("%d",&n); 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; } else {p[j].end_time=p[j].ex_time; p[j].completed_time=p[j].ex_time; p[j].wt_time=p[j].end_time-p[j].rem_time; p[j].turn_time=p[j].wt_time+p[j].ex_time; } p[j].rem_time=p[j].ex_time-p[j].completed_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); 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; } } printf("\n Process Name Waiting Time Turn Around Time"); for(i=0;i<n;i++) { printf("\n%s\t\t%d\t\t%d",p[i].PName,p[i].wt_time,p[i].turn_time); totalWaitTime+=p[i].wt_time; totalTurnAroundTime+=p[i].turn_time; } avgWaitTime=(float)totalWaitTime/n; avgTurnAroundTime=(float)totalTurnAroundTime/n; printf("\nAverage waiting time %f",avgWaitTime); printf("\nAverage turn around time %f",avgTurnAroundTime); }

OUTPUT: enter number of process4 enter process name p1 enter burst time 3 enter process namep2 enter burst time6 enter process namep3 enter burst time4 enter process namep4 enter burst time2 enter quantum time2 name start end burst rem comp p1 0 2 3 1 2 p2 2 4 6 4 2 p3 4 6 4 2 2 p4 6 8 2 0 2 p1 8 9 3 0 3 p2 9 11 6 2 4 p3 11 13 4 0 4 p2 13 15 6 0 6 processname waitingtime turnaroundtime p1 6 9 p2 9 15 p3 9 13 p4 6 8 average waiting time7.500000 average turn around time 11.250000

Result : Thus C program was written for simulating FCFS and SJF scheduling algorithms.

6. Inter Process communication (using shared memory, pipes or message queues


Aim To write a C program to implement inter-process communication using pipes, shared memory and message queues. Description The Linux IPC (Inter-process communication) facilities provide a method for multiple processes to communicate with one another. The types of inter process communication are: 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 NOTES: fd[0] is set up for reading, fd[1] is set up for writing Shared Memory Shared memory allows one or more processes to communicate via memory that appears in all of their virtual address spaces. The pages of the virtual memory is referenced by page table entries in each of the sharing processes' page tables. It does not have to be at the same address in all of the processes' virtual memory. SYNOPSIS #include <sys/ipc.h> #include <sys/shm.h> shmget - allocates a shared memory segment int shmget(key_t key, size_t size, int shmflg); shmget() returns the identifier of the shared memory segment associated with the value of the argument key. void *shmat(int shmid, const void *shmaddr, int shmflg); 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); The function shmdt detaches the shared memory segment located at the address specified by shmaddr from the address space of the calling process.

Message Queues
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); DESCRIPTION The function returns the message queue identifier associated with the value of the key argument. MSGSND & MSGRCV To send or receive a message, the calling process allocates a structure of the following general form: struct msgbuf { long mtype; }; #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); The msgsnd system call appends a copy of the message pointed to by msgp to the message queue whose identifier is specified by msqid. ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg); 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. /* message type, must be > 0 */ char mtext[1]; /* message data */

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) { close(fd[0]); write(fd[1],a,5); wait(0); } else { close(fd[1]); read(fd[0],a,5); printf("\nThe string received from the pipe is %s\n",a); } return 0; } OUTPUT: enter the string to enter into the pipe hello the string received from the pipe is hello

/* 2. IPC USING SHARED MEMEORY */ #include<stdio.h> #include<sys/shm.h> #include<sys/ipc.h> 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]); shmdt(NULL); shmctl(shmid,IPC_RMID,NULL); }

return 0; } OUTPUT: parent writing... reading from child... abcdefghijabcdefghij abcdefghij

/* 3. a. IPC USING MESSAGE QUEUES - SEND MESSAGE */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <string.h> #define MSGSZ 128

/* Declare the message structure. */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; 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); printf("Message: \"%s\" Sent\n", sbuf.mtext); } OUTPUT: message:"did you get there?" sent

/*3 .b. IPC USING MESSAGE QUEUES - RECEIVE MESSAGE */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #define MSGSZ 128 /* Declare the message structure. */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; 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); /*Print the answer. */ printf("%s\n", rbuf.mtext); exit(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.

7. Producer Consumer problem using semaphores


Aim : To write a C program to implement producer consumer problem using semaphore. Semaphores Semaphoreisalocationinmemorywhosevaluecanbetestedandsetbymorethanoneprocess. Thetestandsetoperationis,sofaraseachprocessisconcerned,uninterruptibleoratomic;once startednothingcanstopit.Theresultofthetestandsetoperationistheadditionofthecurrent valueofthesemaphoreandthesetvalue,whichcanbepositiveornegative.Dependingonthe resultofthetestandsetoperationoneprocessmayhavetosleepuntilthesemphore'svalueis changedbyanotherprocess.Semaphorescanbeusedtoimplement criticalregions,areasof criticalcodethatonlyoneprocessatatimeshouldbeexecuting. Sayyouhadmanycooperatingprocessesreadingrecordsfromandwritingrecordstoasingle datafile.Youwouldwantthatfileaccesstobestrictlycoordinated.Youcoulduseasemaphore withaninitialvalueof1and,aroundthefileoperatingcode,puttwosemaphoreoperations,the firsttotestanddecrementthesemaphore'svalueandthesecondtotestandincrementit.Thefirst processtoaccessthefilewouldtrytodecrementthesemaphore'svalueanditwouldsucceed,the semaphore'svaluenowbeing0.Thisprocesscannowgoaheadandusethedatafilebutif anotherprocesswishingtouseitnowtriestodecrementthesemaphore'svalueitwouldfailasthe resultwouldbe1.Thatprocesswillbesuspendeduntilthefirstprocesshasfinishedwiththe datafile.Whenthefirstprocesshasfinishedwiththedatafileitwillincrementthesemaphore's value,makingit1again.Nowthewaitingprocesscanbewokenandthistimeitsattemptto incrementthesemaphorewillsucceed. A semaphore is represented by an anonymous structure including the following members: unsigned short semval; /* semaphore value */ unsigned short semzcnt; /* # waiting for zero */ unsigned short semncnt; /* # waiting for increase */ pid_t sempid; /* process that did last op */

The function semop performs operations on selected members of the semaphore set indicated by semid. Each of the nsops elements in the array pointed to by sops specifies an operation to be performed on a semaphore by a struct sembuf including the following members: unsigned short sem_num; /* semaphore number */ short sem_op; /* semaphore operation */ short sem_flg; /* operation flags */ #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semop(int semid, struct sembuf *sops, unsigned nsops); SEMGET: semget - get a semaphore set identifier SYNOPSIS #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int semflg); DESCRIPTION This function returns the semaphore set identifier associated with the argument key. semctl - semaphore control operations SYNOPSIS #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semctl(int semid, int semnum, int cmd, ...); 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.) /* program to demonstrate a basic producer-consumer implementation. */ #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

/* number of loops to perform. */

int main(int argc, char* argv[]) { int sem_set_id; /* ID of the semaphore set. */ int child_pid; /* PID of our child process. */ int i; /* counter for loop operation. */ struct sembuf sem_op; /* structure for semaphore ops. */ int rc; /* return value of system calls. */ struct timespec delay; /* used for wasting time. */ /* create a private semaphore set with one semaphore in it, */ /* with access only to the owner. */ sem_set_id = semget(IPC_PRIVATE, 1, 0600); printf("semaphore set created, semaphore set id '%d'.\n", sem_set_id); rc = semctl(sem_set_id, 0, SETVAL, 0); /* fork-off a child process, and start a producer/consumer job. */ 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); /* pause execution for a little bit, to allow the */ /* child process to run and handle some requests. */ /* this is done about 25% of the time. */ if (rand() > 3*(RAND_MAX/4)) { delay.tv_sec = 0; delay.tv_nsec = 10; nanosleep(&delay, NULL); } } 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 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.

8. Memory Management Scheme I ( First Fit and Best Fit Memory Allocation Strategies )
Aim :
To implement memory allocation algorithms first fit and best fit. Description : 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. Best Fit The allocator places a process in the smallest block of unallocated memory in which it will fit. Problems: 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.

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.

Unusable space in the form of holes is called external fragmentation Unusable space in the form of holes is called external fragmentation

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 Another strategy is first fit, which simply scans the free list until a large enough hole is found. Despite the name, first-fit is generally better than best-fit because it leads to less fragmentation. Problems: Small holes tend to accumulate near the beginning of the free list, making the memory allocator search farther and farther each time.

Solution: Next Fit Next Fit 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)

Program for Best fit #include<stdio.h> int main() { int a[20],p[20],i,j,n,m,temp,b[20],temp1,temp2,c[20]; printf(enter the no of blocks \n); scanf(%d,&n); for(i=0;i<n;i++) { printf(enter the % dst block sizei); scanf(d,&a[i]); b[i]=i; } printf(enter the no of process \n); scanf(%d,&m);

for(i=0;i<n;i++) { printf(enter the size of %dst process:,i); scanf(%d,&p[i]); c[i]=i; } for(i=0;i<n;i++) { for(j=0;j<m;j++) { if a[i]<a[j]) { temp=a[i]; temp1=b[i]; a[i]=b[i]; b[i]=b[j]; a[j]=temp; b[j]=temp1; } if(p[i]<pj]) { temp=p[i]; temp2=c[i]; p[i]=p[j]; c[i]=c[j]; p[j]=temp; c[j]=temp2; } } } for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(p[i[<=a[i]) { printf(the process %d allocated to block %d\nc[j],b[i]); p[j]=1000; break; } } } for(j=0;j<m;j++) { { if(p[j]!=10000) { printf(the process %d is not allocated \n ,j); } } }

Output [09csebr3@linuxserver~]$cc bestfit.c [09csebr3@linuxserver~]$./a.out Enter no of blocks 3 enter 0st block size:100 enter 1st block size:200 enter 2st block size:300 3 enter the size of 0st process:300 enter the size of 1st process:200 enter the size of 2nd process:100 the process 2 allocated to block 0 the process 1 allocated to block 1 the process 0 allocated the block 2

Program for First Fit #include<stdio.h> int main() { int a[20],p[20],I,j,n,m; printf(enter the no of blocks \n); scanf(%d,&n); for(i=0;i<n;i++) { printf(enter the % dst block sizei); scanf(d,&a[i]); } printf(enter the no of process \n); scanf(%d,&m); for(i=0;i<n;i++) { printf(enter the size of %d st processi); scanf(%d,&p[i]); } for(i=0;i<n;i++) { for(j=0;j<m;j++) { if p[j]<=a[i]) { printf(the process %d allocated to %d\ni,a[i]); p[j]=10000; break; } }

} for(j=0;j<m;j++) { If(p[j]!=10000) { printf(the process %d is not allocated\n,j); } } }

Result: Thus C program was written to implement first fit and best fit allocation strategies.

9. Memory Management Scheme II


( Paging and Page replacement algorithm FIFO) Aim : To write a C program for implementing paging scheme and FIFO page replacement algorithm Paging 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. o Accesses data at offset in physical page frame.

First-In, First-Out (FIFO) First-in, first-out is as easy to implement as Random Replacement, and although its performance is equally unreliable or worse, claims , its behavior does follow a predictable pattern. Rather than choosing a victim page at random, the oldest page (or first-in) is the first to be removed. Conceptually compares FIFO to a limited size queue, with items being added to the queue at the tail. When the queue fills (all of the physical

memory has been allocated), the first page to enter is pushed out of head of the queue. Similar to Random Replacement, FIFO blatantly ignores trends, and although it produces less page faults, still does not take advantage of locality trends unless by coincidence as pages move along the queue .

Program for Segmentation #include<stdio.h> int main() { int segno[10],n,I; long int base[10],offset[10],limit[10],physical[10]; printf(enter the value \n); scanf(%d,&n); printf(segmentation table \n \n); printf($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n); printf(\n\nsegno\t\t base\t\t limit\n\n); for(i=0;i<n;i++) { scanf(%d %d %d ,&segno[i],&base[i],&limit[i]); } printf(enter the logical ddress \n); printf(\n segno\t\t offset\n\n); for(i=0;i<n;i++) { scanf(%d %d ,&segno[i],&offset[i]); } printf($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n); for(i=0;i<n;i++) { If(offset[i]<=limit[i]) { physical[i]=base[i]+limit[i]); printf(\n physical address of the segment); printf(%d,segno[i]); printf(%d,physical[i]); } else { printf(segno %d,segno[i]); printf(is invalid \n\n); } } } Output Enter the value 2 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

segno 1 4

base 2 5

limit 3 6

Enter the logical address Segno 1 4 offse 2 4

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Physical address of the segment S1 - 5 Physical address of the segment s4 - 11 Result: Thus C program was written to implement the segmentation
10 Implement any file allocation technique (Linked, Indexed or Contiguous)

Aim To write a C program for implementing Data Dictionary files Algorithm Step 1 : 2: 3. 4. 5. 6. 7. Program: #include<stdio.h> #include<string.h> FILE *fp; Char s1[50],s2[50],s3[50]; void append() { fp=fopen(words.dataw); printf(\n enter the word:); scanf(%s,s1); fflush(stdin); printf(enter the meaning:); gets(s3); Include the header files Make necessary declaration Read the word & meaning from User If(strcmp(s1,s2)==0||strcmp(s1,s3)==0) to print word found else word not found to print the word and the memory Display the result

fprintf(fp,%s\n%s\n,s1,s3); fclose(fp); } void search() { fp=fopen(words.data.,r); printf(\n Enter the words to find the meaning); scanf(%s,s1); fgets(s2,50,fp); fgets(s3,50,fp); while(!feof(fp)); { s2[strlen(s2)-1]=\0; s3[strlen(s3)-1]=\0; if(strcmp(s1,s2)==0||strcmp(s1,s3)==0) { printf(\n word found); printf(\n %s %s,s2,s3); break; } fgets(s2,50,fp); fgets(s3,50,fp); break; if(feop(fp)) printf(\n word not found!!!)l fclose(fp); } void main() { int choice=0; printf(\n \t\t Dictionary \n \n); do { printf( \n 1. Enter word \n 2. find the meaning); printf( \n 2. Enter the choice[1,2,3]:); scanf(%d,&choice); switch(choice) { case 1: append(); break case 2: search(); case 3: printf(exit from menu); break; default: printf(\n invalid input); } }while(choice!=3); }

Output: Dictionary 1.Enter word 2.find the memory 3.Exit Enter the choice[1/2/3]:1 Enter the word : hari Enter the meaning:name Menu: Enter the choice[1/2/3]:1 Enter the word : hari Word found Hari Menu: Enter the choice[1/2/3]:3 Exit from menu Result: Thus C program was written to implement Data Dictionary files was successfully executed and verified