#include #include #include #include #include #include #include #define MAX(a, b) ((a) > (b) ? (a) : (b)) bool is_prime(uint64_t number) { if (number % 2 == 0) return false; for (uint64_t i = 3; i <= (uint64_t)sqrt(number); i+=2) { if (number % i == 0) return false; } return true; } void prime_dividers(uint64_t last_numer, uint64_t *primes, uint32_t *primes_size) { uint32_t p_size = 0; primes[p_size++] = 2; for (uint64_t i = 3; i <= (uint64_t)(sqrt(last_numer)); i+=2) { bool prime_status = is_prime(i); if (prime_status) { primes[p_size++] = i; } } *primes_size = p_size; } int main(int argc, char **argv) { if (argc != 4) { printf("%s takes only one or two arguments\n", argv[0]); return 1; } uint64_t first_number = 3; uint64_t last_number = 100; int subproccess_count = 2; if (argc == 4) { subproccess_count = atoll(argv[1]); first_number = atoll(argv[2]); last_number = atoll(argv[3]); } int pipes[subproccess_count][2]; pid_t pids[subproccess_count]; uint64_t first_last[2]; first_last[0] = first_number; uint64_t results[subproccess_count]; uint64_t pull_size = (last_number - first_number) / subproccess_count; printf("last_number: %lu, pull_size: %lu\n", last_number, pull_size); // Создаем каналы for (int i = 0; i < subproccess_count; ++i) { if (pipe(pipes[i]) == -1) { perror("pipe"); exit(EXIT_FAILURE); } } // Создаем дочерние процессы for (int sp = 0; sp < subproccess_count; ++sp) { pids[sp] = fork(); if (pids[sp] == -1) { perror("fork"); exit(EXIT_FAILURE); } if (pids[sp] == 0) { close(pipes[sp][1]); uint64_t received_first_last[2]; read(pipes[sp][0], &received_first_last, sizeof(received_first_last)); close(pipes[sp][0]); // Закрываем читающий конец received_first_last[0] = MAX(3, received_first_last[0]); if ((received_first_last[0] & 1) == 0) ++received_first_last[0]; // printf("Proccess #%d: %lu %lu\n", sp, received_first_last[0], received_first_last[1]); uint32_t prime_counter = 0; uint32_t bro_counter = 0; uint64_t prev_prime = 2; uint64_t prime_divs[(uint32_t)sqrt(received_first_last[1])]; uint32_t primes_size = 0; prime_dividers(received_first_last[1], prime_divs, &primes_size); FILE *fptr; char filename[50]; snprintf(filename, sizeof(filename), "%lu.primes", received_first_last[0]); fptr = fopen(filename, "w"); if (fptr == NULL) { printf("Error opening file!\n"); return 1; } for (uint64_t i = received_first_last[0]; i < received_first_last[1]; i+=2) { bool prime_status = true; for (uint32_t j = 0; j < primes_size; ++j) { if (prime_divs[j] * prime_divs[j] > i) break; if (i % prime_divs[j] == 0) { prime_status = false; break; } } if (prime_status) { if (prev_prime == i - 2) { fprintf(fptr, "%lu %lu\n", prev_prime, i); // printf("%lu %lu\n", prev_prime, i); bro_counter++; } prev_prime = i; prime_counter++; } } fclose(fptr); printf("first_number %lu last_number %lu\n", received_first_last[0], received_first_last[1]); printf("\t%d %d\n", prime_counter, bro_counter); exit(bro_counter); // Возвращаем результат через код завершения } } // Код родительского процесса for (int i = 0; i < subproccess_count; ++i) { close(pipes[i][0]); // Закрываем читающие концы в родительском процессе } // Отправляем число дочерним процессам for (int i = 0; i < subproccess_count; ++i) { first_last[1] = pull_size + first_last[0]; write(pipes[i][1], &first_last, sizeof(first_last)); close(pipes[i][1]); first_last[0] = first_last[1]; } // Ждем завершения дочерних процессов и получаем результаты int statuses[subproccess_count]; for (int i = 0; i < subproccess_count; ++i) { waitpid(pids[i], &statuses[i], 0); } for (int i = 0; i < subproccess_count; ++i) { if (WIFEXITED(statuses[i])) { results[i] = WEXITSTATUS(statuses[i]); // printf("#%d bro counter: %lu\n", i, results[i]); } } return 0; }