#include #include #include #include #include #include #include int main(int argc, char *argv[]) { // Проверка аргументов командной строки if (argc < 4) { const char *usage = "Usage: parent " "[ ...]\n" " max_replacements: максимальное количество замен\n" " input/output: пары входных и выходных файлов\n"; fprintf(stderr, "%s", usage); return -1; } // Проверка четности количества файлов (пары input/output) if ((argc - 2) % 2 != 0) { fprintf(stderr, "Error: количество файлов должно быть четным (пары input/output)\n"); return -1; } const char *max_replacements_arg = argv[1]; int num_files = (argc - 2) / 2; // количество пар файлов printf("Родительский процесс: PID=%d\n", getpid()); printf("Будет запущено %d дочерних процессов\n", num_files); printf("Максимальное количество замен: %s\n\n", max_replacements_arg); // Массив для хранения PID дочерних процессов pid_t *child_pids = malloc(num_files * sizeof(pid_t)); if (child_pids == NULL) { perror("malloc failed"); return -1; } // Запуск дочерних процессов for (int i = 0; i < num_files; i++) { const char *input_file = argv[2 + i * 2]; const char *output_file = argv[2 + i * 2 + 1]; pid_t pid = fork(); if (pid < 0) { // Ошибка при создании процесса perror("fork failed"); // Ждем завершения уже запущенных процессов for (int j = 0; j < i; j++) { int status; waitpid(child_pids[j], &status, 0); } free(child_pids); return -1; } else if (pid == 0) { // Код дочернего процесса printf("Дочерний процесс %d: PID=%d, обработка %s -> %s\n", i + 1, getpid(), input_file, output_file); // Запуск программы из лабораторной работы №1 execl("./task18", "task18", input_file, output_file, max_replacements_arg, (char *)NULL); // Если execl вернул управление, произошла ошибка fprintf(stderr, "Дочерний процесс %d: execl failed для %s: %s\n", i + 1, input_file, strerror(errno)); _exit(-1); } else { // Код родительского процесса child_pids[i] = pid; } } // Ожидание завершения всех дочерних процессов printf("\nРодительский процесс ожидает завершения дочерних процессов...\n\n"); for (int i = 0; i < num_files; i++) { int status; pid_t terminated_pid = waitpid(child_pids[i], &status, 0); if (terminated_pid < 0) { perror("waitpid failed"); continue; } // Проверка статуса завершения if (WIFEXITED(status)) { int exit_code = WEXITSTATUS(status); printf("Процесс %d (PID=%d) завершился нормально\n", i + 1, terminated_pid); if (exit_code == 0) { printf(" Код завершения: %d (успех)\n", exit_code); } else { printf(" Код завершения: %d (ошибка)\n", exit_code); } } else if (WIFSIGNALED(status)) { int signal = WTERMSIG(status); printf("Процесс %d (PID=%d) был прерван сигналом %d\n", i + 1, terminated_pid, signal); } else { printf("Процесс %d (PID=%d) завершился с неизвестным статусом\n", i + 1, terminated_pid); } } printf("\nВсе дочерние процессы завершены\n"); free(child_pids); return 0; }