Как я могу управлять каналом, идущим вверх, и каналом, спускающимся по бинарному дереву процессов?

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

Проблема: Родительский процесс A создает два процесса (B и C) и два канала, по одному для каждого процесса. Их файловые дескрипторы хранятся в файле fd. Во второй итерации B порождает двух своих дочерних элементов. B перезаписывает дескрипторы файлов, хранящиеся в fd, дескрипторами файлов нового канала. После создания моего n уровней единственными оставшимися каналами являются конечные узлы их родителей (на один уровень выше).

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

Я новичок в трубах, поэтому я мог бы не объяснять свое объяснение.

Правильно ли я понимаю, и что мне делать, чтобы решить эту проблему?

Образец кода:

#define READ 0
#define WRITE 1

int fd[2][2];

void
spawnChildren(int levels)
{
    if(levels == 0)
       return;

    pipe(fd[0]);
    //spawns 2 children at a single parent
    int pid = fork();
    //parent
    if(pid > 0)
    {
        close(fd[0][WRITE]);
        pipe(fd[1]);
        int pid2 = fork();
        //child B
        if(pid2 == 0)
        {
            close(fd[1][READ]);
            spawnChildren(levels-1);
            return;
        }
        //parent
        else
            close(fd[1][WRITE]);
    }
    //child A
    else
    {
        close(fd[0][READ]);
        spawnChildren(levels-1);
        return;
    }
}

person Swiggity Swooty    schedule 03.10.2012    source источник
comment
Надеюсь, вам не нужно слишком много процессов. Создание небольшого дерева, вероятно, нормально, но попытка построить дерево с тысячами отдельных процессов, вероятно, не будет масштабироваться.   -  person Robert Harvey    schedule 03.10.2012
comment
Кажется, вы нигде не отслеживаете канал обратно к родительскому процессу? Каждый процесс, кроме корня и листьев, должен отслеживать три канала — по одному для каждого дочернего процесса и один для его родителя.   -  person twalberg    schedule 04.10.2012
comment
Чтобы отслеживать подъем канала, следует ли использовать dup2? пример: левое чтение родителя будет эквивалентно каналу записи вверх левого дочернего элемента. Это правильно?   -  person Swiggity Swooty    schedule 04.10.2012
comment
Вы думали о чтении и записи в файлы вместо каналов? Это может упростить вещи в зависимости от того, чего вы пытаетесь достичь.   -  person dbeer    schedule 04.10.2012
comment
Я должен использовать трубы, так как это задание.   -  person Swiggity Swooty    schedule 04.10.2012


Ответы (2)


Если я правильно понимаю, корневой процесс открыл два fd для связи со своими двумя потомками. Затем они просто открывают другие, независимые трубы.

Как корневой процесс может общаться со своими племянниками, когда им четыре?

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

Например, корневой родитель хочет общаться с левым дочерним элементом правого дочернего элемента своего левого дочернего элемента:

  • он отправляет RL.HELLO WORLD своему левому потомку
  • левый дочерний элемент видит R и отправляет #L.HELLO WORLD своему правому дочернему элементу
  • правый дочерний элемент получает #L.HELLO WORLD и отправляет ##.HELLO WORLD своему левому дочернему элементу
  • левый ребенок получает ##.HELLO WORLD и знает, что сообщение для него

  • левый ребенок отвечает, посылая ##.I HEAR YOU своему родителю

  • родитель видит, что его левый ребенок говорит, преобразует последний # в L и отправляет вверх
  • родитель видит, что его правый ребенок говорит #L.I HEAR YOU, и отправляет RL.I HEAR YOU
  • корень получает RL. Я СЛЫШУ ВАС от своего левого потомка и знает, кто его создал

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

Даже для связи только между корнем и листьями потребуются очереди и передача сообщений; это позволило бы только обойтись без протокола "R#L", но, учитывая его простоту, это очень небольшая экономия.

person LSerni    schedule 03.10.2012
comment
Передача сообщений идет только вверх, а это означает, что дети — единственные, кто может писать своим родителям. Родители - единственные, кто может читать слова своих детей. Передача сообщений не требуется. Применение этой программы находится в параллельной внешней сортировке слиянием. - person Swiggity Swooty; 04.10.2012

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

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

person dbeer    schedule 03.10.2012