diff --git a/guess_pipe.c b/guess_pipe.c new file mode 100644 index 0000000..f2246e2 --- /dev/null +++ b/guess_pipe.c @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include +#include + +#define BUF_SIZE 16 + +void write_int(int fd, int value) { + if(write(fd, &value, sizeof(value)) != sizeof(value)) { + perror("write_int"); + exit(EXIT_FAILURE); + } +} + +int read_int(int fd) { + int value; + ssize_t n = read(fd, &value, sizeof(value)); + if(n == 0) { + exit(EXIT_SUCCESS); + } else if(n != sizeof(value)) { + perror("read_int"); + exit(EXIT_FAILURE); + } + return value; +} + +void write_start(int fd) { + const char *msg = "START"; + if(write(fd, msg, strlen(msg)) != (ssize_t)strlen(msg)) { + perror("write_start"); + exit(EXIT_FAILURE); + } +} + +void read_start(int fd) { + char buf[BUF_SIZE] = {0}; + ssize_t n = read(fd, buf, strlen("START")); + if(n <= 0) { + perror("read_start"); + exit(EXIT_FAILURE); + } + buf[n] = '\0'; + if(strcmp(buf, "START") != 0) { + fprintf(stderr, "Ожидалось START, получено: %s\n", buf); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char *argv[]) { + if(argc < 2) { + fprintf(stderr, "Использование: %s N\n", argv[0]); + exit(EXIT_FAILURE); + } + int N = atoi(argv[1]); + if(N <= 0) { + fprintf(stderr, "N должно быть положительным числом\n"); + exit(EXIT_FAILURE); + } + + srand(time(NULL) ^ getpid()); + int total_rounds = 10; + + int pipe_parent_to_child[2], pipe_child_to_parent[2]; + if(pipe(pipe_parent_to_child) < 0 || pipe(pipe_child_to_parent) < 0) { + perror("pipe"); + exit(EXIT_FAILURE); + } + + pid_t child_pid = fork(); + if(child_pid < 0) { + perror("fork"); + exit(EXIT_FAILURE); + } + + int round; + for(round = 1; round <= total_rounds; round++) { + int is_parent = (child_pid > 0); + int secret_holder; + if(is_parent) { + secret_holder = (round % 2 == 1); + } else { + secret_holder = (round % 2 == 0); + } + + if(secret_holder) { + // Процесс загадывает число + int secret = (rand() % N) + 1; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) загадывает число.\n", round, getpid()); + fflush(stdout); + struct timeval start, end; + gettimeofday(&start, NULL); + int attempts = 0; + + if(is_parent) { + write_start(pipe_parent_to_child[1]); + while(1) { + // Читаем догадку от ребёнка из pipe_child_to_parent + int guess = read_int(pipe_child_to_parent[0]); + attempts++; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) получил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + if(guess == secret) { + // Отправляем ответ 1 (верно) через pipe_parent_to_child + write_int(pipe_parent_to_child[1], 1); + break; + } else { + // Отправляем ответ 0 (неверно) + write_int(pipe_parent_to_child[1], 0); + } + } + } else { + write_start(pipe_child_to_parent[1]); + while(1) { + int guess = read_int(pipe_parent_to_child[0]); + attempts++; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) получил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + if(guess == secret) { + write_int(pipe_child_to_parent[1], 1); + break; + } else { + write_int(pipe_child_to_parent[1], 0); + } + } + } + gettimeofday(&end, NULL); + double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", + round, getpid(), attempts, elapsed); + fflush(stdout); + } else { + struct timeval start, end; + gettimeofday(&start, NULL); + int attempts = 0; + int guess = 0; + if(is_parent) { + read_start(pipe_child_to_parent[0]); + while(1) { + guess++; // перебор от 1 + attempts++; + write_int(pipe_parent_to_child[1], guess); + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) отправил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + int resp = read_int(pipe_child_to_parent[0]); + if(resp == 1) { + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) получил верный ответ для догадки %d.\n", round, getpid(), guess); + fflush(stdout); + break; + } + } + } else { + read_start(pipe_parent_to_child[0]); + while(1) { + guess++; + attempts++; + write_int(pipe_child_to_parent[1], guess); + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) отправил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + int resp = read_int(pipe_parent_to_child[0]); + if(resp == 1) { + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) получил верный ответ для догадки %d.\n", round, getpid(), guess); + fflush(stdout); + break; + } + } + } + gettimeofday(&end, NULL); + double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", + round, getpid(), attempts, elapsed); + fflush(stdout); + } + } + + // Закрываем каналы и ожидаем завершения дочернего процесса (если родитель) + if(child_pid > 0) { + close(pipe_parent_to_child[0]); + close(pipe_parent_to_child[1]); + close(pipe_child_to_parent[0]); + close(pipe_child_to_parent[1]); + wait(NULL); + } + return 0; +} diff --git a/guess_signals.c b/guess_signals.c new file mode 100644 index 0000000..7dee226 --- /dev/null +++ b/guess_signals.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include + +volatile sig_atomic_t start_signal_received = 0; + +void sig_start_handler(int sig, siginfo_t *info, void *ucontext) { + start_signal_received = 1; +} + +int main(int argc, char *argv[]) { + if(argc < 2) { + fprintf(stderr, "Использование: %s N\n", argv[0]); + exit(EXIT_FAILURE); + } + int N = atoi(argv[1]); + if(N <= 0) { + fprintf(stderr, "N должно быть положительным числом\n"); + exit(EXIT_FAILURE); + } + + srand(time(NULL) ^ getpid()); + + int total_rounds = 10; // минимум 10 раундов + + // Создаем второй процесс + pid_t child_pid = fork(); + if(child_pid < 0) { + perror("fork"); + exit(EXIT_FAILURE); + } + + sigset_t mask, oldmask; + sigemptyset(&mask); + sigaddset(&mask, SIGRTMIN); + sigaddset(&mask, SIGRTMIN+1); + sigaddset(&mask, SIGUSR1); + sigaddset(&mask, SIGUSR2); + sigprocmask(SIG_BLOCK, &mask, &oldmask); + + struct sigaction sa; + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = sig_start_handler; + sigemptyset(&sa.sa_mask); + sigaction(SIGRTMIN+1, &sa, NULL); + + int round; + for(round = 1; round <= total_rounds; round++) { + int is_parent = (child_pid > 0); + int secret_holder; + if(is_parent) { + secret_holder = (round % 2 == 1); + } else { + secret_holder = (round % 2 == 0); + } + + if(secret_holder) { + int secret = (rand() % N) + 1; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) загадывает число.\n", round, getpid()); + fflush(stdout); + + struct timeval start, end; + gettimeofday(&start, NULL); + int attempts = 0; + int guessed = 0; + + pid_t other_pid = (is_parent ? child_pid : getppid()); + kill(other_pid, SIGRTMIN+1); + + while(!guessed) { + siginfo_t si; + int sig = sigwaitinfo(&mask, &si); + if(sig == SIGRTMIN) { + int guess = si.si_value.sival_int; + attempts++; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) получил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + if(guess == secret) { + kill(other_pid, SIGUSR1); + guessed = 1; + } else { + kill(other_pid, SIGUSR2); + } + } + } + gettimeofday(&end, NULL); + double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; + printf("Раунд %d: Процесс %d (ЗАГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", + round, getpid(), attempts, elapsed); + fflush(stdout); + + } else { + while(!start_signal_received) { + sigsuspend(&oldmask); + } + start_signal_received = 0; // сбрасываем флаг + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) начинает угадывать.\n", round, getpid()); + fflush(stdout); + struct timeval start, end; + gettimeofday(&start, NULL); + int attempts = 0; + int guess = 0; + int guessed = 0; + while(!guessed) { + guess++; // последовательный перебор от 1 + attempts++; + union sigval value; + value.sival_int = guess; + pid_t other_pid; + if(is_parent) { + other_pid = child_pid; + } else { + other_pid = getppid(); + } + sigqueue(other_pid, SIGRTMIN, value); + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) отправил догадку: %d\n", round, getpid(), guess); + fflush(stdout); + // Ожидаем ответа: SIGUSR1 (верно) или SIGUSR2 (неверно) + siginfo_t si; + int sig = sigwaitinfo(&mask, &si); + if(sig == SIGUSR1) { + guessed = 1; + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) получил верный ответ для догадки %d.\n", round, getpid(), guess); + fflush(stdout); + } else if(sig == SIGUSR2) { + // Продолжаем угадывать + } + } + gettimeofday(&end, NULL); + double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec)/1000000.0; + printf("Раунд %d: Процесс %d (УГАДЫВАЮЩИЙ) завершил раунд. Попыток: %d, время: %.3f сек.\n", + round, getpid(), attempts, elapsed); + fflush(stdout); + } + } + + // По окончании раундов родитель ожидает завершения дочернего процесса + if(child_pid > 0) { + wait(NULL); + } + return 0; +}