kirill-refactor
This commit is contained in:
117
mine/lab_3/kirill/parent.c
Normal file
117
mine/lab_3/kirill/parent.c
Normal file
@@ -0,0 +1,117 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user