Code:
fprintf(share->out, "Lift-%d Operation\r\n" "Previous position: Floor %d\r\n"
"Request: Floor %d to Floor %d\r\n"
"Detail operations:\r\n"
" Go from Floor %d to Floor %d\r\n"
" Go from Floor %d to Floor %d\r\n"
" #movement for this request: %d\r\n"
" #request: %d\r\n"
" Total #movement: %d\r\n"
"Current Position: Floor %d\r\n"
"\r\n"
"----------------------------\r\n", id, write1->p, write1->rf, write1->rt, write1->p, write1->rf, write1->rf, write1->rt
, write1->m, write1->total_r[id], write1->total_m[id], write1->c);
here is what I've done so far:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "list.h"
#include <errno.h>
sem_t *full, *empty; //Semaphore mutex intializer
static int *counter; //number of requests made
static int size; //buffer size (must only change once at beginning)
//Doesn't need to be in shared memory because it will be the same for all processes.
static int sec; //Time in seconds, needed for lift to execute operation
static int *length; //Number of values in buffer
//Will be shared across processes using mmap.
static int *in; //index of reader
static int *out_i; //index of writer
static buffer_t *A;
static write_t *write1; //Used for printing the information from buffer.
void *lift(void* vargp) //Consumer
{
share_t* share = vargp;
while (true)
{
while (*length <= 0)
{
sem_wait(empty);
printf("Waiting for request\n");
}
sleep(sec);
printf("lifting information\n");
printf("%d %d \n", A[*out_i].from, A[*out_i].to);
int id = share->id;
//gather information to print
if (write1->p == 0) //only for when system begins (Assign Previous to the first record `from` value)
{
write1->p = A[*out_i].from;
}
write1->rf = A[*out_i].from;
write1->rt = A[*out_i].to;
write1->m = (write1->p - A[*out_i].from) + (A[*out_i].to - A[*out_i].from);
write1->c = A[*out_i].to;
//Now write the information
write1->total_r[id] = write1->total_r[id] + 1;
write1->total_m[id] = write1->total_m[id] + write1->m;
fprintf(share->out, "Lift-%d Operation\n"
"Previous position: Floor %d\n"
"Request: Floor %d to Floor %d\n"
"Detail operations:\n"
" Go from Floor %d to Floor %d\n"
" Go from Floor %d to Floor %d\n"
" #movement for this request: %d\n"
" #request: %d\n"
" Total #movement: %d\n"
"Current Position: Floor %d\n"
"\n"
"----------------------------\n", id, write1->p, write1->rf, write1->rt, write1->p, write1->rf, write1->rf, write1->rt
, write1->m, write1->total_r[id], write1->total_m[id], write1->c);
write1->p = write1->c; //for next statement
*length = *length - 1;
*out_i = (*out_i + 1) % size;
if (*length == 0)
{
printf("Signalling lift\n");
sem_post(full);
}
}
return NULL;
}
void *request_t(void *vargp) //producer
{
share_t* share = vargp;
while(1)
{
while (*length >= size)
{
sem_wait(full);
printf("Waiting for lift\n");
}
printf("Requesting information\n");
//read the input line by line and into the buffer
if (fscanf(share->in, "%d %d\n", &A[*in].from, &A[*in].to) == EOF)
{
break;//stop the loop when file is empty
}
printf("%d %d \n", A[*in].from, A[*in].to);
//If requests go out of bounds, they will be automatically registered as either
//maximum level or minimum level
if (A[*in].to > 20)
{
A[*in].to = 20;
}
else if (A[*in].to < 1)
{
A[*in].to = 1;
}
else if (A[*in].from > 20)
{
A[*in].from = 20;
}
else if (A[*in].from < 1)
{
A[*in].from = 1;
}
//Print buffer information to sim_output
fprintf(share->out, "New Lift Request from Floor %d to Floor %d \n"
"Request No %d \n"
"----------------------------\n", A[*in].from, A[*in].to, * counter = *counter + 1);
*length = *length + 1;
*in = (*in + 1) % size;
if (*length == 1)
{
printf("Signalling request\n");
sem_post(empty);
}
}
return NULL;
}
int main(int argc, char *argv[]) // to avoid segmentation fault
{
//establish values for use (convert argv to int values)
if (argc != 3) //Must have both m and t
{
perror("Insufficient arguements\n");
exit(EXIT_FAILURE);
}
long arg = strtol(argv[1], NULL, 10);
size = arg;
if (size <= 1)
{
perror("buffer size too small\n");
exit(0);
}
//allow variables to be shared among processes without duplicates being made
in = mmap(NULL, sizeof * in, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
out_i = mmap(NULL, sizeof * out_i, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
length = mmap(NULL, sizeof * length, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
counter = mmap(NULL, sizeof * counter, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
write1 = mmap(NULL, sizeof * write1, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*length = 0, *in = 0, *out_i = 0, *counter = 1;
//initialize Buffer as empty array and as shared memory.
A = mmap(NULL, sizeof * A, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
for (int i = 0; i < size + 1; i++) //Had to be changed from calloc to for loop due to errors in mmap()
{ //Caused lift to print 0 instead of read values
A[i].from = 0;
A[i].to = 0;
}
arg = strtol(argv[2], NULL, 10);
sec = arg; //time required by each lift to serve a request
if (sec <= 0)
{
perror("insufficient time\n");
exit(0);
}
//open files for reading and writing
FILE *out = fopen("sim_output.txt", "w");
FILE *in_t = fopen("sim_input.txt", "r");
if (in == NULL && out == NULL) //Check if files exists before we can use them
{
perror("Input file empty\n");
exit(0);
}
//Create a shared memory for the file streams
//it is important the algorithm keeps a consistent stream of values
share_t *share[4];
for (int i = 0; i < 4; i++)//Load files into share for transporting.
{
share[i] = mmap(NULL, sizeof * share, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
share[i]->in = in_t;
share[i]->out = out;
share[i]->id = i;
}
//Create processes
printf("Creating processes\n");
const int shared_mem_id = shmget(IPC_PRIVATE, 2 * sizeof(sem_t), IPC_CREAT | 0660);//must allocate space for two semaphores
sem_t *two_sems = shmat(shared_mem_id, NULL, 0);
if (errno) perror("E2");
full = &two_sems[0];
empty = &two_sems[1];
sem_init(full, 1, 1);//stops here
sem_init(empty, 1, 1);
pid_t Lift_R = fork();
if (Lift_R == 0) { // Lift-R Child Proccess
request_t(share[0]);
shmdt(full);
exit(0);
}
else if (Lift_R == -1)//Error detection
{
perror("could not wait for child\n");
exit(0);
}
pid_t lift_1 = fork();
if (lift_1 == 0) { // lift-1 Child Proccess
lift(share[1]);
shmdt(empty);
exit(0);
}
else if (lift_1 == -1)
{
perror("could not wait for child\n");
exit(0);
}
pid_t lift_2 = fork();
if (lift_2 == 0) { // lift-2 Child Proccess
printf("B\n");
lift(share[2]);
shmdt(empty);
exit(0);
}
else if (lift_2 == -1)
{
perror("could not wait for child\n");
exit(0);
}
pid_t lift_3 = fork();
if (lift_3 == 0) { // lift-3 Child Proccess
printf("C\n");
lift(share[3]);
shmdt(empty);
exit(0);
}
else if (lift_3 == -1)
{
perror("could not wait for child\n");
exit(0);
}
Lift_R = wait(NULL);
int sum_r = write1->total_r[1] + write1->total_r[2] + write1->total_r[3],
sum_t = write1->total_m[1] + write1->total_m[2] + write1->total_m[3]; //Create total sums of requests and movement
fprintf(out, "\r\n"
"Total number of requests %d \r\n"
"Total number of movememts %d \r\n", sum_r, sum_t); //Print at the very last line after all requests were made
fclose(in_t);
fclose(out);
printf("finished\n");
exit(1);
lift_1 = wait(NULL);
printf("1\n");
lift_2 = wait(NULL);
printf("2\n");
lift_3 = wait(NULL);
printf("3\n");
}