Следующая программа управляется именованными семафорами и должна делать это:
- Основной процесс создает
N_PROC
дочерних элементов, и каждому дочернему элементу назначается идентификатор ( 0 для первого созданного дочернего элемента, 1 для второго и т. Д. ).
- Каждый ребенок ждет сигнала от своего отца, используя
pause()
.
- Основной процесс посылает своим детям сигнал
SIGUSR1
.
- Каждый ребенок повторяет это до тех пор, пока не умрет: они открывают файл (один и тот же файл для всех детей), пишут свой идентификатор, закрывают файл и затем спят в течение произвольного числа миллисекунд от 1 до 100.
- Каждую секунду основной процесс открывает тот же файл, что и его дочерние элементы, подсчитывает, сколько раз каждый идентификатор присутствует (печатая их, когда он их читает), и, если дочерний элемент записал свой идентификатор 20 раз, объявляет, что дочерний элемент Победитель отправляет
SIGTERM
всем своим детям, ждет, пока они закончат, а затем удаляет семафоры.
Моя проблема в том, что независимо от того, сколько раз я перекомпилирую или перезапускаю программу, родитель всегда печатает одно и то же, и, таким образом, ребенок номер 2 всегда становится победителем.
Заранее спасибо.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define SEM3 "/example_sem3"
#define FFILE "ejercicio9.txt"
#define N_PROC 3
int valor_semaforo(sem_t *sem) {
int sval;
if (sem_getvalue(sem, &sval) == -1) {
perror("sem_getvalue");
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
exit(EXIT_FAILURE);
}
return sval;
}
int main(void) {
sem_t *sem_write = NULL, *sem_read = NULL, *sem_count = NULL;
pid_t pid[N_PROC];
int i, numero, num[N_PROC], t;
struct sigaction act;
FILE *fp;
srand(time(NULL) + getpid());
if ((sem_write = sem_open(SEM1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_read = sem_open(SEM2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_count = sem_open(SEM3, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
for (i = 0; i < N_PROC; i++) {
num[i] = 0;
pid[i] = fork();
if (pid[i] < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid[i] == 0) {
pause();
while (1) {
sem_wait(sem_write);
fp = fopen(FFILE, "a+");
fprintf(fp, "%d ", i);
fclose(fp);
sem_post(sem_write);
usleep(1 + (rand() % 100));
}
}
}
kill(0, SIGUSR1);
while (1) {
sleep(1);
sem_wait(sem_read);
sem_post(sem_count);
if (valor_semaforo(sem_count) == 1)
sem_wait(sem_write);
sem_post(sem_read);
fp = fopen(FFILE, "r");
while (fscanf(fp, "%d", &numero) > 0) {
printf("%d ", numero);
fflush(stdout);
for (i = 0; i < N_PROC; i++) {
if (numero == i)
(num[i])++;
if (num[i] == 20) {
printf("\nHa finalizado la carrera: el ganador es el proceso %d\n", i);
fflush(stdout);
act.sa_handler = SIG_IGN;
if (sigaction(SIGTERM, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
kill(0, SIGTERM);
while (wait(NULL) > 0);
sem_close(sem_write);
sem_close(sem_read);
sem_close(sem_count);
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
fclose(fp);
exit(EXIT_SUCCESS);
}
}
}
}
printf("\n");
fflush(stdout);
fp = fopen(FFILE, "w+");
fclose(fp);
sem_wait(sem_read);
sem_wait(sem_count);
if (valor_semaforo(sem_count) == 0)
sem_post(sem_write);
sem_post(sem_read);
}