Question
Use of lockf C library function for process synchronization. The shared resource responsible for race condition in the twoupdate program is an external file, and
Use of lockf C library function for process synchronization.
The shared resource responsible for race condition in the twoupdate program is an external file, and is not an arbitrary in-memory data structure. Hence, it is possible to use file and record locking mechanisms available in UNIX to ensure mutual exclusion of the respective critical sections of the two processes, and thereby eliminate the race condition. The required system call in UNIX is fcntl. It is simpler to use a C library function called lockf built on top of fcntl. Spool out the man page for this library function and study it. The function prototype is as follows: int lockf(int fd, int action, long size);
Two valid actions, defined as symbolic constants in , of interest to us are: F_LOCK (Lock a section of a file for exclusive use, if it is available; if the section is already locked, the process blocks until the lock can be established) and F_ULOCK (Unlock a previously locked section of a file).
The third parameter size indicates the number of contiguous bytes to lock or unlock from the current position in the file. A value of zero for size indicates the entire section from the present position to the end of the file. Thus, by using a separate lseek system call to position at the beginning of the file before invoking lockf, the entire file can be locked or unlocked.
Suitably modify process0.c and process1.c to use the lockf function. Specifically, modify the function prototypes and invocations for both lockfile and unlockfile to allow passing the file descriptor as a parameter. Then modify the lockfile and unlockfile functions. Each requires exactly two lines of code.
Create a script output with a listing of all modified source files -- twoupdate.c, process0.c and process1.c. Show the output of four or five runs of twoupdate for small values of count, say below 30, and three fairly large values.
BELOW IS THE CODE for twoupdate.c, process0.c (process1.c is just a copy), and sharevar.h
//twoupdate.c
#include
#include
#include
#include
#include
#include "sharevar.h"
/*Variables needed for shared memory segment*/
/*Set up as external variables for programming ease*/
int shmid;
syncvars *shmptr;
int main (int argc, char *argv[])
{
FILE *fp; int initial, final; int status;
/*Check for command line arguments*/
if (argc != 3)
{
printf("usage: %s filename count ", argv[0]);
return -1;
}
/*Determine initial value in file before update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &initial);
fclose(fp);
/*Create a shared memory segment for the given key*/
/*provided one does not exist already*/
shmid = shmget(SHMKEY, sizeof(syncvars), PERMS | IPC_CREAT);
/*Attach the shared memory segment to this process*/
shmptr = (syncvars *) shmat(shmid, (void *) NULL, 0);
/*Initialize the shared memory for Peterson's Algorithm*/
shmptr->flag[0] = FALSE;
shmptr->flag[1] = FALSE;
shmptr->turn = 0;
/*Launch the two processes*/
if (fork() == 0) {
execlp("process0", "process0", argv[1], argv[2], (char *) NULL);
}
if (fork() == 0) {
execlp("process1", "process1", argv[1], argv[2], (char *) NULL);
}
/*Wait for the two processes to terminate*/
wait(&status); wait(&status);
/*Detach the shared memory segment*/
shmdt((void *) shmptr);
/*Remove the shared memory segment*/
shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL);
/*Determine final value in file after update*/
fp = fopen(argv[1], "r");
fscanf(fp, "%d", &final);
fclose(fp);
/*Print value in file before and after two-process update*/
printf(" ****Initial value in file %d ", initial);
printf("****Final value in file %d ", final);
return 0;
}
//process1.c
#include
#include
#include
#include
#include
#include
#include
void waste_time(void);
#define MAXSIZE 80
int main(int argc, char *argv[])
{
/*Uses UNIX input/output system calls for file access */
/*for no reason other than educational value*/
/*function prototype for file access*/
void fileaccess (int fd, int count);
int fd, count;
/*Check for command line arguments*/
if (argc != 3) {
printf("usage: process0 filename count ");
return -1;
}
count = atoi(argv[2]);
/*Open file and update*/
fd = open(argv[1], O_RDWR, 0);
fileaccess(fd, count);
return 0;
}
/*Access the file with the given fd and increment*/
/*the only integer value in that file count times*/
void fileaccess(int fd, int count)
{
/*function prototypes for locking and unlocking file*/
void lockfile (void);
void unlockfile (void);
int i, k, value; pid_t pid;
char buff[MAXSIZE];
/*Initialize the seed for random number generator*/
srand(time(NULL));
pid = getpid();
for (i = 0; i < count; i++)
{
lockfile(); /*lock the file*/
/*Read value from file*/
lseek(fd, 0L, 0);
k = read(fd, buff, MAXSIZE); buff[k] = '\0';
sscanf(buff, "%d ", &value);
/*Increment value*/
value++;
/*Slow down*/
waste_time();
/*Write back into file*/
sprintf(buff, "%10d ", value);
lseek(fd, 0L, 0);
k = strlen(buff); write(fd, buff, k);
printf("pid = %d, new value = %d ", pid, value);
unlockfile(); /*unlock the file*/
}
}
void waste_time (void)
{
/*Slow down; waste time in loop*/
int randNum = rand() % 100000; int x;
for (x = 0; x < randNum; x++) {
}
}
void lockfile(void)
{
}
void unlockfile(void)
{
}
//sharevar.h
#define PERMS 0666 /*Access rights*/ #define SHMKEY ((key_t) 800592098) /*Use your Banner ID#*/ #define FALSE 0 #define TRUE 1 typedef struct { int flag[2]; int turn; } syncvars;
Thanks so much for your help!!!
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started