Массив структур в разделяемой памяти для двух процессов

Я пытаюсь создать массив структур для совместного использования родительским и дочерним процессом с помощью «shmget». Я следую шаблону моего профессора, но он не включает структуры и массивы (в общей памяти хранится только целое число). Следующий код компилируется без предупреждений, но возвращает «0» в качестве вывода, я ожидаю увидеть «10». Что я делаю неправильно?

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

typedef struct { 
    char character;
    int number;
} item;

int main(int argc, char *argv[])
{
    int mem_id;

    mem_id = shmget(IPC_PRIVATE, 10*sizeof(item), SHM_R | SHM_W);
    item * x;
    item * y;
    item * list[10];

    switch(fork())
    {
        case -1:
            perror("Bad fork()"); exit(1);
        case 0:
            *list = shmat(mem_id, NULL, 0);
            if ((int *) list == (int *) -1)
            {perror("Child cannot attach"); exit(1);}           

            x->character = 'a';
            x->number = 10;

            list[0] = x;

            shmdt(list);
            exit(0);
        default:
            *list = shmat(mem_id, NULL, 0);
            if ((int *) list == (int *) -1)
            {perror("Child cannot attach"); exit(1);}

            wait((int *)0);
            y = list[0];
            shmdt(list);

            printf("%c %d\n", y->character, y->number);

            if (shmctl(mem_id, IPC_RMID, 0) <0)
                { perror("cannot remove shared memory"); exit(1);}

            return 0;
    }
    return 0;
}

person infinite_fat    schedule 13.06.2011    source источник
comment
Мне кажется, вы никогда не инициализируете x   -  person Nemo    schedule 13.06.2011
comment
Если вам просто нужно поделиться между родителем и дочерним элементом, не беспокойтесь об уродстве shmat и т. д. Просто используйте mmap с MAP_SHARED перед fork, и сопоставленная область будет разделена между родителем и дочерним элементом. Лучше всего вам не придется беспокоиться об очистке его, когда вы выходите.   -  person R.. GitHub STOP HELPING ICE    schedule 13.06.2011
comment
Все ваши item являются указателями. Вы также никогда не инициализируете их, что означает, что вы меняете данные в неизвестном месте.   -  person ughoavgfhw    schedule 13.06.2011


Ответы (1)


Я удивлен, что вы не ошиблись, так как:

  1. Вы не инициализируете x, как указал Немо
  2. Ваш массив «список» на самом деле представляет собой массив указателей на элементы, а не массив элементов.
  3. Самое главное. Вы отключаете разделяемую память до того, как распечатаете значение в y.

Код должен выглядеть так:

typedef struct { 
    char character;
    int number;
} item;

int main(int argc, char *argv[])
{
    int mem_id;

    mem_id = shmget(IPC_PRIVATE, 10*sizeof(item), SHM_R | SHM_W);
    item *x;
    item *y;
    item *list;

    switch(fork())
    {
    case -1:
        perror("Bad fork()"); exit(1);
    case 0:
        list = (item *)shmat(mem_id, NULL, 0);
        if ((void *) -1 == (void *)list)
        {
            perror("Child cannot attach"); exit(1);
        }
        x = list;
        x->character = 'a';
        x->number = 10;

        shmdt(list); // No need for this
        exit(0);
    default:
        list = (item *)shmat(mem_id, NULL, 0);
        if ((void *) list == (void *) -1)
        {
           perror("Child cannot attach"); exit(1);
        }

        wait((int *)0);
        y = list;
        printf("%c %d\n", y->character, y->number);

        shmdt(list);

        if (shmctl(mem_id, IPC_RMID, 0) <0)
            { perror("cannot remove shared memory"); exit(1);}

        return 0;
    }
    return 0;
}
person Karlson    schedule 25.11.2011