// parent.c - Родительская программа для лабораторной работы №3 // Запускает программу lab1_var12 в нескольких дочерних процессах #include #include #include #include #include #include #include #define MAX_PROCESSES 100 // Структура для хранения информации о дочернем процессе typedef struct { pid_t pid; char *input_file; char *output_file; } ChildInfo; void print_usage(const char *progname) { fprintf(stderr, "Usage: %s [ ...]\n", progname); fprintf(stderr, "Example: %s ./lab1_var12 5 in1.txt out1.txt in2.txt out2.txt\n", progname); } int main(int argc, char *argv[]) { // Проверка минимального количества аргументов // Формат: parent <программа> [ ...] if (argc < 5 || (argc - 3) % 2 != 0) { fprintf(stderr, "ERROR: Недостаточное или неверное количество аргументов\n"); print_usage(argv[0]); return 1; } const char *lab1_program = argv[1]; const char *max_replacements = argv[2]; // Вычисляем количество пар (input, output) int num_files = (argc - 3) / 2; if (num_files > MAX_PROCESSES) { fprintf(stderr, "ERROR: Слишком много файлов (максимум %d пар)\n", MAX_PROCESSES); return 1; } printf("=== Запуск родительского процесса ===\n"); printf("Родительский PID: %d\n", getpid()); printf("Программа для запуска: %s\n", lab1_program); printf("Максимум замен: %s\n", max_replacements); printf("Количество файловых пар: %d\n\n", num_files); // Массив для хранения информации о дочерних процессах ChildInfo children[MAX_PROCESSES]; int created_count = 0; // Создаем дочерние процессы for (int i = 0; i < num_files; i++) { char *input_file = argv[3 + i * 2]; char *output_file = argv[3 + i * 2 + 1]; printf("Создание процесса %d для файлов: %s -> %s\n", i + 1, input_file, output_file); pid_t pid = fork(); if (pid < 0) { // Ошибка при создании процесса fprintf(stderr, "ERROR: Не удалось создать дочерний процесс для %s: %s\n", input_file, strerror(errno)); continue; // Продолжаем создавать остальные процессы } else if (pid == 0) { // Дочерний процесс printf(" -> Дочерний процесс PID=%d запускает обработку %s\n", getpid(), input_file); // Запускаем программу lab1_var12 с аргументами execl(lab1_program, lab1_program, input_file, output_file, max_replacements, NULL); // Если execl вернул управление, значит произошла ошибка fprintf(stderr, "ERROR: Не удалось запустить программу %s: %s\n", lab1_program, strerror(errno)); _exit(-1); } else { // Родительский процесс children[created_count].pid = pid; children[created_count].input_file = input_file; children[created_count].output_file = output_file; created_count++; } } if (created_count == 0) { fprintf(stderr, "ERROR: Ни один дочерний процесс не был создан\n"); return 1; } printf("\n=== Ожидание завершения дочерних процессов ===\n"); // Ожидаем завершения всех дочерних процессов int success_count = 0; int error_count = 0; for (int i = 0; i < created_count; i++) { int status; pid_t finished_pid = waitpid(children[i].pid, &status, 0); if (finished_pid < 0) { fprintf(stderr, "ERROR: Ошибка при ожидании процесса PID=%d: %s\n", children[i].pid, strerror(errno)); error_count++; continue; } printf("\nПроцесс PID=%d завершен (%s -> %s)\n", finished_pid, children[i].input_file, children[i].output_file); if (WIFEXITED(status)) { int exit_code = WEXITSTATUS(status); printf(" Код завершения: %d\n", exit_code); if (exit_code == 0) { printf(" Статус: SUCCESS\n"); success_count++; } else if (exit_code == 255 || exit_code == -1) { printf(" Статус: ERROR (не удалось выполнить)\n"); error_count++; } else { printf(" Статус: ERROR\n"); error_count++; } } else if (WIFSIGNALED(status)) { int signal = WTERMSIG(status); printf(" Процесс завершен сигналом: %d\n", signal); printf(" Статус: ERROR (получен сигнал)\n"); error_count++; } else { printf(" Статус: Неизвестный статус завершения\n"); error_count++; } } printf("\n=== Итоговая статистика ===\n"); printf("Всего запущено процессов: %d\n", created_count); printf("Успешно завершено: %d\n", success_count); printf("Завершено с ошибкой: %d\n", error_count); if (error_count > 0) { printf("\nОБЩИЙ СТАТУС: Завершено с ошибками\n"); return 1; } else { printf("\nОБЩИЙ СТАТУС: Все процессы завершены успешно\n"); return 0; } }