initial version
This commit is contained in:
parent
1ba98d55b1
commit
48976fecd7
187
guess_pipe.c
Normal file
187
guess_pipe.c
Normal file
@ -0,0 +1,187 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
146
guess_signals.c
Normal file
146
guess_signals.c
Normal file
@ -0,0 +1,146 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user