Как мне синхронизировать c выходы двух процессов, используя семафор с C в Linux? - PullRequest
3 голосов
/ 28 марта 2020

У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

#define SEMAPHORE 0

int main(int argc, char *argv[])
{
    int semid, pid, j = 10;
    struct sembuf operation;
    key_t key;

    key = ftok(argv[0], 'U');

    if ((semid = semget(key, 1, IPC_CREAT | 0600)) == -1)
    {
        perror("Error at semget");
        exit(-1);
    }
    semctl(semid, SEMAPHORE, SETVAL, 1);

    /* Child is created  */
    if ((pid = fork()) == -1)
    {
        perror("Error at fork");
        exit(-1);
    }
    else if (pid == 0)
    {
        /* Code corresponding to the child process  */
        while (j)
        {
            /* DOWN operation is performed at the semaphore  */
            operation.sem_flg = 0;
            operation.sem_op = -1;
            operation.sem_num = SEMAPHORE;

            semop(semid, &operation, 1);

            printf("I AM THE CHILD PROCESS, IMPRESSION: %d\n", j--);

            /* UP operation is performed at the semaphore  */
            operation.sem_op = 1;
            operation.sem_num = SEMAPHORE;
            semop(semid, &operation, 1);
        }
    }
    else
    {
        /* Code corresponding to the parent process */
        while (j)
        {
            /* DOWN operation is performed at the semaphore */
            operation.sem_flg = 0;
            operation.sem_op = -1;
            operation.sem_num = SEMAPHORE;

            semop(semid, &operation, 1);

            printf("I AM THE FATHER PROCESS, IMPRESSION: %d\n", j--);

            /* UP operation is performed at the semaphore */
            operation.sem_op = 1;
            operation.sem_num = SEMAPHORE;
            semop(semid, &operation, 1);
        }
    }
}

Таким образом, я мог ожидать следующий вывод:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1
I AM THE CHILD PROCESS, IMPRESSION: 1

Или сначала последовательно ребенок, а затем отец. Тем не менее, я запускаю его и получаю следующий вывод:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 1

Или иногда получается такое впечатление, но я не получаю ожидаемого:

I AM THE FATHER PROCESS, IMPRESSION: 10
I AM THE FATHER PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 10
I AM THE CHILD PROCESS, IMPRESSION: 9
I AM THE CHILD PROCESS, IMPRESSION: 8
I AM THE CHILD PROCESS, IMPRESSION: 7
I AM THE CHILD PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 8
I AM THE FATHER PROCESS, IMPRESSION: 7
I AM THE FATHER PROCESS, IMPRESSION: 6
I AM THE CHILD PROCESS, IMPRESSION: 4
I AM THE CHILD PROCESS, IMPRESSION: 3
I AM THE CHILD PROCESS, IMPRESSION: 2
I AM THE CHILD PROCESS, IMPRESSION: 1
I AM THE FATHER PROCESS, IMPRESSION: 5
I AM THE FATHER PROCESS, IMPRESSION: 4
I AM THE FATHER PROCESS, IMPRESSION: 3
I AM THE FATHER PROCESS, IMPRESSION: 2
I AM THE FATHER PROCESS, IMPRESSION: 1

I Понимаете, что порядок выполнения процессов напрямую зависит от операционной системы, но разве не предполагается, что когда один из двух процессов запускается UP, другой должен войти в систему для запуска?

Поэтому мой вопрос таков: что именно здесь происходит?

1 Ответ

2 голосов
/ 28 марта 2020

Пусть P (sem) обозначает операцию down для семафора sem , а V (sem) обозначает операцию up для семафора sem .

В настоящее время ваш код выглядит так:

// semaphore s1
s1 = 1;
// parent process
P (s1);  
 // work
V (s1)

// child process
P (s1)
  // work
V (s1)

Итак, здесь говорится, что только один процесс может выполнять «работу» за раз, и ядро ​​следует за этим.

Для синхронизации вывода два процесса, необходимо сделать следующее.

// semaphores, sem-parent, sem-child
sem-parent = 1; sem-child = 0;

// parent process
P (sem-parent);
   // work
V (sem-child);

// child process
P (sem-child);
   // work
V (sem-parent);
...