semop () должен ждать / блокировать, пока значение двоичного семафора не станет 1, но не ждет - PullRequest
0 голосов
/ 29 марта 2019

В родительском процессе создание объекта семафора только с одним семафором.Инициализация семафора в начальное значение ноль (0).Выполнение операции декремента в дочернем процессе и операции инкремента в родительском процессе.

Начальное значение - 0 Родитель - Приращение (1) Дочерний - Декремент (0)

Здесь я хочу спатьparent в течение некоторого времени, так что child ожидает уменьшения значения семафора до тех пор, пока parent не увеличит его до 1.

В parent я поместил sleep (10) и дал первому исполнению child семафор декремента, чтобы child ждал до 10 sec, покаparent увеличивает семафор.

Для этого я попробовал два разных подхода для реализации semop () (с IPC_NOWAIT и DEFAULT) в дочернем процессе, и я предоставлю код для обоих подходов.Я не понимаю, почему эти два подхода ведут себя по-разному, поскольку они должны давать одинаковое поведение.

Первый подход с использованием IPC_NOWAIT:

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

#define KEY1 12345

union semun {
             int val;
             struct semid_ds *buf;
             unsigned short *array;
             struct seminfo *__buf;
};

int main()
{
    int ret1,ret, sem, id2;
    union semun u1;
    struct sembuf sboa,sb;
    int status;

    sem = semget(KEY1, 1, IPC_CREAT|0600);

    if(sem<0) { perror("error in semaphore creation"); exit(1); }

    u1.val = 0;
    ret1=semctl(sem,0,SETVAL,u1);

    ret1 = semctl(sem,0,GETVAL);
    printf("Initial value of sem - %d\n",ret1);

    ret= fork();
    if(ret<0)
    {
        perror("error in chid");
        exit(1);
    }
    if(ret==0)
    {
        //sleep(1);
        int x;
        ret1 = semctl(sem,0,GETVAL);
        printf("child.....before decrement..the value of sem - %d\n",ret1);
        sboa.sem_num = 0;
        sboa.sem_op = -1;
        sboa.sem_flg = IPC_NOWAIT;

        while ((x = semop(sem, &sboa, 1) < 0))
        {
            if (errno == EAGAIN)
            {
                //printf("Not able to get semaphore, received EAGAIN error\n");
                //printf("child.....before decrement..the value of sem - %d\n",ret1);
                sleep(1); continue;
            }
            else
            {
                perror("exiting now from child as not able to do semop:");
                break;
            }
        }

        ret1 = semctl(sem,0,GETVAL);
        printf("child.....after decrement..the value of sem - %d\n",ret1);
        exit(0);
    }
    if(ret>0)
    {
        int x;
        ret1 = semctl(sem,0,GETVAL);
        printf("parent.....before increment..the value of sem - %d\n",ret1);
        sleep(10);

        sboa.sem_num = 0;
        sboa.sem_op =  +1;
        sboa.sem_flg = 0;

        semop(sem,&sboa, 1);

        ret1 = semctl(sem,0,GETVAL);
        printf("parent....after increment ..the value of sem - %d\n",ret1);
    }

    ret = waitpid(-1,&status,0);
    if(ret > 0 )
    {
        printf("Child with the id: %d terminated\n", ret);
        if(WIFEXITED(status))
        {
            printf("Process exited normally\n");
        }
        else
        {
            printf("Process exited abnormally");
        }
    }
    else
    {
        perror("Error in executing waitpid\n");
        exit(1);
    }

    semctl(sem,0,IPC_RMID);
    return(0);
}

// ВЫХОД с IPC_NOWAIT

Initial value of sem - 0
parent.....before increment..the value of sem - 0
child.....before decrement..the value of sem - 0
parent....after increment ..the value of sem - 1
child.....after decrement..the value of sem - 0
Child with the id: 10284 terminated
Process exited normally

Второй подход с использованием по умолчанию:

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

#define KEY1 12345

union semun {
             int val;
             struct semid_ds *buf;
             unsigned short *array;
             struct seminfo *__buf;
};

int main()
{
    int ret1,ret, sem, id2;
    union semun u1;
    struct sembuf sboa,sb;
    int status;

    sem = semget(KEY1, 1, IPC_CREAT|0600);

    if(sem<0) { perror("error in semaphore creation"); exit(1); }

    u1.val = 0;
    ret1=semctl(sem,0,SETVAL,u1);

    ret1 = semctl(sem,0,GETVAL);
    printf("Initial value of sem - %d\n",ret1);

    ret= fork();
    if(ret<0)
    {
        perror("error in chid");
        exit(1);
    }
    if(ret==0)
    {
        int x;
        ret1 = semctl(sem,0,GETVAL);
        printf("child.....before decrement..the value of sem - %d\n",ret1);
        sboa.sem_num = 0;
        sboa.sem_op = -1;
        sboa.sem_flg = 0;
        semop(sem, &sboa, 1);

        ret1 = semctl(sem,0,GETVAL);
        printf("child.....after decrement..the value of sem - %d\n",ret1);
        exit(0);
    }
    if(ret>0)
    {
        int x;
        ret1 = semctl(sem,0,GETVAL);
        printf("parent.....before increment..the value of sem - %d\n",ret1);
        sleep(10);

        sboa.sem_num = 0;
        sboa.sem_op =  +1;
        sboa.sem_flg = 0;

        semop(sem,&sboa, 1);

        ret1 = semctl(sem,0,GETVAL);
        printf("parent....after increment ..the value of sem - %d\n",ret1);
    }

    ret = waitpid(-1,&status,0);
    if(ret > 0 )
    {
        printf("Child with the id: %d terminated\n", ret);
        if(WIFEXITED(status))
        {
            printf("Process exited normally\n");
        }
        else
        {
            printf("Process exited abnormally");
        }
    }
    else
    {
        perror("Error in executing waitpid\n");
        exit(1);
    }

    semctl(sem,0,IPC_RMID);
    return(0);
}

// ВЫХОД с использованием DEFAULT

Initial value of sem - 0
parent.....before increment..the value of sem - 0
child.....before decrement..the value of sem - 0    --> after this the child should have blocked for 10 sec but it continued to print next line
child.....after decrement..the value of sem - 0     --> this line should have printed after 10 sec, how could child get to this line before decrementing semaphore??
parent....after increment ..the value of sem - 1
Child with the id: 10261 terminated
Process exited normally

Таким образом, при подходе DEFAULT semop () должен ждать, пока родительский процесс примет значение семафора1 но это не так, ПОЧЕМУ?Я использовал IPC_NOWAIT для реализации semop (). Должны ли мы всегда использовать этот подход?Каков лучший / рекомендуемый способ реализации semop () для такого рода проблем?ПРИМЕЧАНИЕ. Для справки используйте оба фрагмента кода.

...