From c70db7363d0070a4cdf3392b05561c3e3d4f2226 Mon Sep 17 00:00:00 2001 From: Ivaylo Ivanov Date: Sat, 15 Dec 2018 18:45:22 +0100 Subject: [PATCH] Rework children creation and add recursive calls --- cpair/cpair.c | 194 +++++++++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 74 deletions(-) diff --git a/cpair/cpair.c b/cpair/cpair.c index 3f9c7a8..ddeb244 100644 --- a/cpair/cpair.c +++ b/cpair/cpair.c @@ -60,7 +60,28 @@ 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) { +int main(int argc, char *argv[]) { + if (argc > 1) { + puts("The command takes no additional arguments."); + puts("Usage: cpair"); + exit(EXIT_FAILURE); + } + + fprintf(stderr, "Process id: %d\n", getpid()); + /** + * Create the pipe file descriptors and inititalize the pipes + * + * fd[0] - input side of pipe + * fd[1] - output side of pipe + * + **/ + int in_pipe_a[2], out_pipe_a[2], in_pipe_b[2], out_pipe_b[2]; + + if(pipe(in_pipe_a) < 0 || pipe(in_pipe_b) < 0 || pipe(out_pipe_a) < 0 || pipe(out_pipe_b) < 0) { + fprintf(stderr, "ERROR: Failed creating the pipes\n"); + exit(EXIT_FAILURE); + } + char input[__UINT8_MAX__] = ""; ///< An array to save the input to int point_num = 0; ///< Save the number of points node_t * head = NULL; @@ -101,101 +122,126 @@ int main(void) { exit(EXIT_SUCCESS); } - float x_mean = get_x_mean(head); - - node_t * first_part = malloc(sizeof(node_t)); - node_t * second_part = malloc(sizeof(node_t)); - - 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 + /// Create first child switch(child_a = fork()) { case -1: fprintf(stderr ,"ERROR: Couldn't fork child\n"); exit(EXIT_FAILURE); case 0: - if(read(pipe_a[0], child_a_part, sizeof(node_t)) < 0) { - fprintf(stderr, "ERROR: Failed reading from pipe\n"); + /// Child execution + fprintf(stderr, "Child 1 id: %d\n", getpid()); + close(out_pipe_a[0]); + close(in_pipe_a[1]); + close(STDIN_FILENO); + if(dup2(in_pipe_a[0], STDIN_FILENO) != STDIN_FILENO) { + fprintf(stderr, "ERROR: Failed duplicating STDIN"); 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; + execlp(argv[0], argv[0], NULL); + + fprintf(stderr, "ERROR: Failed to load program into child"); + exit(EXIT_FAILURE); default: - write(pipe_b[0], second_part, sizeof(node_t)); + /// Parent execution + /// Create second child 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"); + /// Child execution + fprintf(stderr, "Child 2 id: %d\n", getpid()); + close(out_pipe_b[0]); + close(in_pipe_b[1]); + close(STDIN_FILENO); + if(dup2(in_pipe_b[0], STDIN_FILENO) != STDIN_FILENO) { + fprintf(stderr, "ERROR: Failed duplicating STDIN"); 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; + execlp(argv[0], argv[0], NULL); + + fprintf(stderr, "ERROR: Failed to load program into child"); + exit(EXIT_FAILURE); default: + /// Parent execution + close(in_pipe_a[0]); + close(in_pipe_b[0]); + close(STDOUT_FILENO); + + float x_mean = get_x_mean(head); + + node_t * first_part = malloc(sizeof(node_t)); + int first_part_len = 1; + + node_t * second_part = malloc(sizeof(node_t)); + int second_part_len = 1; + + 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; + first_part_len ++; + } else { + second_part_buff -> points[0] = current -> points[0]; + second_part_buff -> next = malloc(sizeof(node_t)); + second_part_buff = second_part_buff -> next; + second_part_len ++; + } + current = current -> next; + } + + /** + * Send the correct lists to the children + **/ + + /// First half + if(dup2(in_pipe_a[1], STDIN_FILENO) != STDIN_FILENO) { + fprintf(stderr, "ERROR: Failed duplicating STDIN"); + exit(EXIT_FAILURE); + } + + if (write(in_pipe_a[1], first_part_buff, first_part_len*sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed writing to child\n"); + exit(EXIT_FAILURE); + } + close(STDOUT_FILENO); + ///Second half + if(dup2(in_pipe_b[1], STDIN_FILENO) != STDIN_FILENO) { + fprintf(stderr, "ERROR: Failed duplicating STDIN"); + exit(EXIT_FAILURE); + } + + if (write(in_pipe_b[1], first_part_buff, second_part_len*sizeof(node_t)) < 0) { + fprintf(stderr, "ERROR: Failed writing to child\n"); + exit(EXIT_FAILURE); + } + close(STDOUT_FILENO); + + /// Wait for the correct exit of the children + if(wait_for_termination(child_a) != EXIT_SUCCESS || wait_for_termination(child_b) != EXIT_SUCCESS) { + fprintf(stderr, "ERROR: Children didn't terminate successfully"); + exit(EXIT_FAILURE); + } + + /// Free the memory + free(head); + free(first_part); + free(first_part_buff); + free(second_part); + free(second_part_buff); + free(current); break; } - break; } - if(wait_for_termination(child_a) != EXIT_SUCCESS) - exit(EXIT_FAILURE); - - if(wait_for_termination(child_b) != EXIT_SUCCESS) - exit(EXIT_FAILURE); - - /// Free the memory - free(head); - free(first_part); - free(first_part_buff); - free(second_part); - free(second_part_buff); - free(current); - exit(EXIT_SUCCESS); }