Как поделиться связанным списком между двумя процессами? - PullRequest
3 голосов
/ 18 февраля 2010

У меня есть два процесса, и я хочу поделиться связанным списком между ними. Один из процессы просто будут читать список, в то время как другой процесс собирается изменить список (добавить / удалить записи). Можете ли вы сказать мне, как этого добиться?


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

Если кто-нибудь может сказать мне, как его достичь, тогда он мне очень поможет.

У меня есть одна идея, как упомянуто ниже: Могу ли я сделать что-то вроде этого, где я создаю сегмент общей памяти размером узла. Тогда я просто имею дело с malloc? Что я имею в виду, я создам общую память с помощью shmget (key, SHMSZ, IPC_CREAT | 0666), где SHMSZ будет иметь размер узла структуры. Так что я делю только главу списка между двумя процессами. Первая запись в списке будет иметь все значения 0, кроме записи ссылки, которая будет указывать на следующую запись в списке, и эта запись создается с помощью malloc, поскольку в моем приложении, так как другой процесс будет читать только пока один процесс будет добавлять / удалить записи в списке.

Я получил один ответ, который говорит мне, что я не могу использовать malloc. Не знаю почему не могу используйте malloc. Не могли бы вы сказать мне, почему я не могу использовать malloc?

Ниже приведен мой код для вышеуказанной цели, который я пытался, но получил ошибку сегментации.

struct node
{
    int val;
    struct node* next;
};

void append(struct node *q,int val);
main()
{

    key_t key = 5678;

    int shmid;

    struct node *head;

    if ((shmid = shmget(key, sizeof(struct node), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    };

    head = struct node*(shmat(shmid, (void *) 0, 0));

    head->val = 0;
    head->next= 0;

    append(head,2);
    append(head,5);
    append(head,6);

    exit(0);
}

void append(struct node *q,int val)

{
    struct node *temp1,*temp2;

    if (q->next == 0)

    {
        temp1=malloc(sizeof(struct node));
        temp1->val = val;
        temp1->next = 0;
        q->next = temp1;
    }

    else

    {
        temp2=malloc(sizeof(struct node));
        temp2->val = val;

        temp1 = q->next;
        while(1)
        {
            if (temp1 == 0)
            {
                temp1=temp2;
                break;
            }
            else
                temp1=temp1->next;
        }
    }

    return;

}

Ответы [ 4 ]

2 голосов
/ 19 февраля 2010

Я не знаю, кто такой Бидж, но он пишет превосходные справочники , и он написал один для сегментов общей памяти .

1 голос
/ 18 февраля 2010

У вас есть несколько вариантов:

  • использовать межпроцессное взаимодействие (сокеты, именованные каналы и т. Д.) Для отправки дублированного списка каждому процессу, которому требуется копия.У вас будут дублирующиеся списки, что может означать, что вы будете выполнять дублирующую работу, и у вас возникнет проблема с синхронизацией списков - это может или не может иметь отношение к вашей проблеме.
  • используйте сервер списков,и межпроцессное взаимодействие для запроса или установки элементов списка.Вам нужно будет изящно обрабатывать случаи, когда клиент никогда не возвращает элемент списка (возможно, с тактовым сигналом и / или временем резервирования)
  • использовать разделяемую память для непосредственного совместного использования списка между процессами.Вы должны быть очень осторожны с блокировкой, и она не будет работать в разных системах.
  • используйте fork (), и пусть дочерний процесс наследует список.Как и в первом решении, вы получите дублирующиеся списки с (потенциально) дублирующейся работой или дублирующимися элементами.Как и в третьем решении, это не работает во всех системах.
  • использует некоторую комбинацию из перечисленного.
0 голосов
/ 19 февраля 2010

Причина, по которой вы не можете использовать malloc для отдельных узлов, заключается в том, что malloc возвращает указатель в кучу для данного процесса. Указатель ничего не значит для другого процесса, который имеет свою собственную кучу. Адрес может быть действительным в обоих процессах, но «физическая» память, на которую он ссылается, будет разной.

Если вы используете shmget, вам нужно будет использовать его для каждого узла (или создать больший кусок, а затем использовать смещения в нем, как уже было предложено). Если для каждого узла использовались отдельные вызовы shmget, то ключом мог быть указатель next в списке. Это был бы «простой» способ его реализации, но он не может быть хорошей идеей. Я считаю, что существует общесистемное ограничение на объекты общей памяти. Я думаю, что это определено SHMMNI, который является 4096 в системе, которую я только что проверил.

Другим способом его реализации было бы просто сделать один процесс владельцем списка (процесс, который создает и удаляет узлы). Затем используйте один объект общей памяти для связи между двумя процессами, чтобы раздавать отдельные узлы. Затем для синхронизации использовались общие семафоры (semget, semop и т. Д.).

0 голосов
/ 19 февраля 2010

Простой ответ: не надо.

Преимущество нескольких процессов заключается в том, что у вас нет общей памяти. Это дает вам изоляцию от другого процесса. Наличие барьера «только для данных» дает вам большие преимущества в плане дизайна и надежности.

Вместо этого, процесс производства должен отправить новые данные (как данные) в процесс потребления. Это может быть сделано через STDIN / STDOUT, или через сокет, или даже что-то столь же низкое как файл.

...