#include #include #include #include #include #include #include #include #include #define MAX(a, b) ((a) > (b) ? (a) : (b)) // Функция для создания дочернего процесса с перенаправлением STDIN BOOL CreateChildProcess( LPTSTR commandLine, HANDLE hChildStdIn, HANDLE hChildStdOut, PROCESS_INFORMATION *pi ) { // PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); si.hStdOutput = hChildStdOut; si.hStdInput = hChildStdIn; si.dwFlags |= STARTF_USESTDHANDLES; ZeroMemory(pi, sizeof(*pi)); return CreateProcess( NULL, // Имя исполняемого модуля commandLine, // Командная строка NULL, // Атрибуты безопасности процесса NULL, // Атрибуты безопасности потока TRUE, // Наследование дескрипторов 0, // Флаги создания NULL, // Окружение NULL, // Текущий каталог &si, // STARTUPINFO pi // PROCESS_INFORMATION ); } int main(int argc, char **argv) { if (argc != 4) { printf("Usage: %s \n", argv[0]); return 1; } uint64_t first_number; uint64_t last_number; int subproccess_count = 2; subproccess_count = atoll(argv[1]); if (subproccess_count < 1) { printf("Subprocess amount should be 1 or more\n"); return 1; } first_number = MAX(llabs(atoll(argv[2])), 3); last_number = llabs(atoll(argv[3])); if (last_number <= first_number) { printf("Last number must be greater than the first number.\n"); return 1; } // HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hStdInPipeWrite[subproccess_count]; HANDLE hStdInPipeRead[subproccess_count]; HANDLE hStdOutPipeWrite[subproccess_count]; HANDLE hStdOutPipeRead[subproccess_count]; // HANDLE hPipeRead[subproccess_count], hPipeWrite[subproccess_count]; PROCESS_INFORMATION pi[subproccess_count]; HANDLE processHandles[subproccess_count]; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // Создаем каналы для процесса-возводителя в квадрат for (int i = 0; i < subproccess_count; ++i) { if (!CreatePipe(&hStdInPipeRead[i], &hStdInPipeWrite[i], &saAttr, 0)) { printf("StdIn CreatePipe #%d failed (%lu)\n", i, GetLastError()); return 1; } if (!SetHandleInformation(hStdInPipeWrite[i], HANDLE_FLAG_INHERIT, 0)) { printf("StdIn SetHandleInformation failed (%lu)\n", GetLastError()); return 1; } if (!CreatePipe(&hStdOutPipeRead[i], &hStdOutPipeWrite[i], &saAttr, 0)) { printf("StdOut CreatePipe #%d failed (%lu)\n", i, GetLastError()); return 1; } if (!SetHandleInformation(hStdOutPipeRead[i], HANDLE_FLAG_INHERIT, 0)) { printf("StdOut SetHandleInformation failed (%lu)\n", GetLastError()); return 1; } } // Создаем процесс для возведения в квадрат TCHAR sqCmdLine[] = "twinfinder.exe"; for (int i = 0; i < subproccess_count; ++i) { if (!CreateChildProcess(sqCmdLine, hStdInPipeRead[i], hStdOutPipeWrite[i], &pi[i])) { printf("CreateChildProcess #%d failed (%lu)\n", i, GetLastError()); return 1; } processHandles[i] = pi[i].hProcess; CloseHandle(hStdInPipeRead[i]); CloseHandle(hStdOutPipeWrite[i]); CloseHandle(pi[i].hThread); } uint64_t numbers[3]; uint64_t pull_size = (last_number - first_number) / subproccess_count; numbers[0] = first_number; numbers[2] = pull_size; printf("first_number: %zu, last_number: %zu, pull_size: %zu\n", first_number, last_number, pull_size); numbers[1] = pull_size + numbers[0]; // Передаем число процессу-возводителю в квадрат for (int i = 0; i < subproccess_count; ++i) { DWORD dwWritten; if (!WriteFile(hStdInPipeWrite[i], numbers, sizeof(numbers), &dwWritten, NULL)) { printf("WriteFile to pipe #%d failed (%lu)\n", i, GetLastError()); return 1; } CloseHandle(hStdInPipeWrite[i]); numbers[0] = numbers[1] - 2; numbers[1] = pull_size + numbers[0] + 2; Sleep(1000); } // Закрываем каналы записи for (int i = 0; i < subproccess_count; ++i) { } size_t max_size = pull_size; // size_t max_size = 2 * (size_t)sqrt(pull_size + 2); size_t size = 2 * (uint32_t)sqrt(numbers[2] + 2); uint64_t *results = (uint64_t*) malloc(size * sizeof(uint64_t)); // uint64_t results[subproccess_count * max_size]; if (results == NULL) { // Handle memory allocation failure perror("malloc failed"); return 1; // Exit } size_t total_size = 0; for (int i = 0; i < subproccess_count; ++i) { // uint64_t read_buffer[pull_size]; size_t read_buffer_size = pull_size * sizeof(uint64_t); uint64_t *read_buffer = (uint64_t*) malloc(read_buffer_size); DWORD dwRead; while (ReadFile(hStdOutPipeRead[i], read_buffer, read_buffer_size, &dwRead, NULL) && dwRead > 0) { size_t elements_read = dwRead / sizeof(uint64_t); // printf("Read %zu elements from pipe %d.\n", elements_read, i); if (total_size + elements_read > size) { size_t new_size = size * 2; if (new_size < total_size + elements_read) { new_size = total_size + elements_read; } // printf("Resizing needed: total_size (%zu) + elements_read (%zu) > size (%zu)\n", total_size, elements_read, size); // printf(" -> New size will be %zu\n", new_size); uint64_t* new_results = (uint64_t*) realloc(results, new_size * sizeof(uint64_t)); if (new_results == NULL) { perror("realloc failed"); free(results); // Free the old memory return 1; } // Update pointer and capacity results = new_results; size = new_size; } memcpy(results + total_size, read_buffer, dwRead); total_size += elements_read; // printf("After copy: total_size = %zu, size = %zu\n\n", total_size, size); } CloseHandle(hStdOutPipeRead[i]); } WaitForMultipleObjects(subproccess_count, processHandles, TRUE, INFINITE); for (int i = 0; i < subproccess_count; ++i) { CloseHandle(processHandles[i]); } printf("Parent received all results. Found %zu twin primes:\n", total_size); for (size_t i = 0; i < total_size; ++i) { printf("%llu %llu\n", results[i] - 2, results[i]); } printf("Parent received all results. Found %zu twin primes:\n", total_size); free(results); printf("Parent process finished.\n"); return 0; }