#include #include #include #include #include #include #include #include #include #include #define READ 0 #define WRITE 1 #define MAX_PROCESSES 5 #define MAX_FILENAME_LENGTH 20 int main(int argc, char *argv[]) { int num_processes; pid_t process_ids[MAX_PROCESSES]; int fd[MAX_PROCESSES][2]; int i; int child_num; int rand_number; char pipe_message_input[LINE_MAX], pipe_message_output[LINE_MAX]; char input_file_name[MAX_FILENAME_LENGTH], output_file_name[MAX_FILENAME_LENGTH]; FILE *input, *output; int is_child = 0; if (argc < 3 ) { printf("Please enter correct number of slave processes (2-5) and the input file name.\n"); exit(1); } num_processes = atoi(argv[1]); if (num_processes < 2 || num_processes > 5) { printf("Please input a number between 2 and 5\n"); exit(1); } printf("Number of child processes: %d\n", num_processes); srand(time(NULL)); //create n pipes for (i = 0; i < num_processes; i++) { if (pipe(fd[i]) == -1) { //pipe failed printf("Creating pipe #%d failed!\n", i); exit(1); } } //fork processes and setup is_child == 1 for children for (i = 0; i < num_processes; i++) { //making sure slave processes are not forking if (!is_child) { process_ids[i] = fork(); if (process_ids[i] < 0) { printf("fork() #%d failed!\n", i); exit(1); } if (process_ids[i] == 0) { //this is the child, let's make him aware of it is_child = 1; child_num = i; } } } //closing pipe ends if (is_child) { //close write end for children close(fd[child_num][WRITE]); } else { //close read end for all pipes in parent for (i = 0; i < num_processes; i++) { close(fd[i][READ]); } } //input file name and open file if (!is_child) { memcpy(input_file_name, argv[2], strlen(argv[2]) + 1); input = fopen(input_file_name, "r"); if (input == NULL) { printf("Error opening file in master process.\n"); exit(1); } printf("Master: opened file %s.\n", input_file_name); } //output file name for each child if (is_child) { sprintf(output_file_name, "%d.txt", child_num + 1); output = fopen(output_file_name, "w"); if (output == NULL) { printf("Error opening file in slave process %d.\n", child_num + 1); exit(1); } printf("Child: opened file %d.txt\n", child_num+1); } if (!is_child) { printf("Master: getting ready to read from file!\n"); //read from file and write into pipes while (fgets(pipe_message_input, LINE_MAX, input) != NULL) { rand_number = (rand() % num_processes); write(fd[rand_number][WRITE], pipe_message_input, strlen(pipe_message_input)+1); printf("\t Main: sent message to pipe %d -> %s", rand_number+1, pipe_message_input); //parent unhangs child after sending him the message printf("\t Main: continuing child %d\n", rand_number+1); kill(process_ids[rand_number], SIGCONT); waitpid(process_ids[rand_number], NULL, WUNTRACED); } fclose(input); printf("Master: closing pipes!\n"); for (i = 0; i < num_processes; i++) { close(fd[i][WRITE]); close(fd[i][READ]); } for (i = 0; i < num_processes; i++) { kill(process_ids[i], SIGCONT); } } if (is_child) { while (1) { //read until WRITE side of pipe is closed printf("Child %d: holding...\n", child_num+1); //child stops itself kill(getpid(), SIGSTOP); printf("Child %d continued.\n", child_num+1); printf("Child %d: Reading from pipe.\n", child_num+1); if (read(fd[child_num][READ], pipe_message_output, LINE_MAX) == 0) { printf("Child %d: pipe closed. exiting.\n"); fclose(output); exit(1); break; } else { printf("Child #%d recieved message %s\n", child_num+1, pipe_message_output); fputs(pipe_message_output, output); } } fclose(output); } wait(NULL); return 0; }