Как мне заставить n процессов ждать, используя семафор? - PullRequest
0 голосов
/ 05 января 2019

Мне снова понадобится твоя помощь ...

Я пытаюсь разработать Программу на C, которая выполняет следующее:

managerProcess создает NUM_PROCESSES Student процессов.

Каждый Student Процесс, как только он создан, ожидает создания других процессов Student, пока не будет создано число процессов.

Когда все Student процессы созданы, они начинают выполнять свою работу, которая не относится к этому вопросу.

Важная вещь: каждый Student Процесс должен иметь одинаковый код.

Вот код, который я написал:

pid_t run_child(Student s, int index, int (*function)(Student s, int index)){
    pid_t  p;
    p = fork();
    if (p == -1) 
        return -1;
    else if (!p)
        exit(function(s, index));
    else 
        return p;
}



int child_process(Student s, int index){
    //This printf is executed NUM_PROCESSES times 
    printf("Child Process %d has been created\n", getpid());
    //Once reached this point each Process running this function will do other things

    /*SOME OTHER CODE STUDENT PROCESSES EXECUTE*/
    printf("%d Student Processes Created\n", NUM_PROCESSES);
    return EXIT_SUCCESS;
}

Наконец main.c Файл:

int main(int argc, char *argv[]){
    pid_t  child_pid[NUM_PROCESSES];
    int    child_status[NUM_PROCESSES];
    int i;
    int status;
    status = EXIT_SUCCESS; 

    for (i = 0; i < NUM_PROCESSES; i++) {
        Student s;
        child_pid[i] = run_child(s, i, child_process);
        if (child_pid[i] == -1) {
            fprintf(stderr, "Cannot fork a child process: %s.\n", strerror(errno));
            status = EXIT_FAILURE;
        } 
    }
    return status;
}

Как вы можете заметить, приведенный выше код создает NUM_PROCESSES Student процессов, и это хорошо. Я хочу, чтобы каждый Student Процесс ожидал создания всех NUM_PROCESSES Student Процессов, и только тогда они начинают делать другие вещи. Как мне добиться этого с помощью Semaphore, разработанного ниже?

//Creates ONE Semaphore
int createSemaphore(key_t semaphoreKey){
    int semaphoreId = semget(semaphoreKey, 1, 0666 | IPC_CREAT);
    if(semaphoreId == -1){
        printf(RED "Semaphore Creation failed\n"RESET);
        return -1;
    }
    return semaphoreId;
}

//Creates a set of Semaphores with numSems Semaphores
int createSemaphoreSet(key_t semaphoreKey, int numSems){
    int semaphoreId = semget(semaphoreKey, numSems, 0666 | IPC_CREAT);
    if(semaphoreId == -1){
        printf(RED "Semaphore Set Creation Failed\n" RESET);
        return -1;
    }
    return semaphoreId;
}

//Decreases semaphores value by 1
void semaphoreWait(int semaphoreId, int semaphoreNumber){
    struct sembuf buffer;
    buffer.sem_num = semaphoreNumber;
    buffer.sem_op = -1;
    buffer.sem_flg = 0;
    int done = semop(semaphoreId, &buffer, 1);
    if(done == -1){
        printf(RED "Wait on Semaphore %d failed\n" RESET, semaphoreNumber);
        return;
    }
}

//Increments semaphore's value by 1
void semaphoreSignal(int semaphoreId, int semaphoreNumber){
    struct sembuf buffer;
    buffer.sem_num = semaphoreNumber;
    buffer.sem_op = 1;
    buffer.sem_flg = 0;
    int done = semop(semaphoreId, &buffer, 1);
    if(done == -1){
        printf(RED "semaphoreSignal Failed on Semaphore %d\n" RESET, semaphoreNumber);
        return;
    }
}

Надеюсь, я был чист. Большое спасибо

1 Ответ

0 голосов
/ 05 января 2019

При использовании семафора System-V, который вы используете, общая схема будет выглядеть так:

  1. Родительский процесс создает или открывает семафор с помощью semget() и инициализирует его значение 0 с помощью semctl().

  2. Родитель разветвляет всех детей.

  3. Каждый дочерний элемент выполняет операцию семафора с уменьшением на единицу с помощью semop(). Например,

    struct sembuf semops = { .sem_num = 0, .sem_op = -1 };
    int result = semop(semid, &semops, 1);
    

    Каждый дочерний элемент будет блокироваться, пока не сможет выполнить эту операцию, не делая значение семафора отрицательным.

  4. Родитель использует semop() для увеличения значения семафора на количество дочерних процессов. Эта операция семафора не блокируется, и после ее завершения все дочерние элементы смогут продолжить.

    struct sembuf semops2 = { .sem_num = 0, .sem_op = NUM_PROCESSES };
    int result2 = semop(semid, &semops2, 1);
    

Существуют и другие комбинации операций с семафорами, которые могут достичь того, что вы описываете (и более современные разновидности семафоров, с которыми вы могли бы выполнять некоторые из них), но я полагаю, что вышеизложенное представляет стандартную идиому System-V для такой задачи.

...