118 lines
4.5 KiB
C
118 lines
4.5 KiB
C
#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;
|
||
}
|