Files
CS-LABS/kirill/lab_3/parent.c
2025-12-10 16:50:28 +07:00

118 lines
4.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]) {
// Проверка аргументов командной строки
if (argc < 4) {
const char *usage =
"Usage: parent <max_replacements> <input1.txt> <output1.txt> "
"[<input2.txt> <output2.txt> ...]\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;
}