Update guess_signals.c

This commit is contained in:
2025-04-18 06:40:12 +00:00
parent 81387814f8
commit 62fd2c92a5

View File

@@ -5,6 +5,7 @@
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <errno.h>
volatile sig_atomic_t start_signal_received = 0; volatile sig_atomic_t start_signal_received = 0;
@@ -34,6 +35,7 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Блокируем сигналы
sigset_t mask, oldmask; sigset_t mask, oldmask;
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, SIGRTMIN); sigaddset(&mask, SIGRTMIN);
@@ -42,21 +44,19 @@ int main(int argc, char *argv[]) {
sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, &oldmask); sigprocmask(SIG_BLOCK, &mask, &oldmask);
// Обработчик для старта угадывающего
struct sigaction sa; struct sigaction sa;
sa.sa_flags = SA_SIGINFO; sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sig_start_handler; sa.sa_sigaction = sig_start_handler;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sigaction(SIGRTMIN+1, &sa, NULL); sigaction(SIGRTMIN+1, &sa, NULL);
int round; // Параметры таймаута для sigtimedwait
for(round = 1; round <= total_rounds; round++) { struct timespec timeout = {5, 0}; // 5 секунд
for (int round = 1; round <= total_rounds; round++) {
int is_parent = (child_pid > 0); int is_parent = (child_pid > 0);
int secret_holder; int secret_holder = is_parent ? (round % 2 == 1) : (round % 2 == 0);
if(is_parent) {
secret_holder = (round % 2 == 1);
} else {
secret_holder = (round % 2 == 0);
}
if (secret_holder) { if (secret_holder) {
int secret = (rand() % N) + 1; int secret = (rand() % N) + 1;
@@ -68,12 +68,21 @@ int main(int argc, char *argv[]) {
int attempts = 0; int attempts = 0;
int guessed = 0; int guessed = 0;
pid_t other_pid = (is_parent ? child_pid : getppid()); pid_t other_pid = is_parent ? child_pid : getppid();
kill(other_pid, SIGRTMIN+1); kill(other_pid, SIGRTMIN+1);
while (!guessed) { while (!guessed) {
siginfo_t si; siginfo_t si;
int sig = sigwaitinfo(&mask, &si); int sig = sigtimedwait(&mask, &si, &timeout);
if (sig == -1) {
if (errno == EAGAIN) {
// тайм-аут, продолжаем ждать
continue;
} else {
perror("sigtimedwait");
exit(EXIT_FAILURE);
}
}
if (sig == SIGRTMIN) { if (sig == SIGRTMIN) {
int guess = si.si_value.sival_int; int guess = si.si_value.sival_int;
attempts++; attempts++;
@@ -87,58 +96,65 @@ int main(int argc, char *argv[]) {
} }
} }
} }
gettimeofday(&end, NULL); gettimeofday(&end, NULL);
double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1e6;
printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n",
round, getpid(), attempts, elapsed); round, getpid(), attempts, elapsed);
fflush(stdout); fflush(stdout);
} else { } else {
// Ожидаем сигнала старта от загадывающего
while (!start_signal_received) { while (!start_signal_received) {
sigsuspend(&oldmask); sigsuspend(&oldmask);
} }
start_signal_received = 0; // сбрасываем флаг start_signal_received = 0; // сбрасываем флаг
printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) начинает угадывать.\n", round, getpid()); printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) начинает угадывать.\n", round, getpid());
fflush(stdout); fflush(stdout);
struct timeval start, end; struct timeval start, end;
gettimeofday(&start, NULL); gettimeofday(&start, NULL);
int attempts = 0; int attempts = 0;
int guess = 0; int guess = 0;
int guessed = 0; int guessed = 0;
pid_t other_pid = is_parent ? child_pid : getppid();
while (!guessed) { while (!guessed) {
guess++; // последовательный перебор от 1 guess++; // последовательный перебор от 1
attempts++; attempts++;
union sigval value; union sigval value;
value.sival_int = guess; value.sival_int = guess;
pid_t other_pid;
if(is_parent) {
other_pid = child_pid;
} else {
other_pid = getppid();
}
sigqueue(other_pid, SIGRTMIN, value); sigqueue(other_pid, SIGRTMIN, value);
printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) отправил догадку: %d\n", round, getpid(), guess); printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) отправил догадку: %d\n", round, getpid(), guess);
fflush(stdout); fflush(stdout);
// Ожидаем ответа: SIGUSR1 (верно) или SIGUSR2 (неверно) // Ожидаем ответа: SIGUSR1 (верно) или SIGUSR2 (неверно)
siginfo_t si; siginfo_t si;
int sig = sigwaitinfo(&mask, &si); int sig = sigtimedwait(&mask, &si, &timeout);
if (sig == -1) {
if (errno == EAGAIN) {
// тайм-аут, можно повторить или обработать
continue;
} else {
perror("sigtimedwait");
exit(EXIT_FAILURE);
}
}
if (sig == SIGUSR1) { if (sig == SIGUSR1) {
guessed = 1; guessed = 1;
printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) получил верный ответ для догадки %d.\n", round, getpid(), guess); printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) получил верный ответ для догадки %d.\n", round, getpid(), guess);
fflush(stdout); fflush(stdout);
} else if(sig == SIGUSR2) {
// Продолжаем угадывать
} }
} }
gettimeofday(&end, NULL); gettimeofday(&end, NULL);
double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec) / 1e6;
printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n",
round, getpid(), attempts, elapsed); round, getpid(), attempts, elapsed);
fflush(stdout); fflush(stdout);
} }
} }
// По окончании раундов родитель ожидает завершения дочернего процесса
if (child_pid > 0) { if (child_pid > 0) {
wait(NULL); wait(NULL);
} }