From 446ac678db1e7ed9d0e998cad9bb89ca6f66e1e9 Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Fri, 14 Dec 2018 19:51:54 +0100 Subject: [PATCH] Add process fork (albeit non-functioning) --- cpair/cpair.c | 183 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 158 insertions(+), 25 deletions(-) diff --git a/cpair/cpair.c b/cpair/cpair.c index 1e8457b..3f9c7a8 100644 --- a/cpair/cpair.c +++ b/cpair/cpair.c @@ -26,7 +26,9 @@ * The program does the following: * - No output if the array has one point * - The points if the array has 2 points - * - Otherwise, the array is split in 2 parts based on the mean of X and sent to 2 different paralell child processes. The parent watches for the return code of the children and terminates with an error if any of the children exit with anything other than success. + * - Otherwise, the array is split in 2 parts based on the mean of X and sent to 2 different paralell child processes. + * The parent watches for the return code of the children and terminates with an error if any of the children exit + * with anything other than success. * * Algorithm description when there are more than 2 points: * - P1 and P2 are the closest pairs for the first and the second part respectively. @@ -44,18 +46,24 @@ /// Node struct for linked list typedef struct node { + /** + * points[0] - contains the X coordinate of the point + * points[1] - contains the Y coordinate of the point + * + **/ float points[2]; struct node * next; } node_t; float get_x_mean(node_t * head); float get_distance(float x1, float x2, float y1, float y2); +node_t * find_shortest_distance(node_t * list); +int wait_for_termination(pid_t child); int main(void) { char input[__UINT8_MAX__] = ""; ///< An array to save the input to int point_num = 0; ///< Save the number of points node_t * head = NULL; - pid_t child_a, child_b; head = malloc(sizeof(node_t)); @@ -74,13 +82,13 @@ int main(void) { current = current -> next; point_num++; ///< Increase the list length } else { - puts("ERROR: Ill-formed line found"); + fprintf(stderr, "ERROR: Ill-formed line found\n"); exit(EXIT_FAILURE); } } if(feof(stdin) == 0) { - puts("ERROR: An error interrupted the read"); + fprintf(stderr, "ERROR: An error interrupted the read\n"); exit(EXIT_FAILURE); } @@ -95,35 +103,98 @@ int main(void) { float x_mean = get_x_mean(head); - child_a = fork(); - child_b = fork(); + node_t * first_part = malloc(sizeof(node_t)); + node_t * second_part = malloc(sizeof(node_t)); - switch(child_a){ + node_t * first_part_buff = first_part; + node_t * second_part_buff = second_part; + + /// Separate the lists based on the mean + current = head; + while(current != NULL) { + if(current -> points[0] <= x_mean) { + first_part_buff -> points[0] = current -> points[0]; + first_part_buff -> next = malloc(sizeof(node_t)); + first_part_buff = first_part_buff -> next; + } else { + second_part_buff -> points[0] = current -> points[0]; + second_part_buff -> next = malloc(sizeof(node_t)); + second_part_buff = second_part_buff -> next; + } + current = current -> next; + } + + /** + * Create the pipe file descriptors and inititalize the pipes + * + * fd[0] - input side of pipe + * fd[1] - output side of pipe + * + **/ + int pipe_a[2], pipe_b[2]; + + if(pipe(pipe_a) < 0 || pipe(pipe_b) < 0) { + fprintf(stderr, "ERROR: Failed creating the pipe\n"); + exit(EXIT_FAILURE); + } + + pid_t child_a, child_b; ///< Create variables for the child processes + node_t * child_a_part = NULL; + node_t * child_b_part = NULL; + + write(pipe_a[0], first_part, sizeof(node_t)); ///< Send the first part of the array to the child + + switch(child_a = fork()) { case -1: - puts("ERROR: Coudn't fork child"); + fprintf(stderr ,"ERROR: Couldn't fork child\n"); exit(EXIT_FAILURE); case 0: - puts("Child"); + if(read(pipe_a[0], child_a_part, sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed reading from pipe\n"); + exit(EXIT_FAILURE); + } + if(write(pipe_a[1], find_shortest_distance(child_a_part), sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed writing to pipe\n"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); break; default: + write(pipe_b[0], second_part, sizeof(node_t)); + switch(child_b = fork()) { + case -1: + fprintf(stderr, "ERROR: Couldn't fork child\n"); + exit(EXIT_FAILURE); + case 0: + if(read(pipe_b[0], child_b_part, sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed reading from pipe\n"); + exit(EXIT_FAILURE); + } + if(write(pipe_b[1], find_shortest_distance(child_b_part), sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed writing to pipe\n"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); + break; + default: + break; + } break; } - switch(child_b){ - case -1: - puts("ERROR: Coudn't fork child"); - exit(EXIT_FAILURE); - case 0: - puts("Child"); - break; - default: - break; - } + if(wait_for_termination(child_a) != EXIT_SUCCESS) + exit(EXIT_FAILURE); - int status; + if(wait_for_termination(child_b) != EXIT_SUCCESS) + exit(EXIT_FAILURE); - waitpid(child_a, &status, 0); - waitpid(child_b, &status, 0); + /// Free the memory + free(head); + free(first_part); + free(first_part_buff); + free(second_part); + free(second_part_buff); + free(current); exit(EXIT_SUCCESS); } @@ -138,14 +209,15 @@ int main(void) { float get_x_mean(node_t * head) { node_t * current = head; float x_sum = 0; - int i = 0; - while(current -> next != NULL) { + int i = 1; + + while(current != NULL) { x_sum += current -> points[0]; current = current -> next; i++; } - return x_sum/i; + return x_sum/(i - 2); ///< TODO: Fix the bug with the 2 more iterations } /** @@ -160,3 +232,64 @@ float get_x_mean(node_t * head) { float get_distance(float x1, float x2, float y1, float y2) { return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2)); } + +/** + * @brief Function to find the shortest distance in a list + * @details The function gets a list of points and finds the pair + * with the shortest distance between them. + * @param list - the list with points + * @return res - a list containing the coordinates of the two closest points + * + **/ +node_t * find_shortest_distance(node_t * list) { + node_t * current = list; + node_t * next = list; + + /// Setup the result list + node_t * res = malloc(sizeof(node_t)); + res -> next = malloc(sizeof(node_t)); + + int current_shortest = 0; + int new_shortest = 0; + + while(current != NULL) { + next = current -> next; + if(next != NULL) { + new_shortest = get_distance(current -> points[0], next -> points[0], current -> points[1], next -> points[1]); + + if(new_shortest < current_shortest) { + current_shortest = new_shortest; + + /// Save the pairs + res -> points[0] = current -> points[0]; + res -> points[1] = current -> points[1]; + res -> next -> points[0] = next -> points[0]; + res -> next -> points[1] = next -> points[1]; + } + + current = next; + } else + break; + } + + return res; +} + +/** + * @briefs Function that waits for a child to close + * @details The function waits for a child to close. + * If it closes successfully, it returns the exit status only. + * Otherwise, it prints an error message and then returns the exit status. + * @param child - the pid of the child process + * @return the exist status of the child process + * + **/ +int wait_for_termination(pid_t child) { + int exit_stat = 0; + + if(waitpid(child, &exit_stat, 0) < 0) { + fprintf(stderr, "ERROR: Child did not exit successfully\n"); + } + + return WEXITSTATUS(exit_stat); +}