0% found this document useful (0 votes)
9 views15 pages

Experiment 4

The document outlines an experiment to implement Mutual Exclusion using a centralized algorithm, simulating processes and a coordinator for file access. It includes code for both client and controller processes, detailing how requests for critical region access are managed and how to handle process crashes. The findings indicate successful implementation of centralized mutual exclusion, improved handling of crashed processes, but highlight the risk of system failure if the coordinator crashes.

Uploaded by

Harshit Jindal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views15 pages

Experiment 4

The document outlines an experiment to implement Mutual Exclusion using a centralized algorithm, simulating processes and a coordinator for file access. It includes code for both client and controller processes, detailing how requests for critical region access are managed and how to handle process crashes. The findings indicate successful implementation of centralized mutual exclusion, improved handling of crashed processes, but highlight the risk of system failure if the coordinator crashes.

Uploaded by

Harshit Jindal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

EXPERIMENT 4

Aim:
Program to implement Mutual Exclusion to access a shared file using centralized
algorithm. Simulate the process and coordinator as different processes. Also design how
to handle a scenario when a process having a resource crashes.
Number of processes: minimum 5.
Number of resources: minimum 2 files
Description:
In centralized algorithm one process is elected as the coordinator which may be the
machine. Whenever a process wants to enter a critical region, it sends a request message to
the coordinator stating which critical region it wants to enter and asking for permission. If
no other process is currently in that critical region, the coordinator sends back a reply
granting permission). When the reply arrives, the requesting process enters the critical
region. When another process asks for permission to enter the same critical region. Now
the coordinator knows that a different process is already in the critical region, so it cannot
grant permission. The coordinator just refrains from replying, thus blocking process 2,
which is waiting for a reply or it could send a reply ‘permission denied.’ When process 1
exits the critical region, it sends a message to the coordinator releasing its exclusive access.
The coordinator takes the first item off the queue of deferred requests and sends that
process a grant message. If the process was still blocked it unblocks and enters the critical
region. If an explicit message has already been sent denying permission, the process will
have to poll for incoming traffic or block later. When it sees the grant, it can enter the
critical region.

Code:
Client.c
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
typedef struct resources
{
int A; char B; int C; char D; char E;
}resources;

int main()
{
struct sockaddr_in sa; // Socket address data structure
resources R;
int n, sockfd; // read and source
char buff[1025], obuff[256]; // buffer to store the read stream
int snded, rec;

sockfd = socket(PF_INET, SOCK_STREAM, 0); // New socket created

// Checking for valid socket


if (sockfd < 0)
{
printf("Error in creation\n"); exit(0);
}

else
printf("Socket created\n");

// Clearing and assigning type and address to the socket


bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(8888);

// establishing and verifying the connection


if (connect(sockfd, (const struct sockaddr*)&sa, sizeof(sa)) < 0)
{
printf("Connection failed\n");
exit(0);
}
else
printf("Connection made\n");

while (1)
{
snded = write(sockfd, "PING", 5);
if (snded > -1)
printf("SENT PING\n");
rec = read(sockfd, obuff, 256);
obuff[rec] = '\0';

if (strcmp(obuff, "PONG") == 0)
{
usleep(750);
FILE *f;
FILE *f2;
f = fopen("shared_mem.txt", "r");
fread(&R, sizeof(R), 1, f);
fclose(f);
f2 = fopen("shared2.txt", "r");
fread(&R, sizeof(R), 1, f2);
fclose(f2);
printf("Read %d, %d, %d, %d, %d from server\n", R.A, R.B, R.C, R.D, R.E);
R.A += 1;
R.B += 1;
R.C += 1;
R.D += 1;
R.E += 1;
f = fopen("shared_mem.txt", "w");
fwrite(&R, sizeof(R), 1, f);
fclose(f);
f = fopen("shared2.txt", "w");
fwrite(&R, sizeof(R), 1, f2);
fclose(f2);
printf("Got access to CS\n");
snded = write(sockfd, "DONE", 4);
printf("Freeing Lock\n");
break;
}

}
close(sockfd); // Closing the socket
return 0;
}
Controller.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#define TRUE 1
#define FALSE 0

typedef struct resources


{
int A; int B; int C; int D; int E;
}resources;

