/* Solution for 'Supervisor & cooperating workers' pattern #6 * The program creates 4 anonymous pipes (1 for reading, 1 for reading, for each process. You have 2 processes => 2 x 2 = 4 anoynmous pipes) */ #include #include #include #include #include #define MAX_SIZE 1024 void handle_error(const char *msg) { perror(msg); exit(EXIT_FAILURE); } int count_occurrences(char ch, const char *str) { int occurrences = 0; for (int i = 0; str[i]; ++i) if (ch == str[i]) occurrences++; return occurrences; } int main() { int pipe1_child1[2], pipe2_child1[2], pipe1_child2[2], pipe2_child2[2]; char ch; pid_t child1, child2; if (pipe(pipe1_child1) == -1) handle_error("[Error] When creating the first anonymous pipe: "); if (pipe(pipe2_child1) == -1) handle_error("[Error] When creating the first anonymous pipe: "); if ((child1 = fork()) == -1) handle_error("[Error] When forking the first child: "); if (child1 == 0) { // Executed by the first child char buffer[MAX_SIZE], i, ch; int index = 0, occurrences; close(pipe1_child1[1]); // Close the writing end of the reading pipe close(pipe2_child1[0]); // Close the reading end of the writing pipe read(pipe1_child1[0], &ch, 1); while (read(pipe1_child1[0], &i, 1) != 0) if(index < MAX_SIZE) buffer[index++] = i; buffer[ (index == MAX_SIZE) ? MAX_SIZE - 1 : index ] = '\0'; printf("[%d] Read: %s\n", getpid(), buffer); occurrences = count_occurrences(ch, buffer); write(pipe2_child1[1], &occurrences, sizeof(int)); close(pipe2_child1[1]); // Close the writing end close(pipe1_child1[0]); // Close the reading end }else{ // Executed by the parent if (pipe(pipe1_child2) == -1) handle_error("[Error] When creating the second anonymous pipe: "); if (pipe(pipe2_child2) == -1) handle_error("[Error] When creating the second anonymous pipe: "); if ((child2 = fork()) == -1) handle_error("[Error] When forking the first child: "); if (child2 == 0) { // Executed by the second child char buffer[MAX_SIZE], i, ch; int index = 0, occurrences; close(pipe1_child2[1]); // Close the writing end of the reading pipe close(pipe2_child2[0]); // Close the reading end of the writing pipe read(pipe1_child2[0], &ch, 1); while (read(pipe1_child2[0], &i, 1) != 0) if(index < MAX_SIZE) buffer[index++] = i; buffer[ (index == MAX_SIZE) ? MAX_SIZE - 1 : index ] = '\0'; printf("[%d] Read: %s\n", getpid(), buffer); occurrences = count_occurrences(ch, buffer); write(pipe2_child2[1], &occurrences, sizeof(int)); close(pipe2_child2[1]); // Close the writing end close(pipe1_child2[0]); // Close the reading end }else{ // Executed by the parent close(pipe1_child1[0]); // Close the reading end (int the parent) of the child1's reading pipe close(pipe2_child1[1]); // Close the writing end (in the parent) of the child1's writing pipe close(pipe1_child2[0]); // Close the reading end (int the parent) of the child2's reading pipe close(pipe2_child2[1]); // Close the writing end (in the parent) of the child2's writing pipe int counter = 1, occurrences_child1, occurrences_child2; printf("Enter a sequence of characters, ended by CTRL + D.\n"); ch = getchar(); // Reading the fist character and sending it to both childs write(pipe1_child1[1], &ch, 1); write(pipe1_child2[1], &ch, 1); while ((ch = getchar()) != EOF) { if (counter % 2 == 0) // characters from even positions will be sent to the first child write(pipe1_child1[1], &ch, 1); else // characters from even positions will be sent to the first child write(pipe1_child2[1], &ch, 1); counter++; } // Closing the write end on the parent, so that the childs can receive EOF close(pipe1_child1[1]); close(pipe1_child2[1]); read(pipe2_child1[0], &occurrences_child1, sizeof(int)); read(pipe2_child2[0], &occurrences_child2, sizeof(int)); printf("[PARENT] Received from the first child, with PID = %d: %d\n", child1, occurrences_child1); printf("[PARENT] Received from the second child, with PID = %d: %d\n", child2, occurrences_child2); printf("[PARENT] The sum of both occurrences is: %d\n", occurrences_child1 + occurrences_child2); // Close the childs' reading ends on the parent close(pipe2_child1[0]); close(pipe2_child2[0]); } } return 0; }