У меня есть гоночная программа на C, в которой всегда один и тот же победитель, несмотря ни на что - PullRequest
1 голос
/ 30 мая 2019

Следующая программа управляется именованными семафорами и должна делать это:

  1. Основной процесс создает N_PROC дочерних элементов, и каждому дочернему элементу назначается идентификатор ( 0 для первого созданного дочернего элемента, 1 для второго и т. Д. ).
  2. Каждый ребенок ждет сигнала от своего отца, используя pause().
  3. Основной процесс посылает своим детям сигнал SIGUSR1.
  4. Каждый ребенок повторяет это до тех пор, пока не умрет: они открывают файл (один и тот же файл для всех детей), пишут свой идентификатор, закрывают файл и затем спят в течение произвольного числа миллисекунд от 1 до 100.
  5. Каждую секунду основной процесс открывает тот же файл, что и его дочерние элементы, подсчитывает, сколько раз каждый идентификатор присутствует (печатая их, когда он их читает), и, если дочерний элемент записал свой идентификатор 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);
}

1 Ответ

1 голос
/ 30 мая 2019

Вы не сбрасываете массив num перед сканированием файла.Бывает, что в вашей системе третий дочерний объект сначала записывает в файл.

Вам необходимо очистить этот массив перед синтаксическим анализом файла с помощью:

memset(num, 0, sizeof num);

или

for (i = 0; i < N_PROC; i++)
    num[i] = 0;
...