int main()
{
resources R, temp;
R.A = 1;
R.B = 2;
R.C = 3;
R.D = 4;
R.E = 5;
FILE *fle;
FILE *fle2;
fle = fopen("shared_mem.txt", "w");
fle2 = fopen("shared2.txt", "w");
fwrite(&R, sizeof(R), 1, fle);
fwrite(&R, sizeof(R), 1, fle2);
fclose(fle);
fclose(fle2);
struct sockaddr_in sa; // Socket address data structure
int opt = TRUE, addrlen;
int sockfd, clients[50];
char buff[256]; // Buffer to hold the out-going stream
int rec, i, sd, activity, new_sock, sended;
int max_sd;
int flag = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0); // New socket created
// Checking for valid socket
memset(clients, 0, sizeof(clients));

fd_set readfds;
if (sockfd < 0)
{
printf("Error in creating socket\n");
exit(0);
}
else
{
printf("Socket Created\n");
}

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0)


{
printf("error\n");
}
// Clearing and assigning type and address to the socket
printf("Socket created\n");
bzero(&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(8888);
sa.sin_addr.s_addr = htonl(INADDR_ANY);

// binding and verifying the socket to address


if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
{
printf("Bind Error\n");
}

else
printf("Binded\n");

// starts the server with a max client queue size set as 10


listen(sockfd, 10);
addrlen = sizeof(sa);
// server run
while (TRUE)
{
// Clearing socket set
FD_ZERO(&readfds);

FD_SET(sockfd, &readfds);
max_sd = sockfd;

for (i = 0; i < 50; i++)


{
sd = clients[i];
if (sd > 0)
FD_SET(sd, &readfds);

if (sd > max_sd)


max_sd = sd;
}

activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);


if (activity < 0)
printf("Select error\n");

if (FD_ISSET(sockfd, &readfds))
{
if ((new_sock = accept(sockfd, (struct sockaddr *)NULL, NULL)) < 0)
perror("accept");

else
{
printf("New connection, sock fd %d\n", new_sock);
}

sended = send(new_sock, buff, strlen(buff), 0);

if (sended < 0)
perror("Send");

for (i = 0; i < 50; i++)


{
if (clients[i] == 0)
{
clients[i] = new_sock;
break;
}
}

for (i = 0; i < 50; i++)


{
sd = clients[i];

if (FD_ISSET(sd, &readfds))
{
FILE *fle;
fle = fopen("shared_mem.txt", "r");
fread(&temp, sizeof(temp), 1, fle);
fclose(fle);

FILE *fle2;
fle2 = fopen("shared2.txt", "r");
fread(&temp, sizeof(temp), 1, fle2);
fclose(fle2);
rec = read(sd, buff, 256);

if (rec == 0)
{
getpeername(sd, (struct sockaddr *)&sa, (socklen_t *)&sa);
printf("%d has disconnected unexpectedly with ip %s and port %d\n", sd,
inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
printf("recovering data\n");
FILE *fle;
fle = fopen("shared_mem.txt", "w+");
fwrite(&temp, sizeof(temp), 1, fle);
fclose(fle);

FILE *fle2;
fle2 = fopen("shared2.txt", "w+");
fwrite(&temp, sizeof(temp), 1, fle2);
fclose(fle2);

close(sd);
clients[i] = 0;
}

else
{
buff[rec] = '\0';
printf("recieved %s from %d\n", buff, sd);

if (strcmp(buff, "PING") == 0 && flag == 1)


{
printf("Read buffer = %s, from %d and send NACK\n", buff, sd);
sended = write(sd, "NACK", 4);
}

else if (strcmp(buff, "PING") == 0 && flag == 0)


{
printf("Read Buffer = %s, from %d\n", buff, sd);
flag = 1;
sended = write(sd, "PONG", 4);
}

else if (strcmp(buff, "DONE") == 0)


{
printf("Lock freed\n");
flag = 0;
FILE *fle;
fle = fopen("shared_mem.txt", "r");
fread(&temp, sizeof(temp), 1, fle);

FILE *fle2;
fle2 = fopen("shared2.txt", "r");
fread(&temp, sizeof(temp), 1, fle2);
printf("Read %d, %d, %d, %d, %d from %d\n", temp.A, temp.B, temp.C,
temp.D, temp.E, sd);
fclose(fle);
fclose(fle2);
clients[i] = 0;
close(sd);
break;
}
}
}
}
}

close(sockfd); // close the socket


return 0;
}
Result/Output:
Discussion:

Centralised Algorithm is fair and requests are granted in the order in which they are received.
There is no starvation and is easy to implement and it has the disadvantage that the coordinator is
a single point of failure, the entire system may go down if it crashes.
Findings and Learnings:
1. We successfully implemented Centralized Mutual Exclusion.

2. The system is better at handling crashed processes

3. The Entire system fails for Crashed Clients.

You might also like