Запись в трубу или трубы - PullRequest
3 голосов
/ 30 октября 2011

Каков наилучший способ сделать это теоретически? Мне нужно разрешить пользователю вводить число процессов для отправки в канал, например, «3», и, когда он проходит через три [три, что?] на каждой итерации, мне нужно создать процесс, отправить это [что?] в трубу и распечатать его.

В следующий раз, когда пользователь введет другое число, скажем «4», он должен напечатать предыдущие 3 + 1 ... Я работаю над этим, но не могу понять, как это сделать. Вот мой код Мне просто нужно руководство, не нужно пытаться решить его для меня (но предложения будут высоко оценены).

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

1 Ответ

0 голосов
/ 30 октября 2011

Предложение № 1: Используйте функции

Используйте функции даже для небольших работ, таких как:

void create_fifo(const char *name)
{
    /* Create the first named - pipe */
    int ret_val = mkfifo(name, 0666);

    if ((ret_val == -1) && (errno != EEXIST))
    {
        perror("Error creating the named pipe");
        exit(1);
    } 
}

Теперь вы можете просто написать в своей основной программе:

create_fifo(PIPE1);
create_fifo(PIPE5);

Это сокращает беспорядок в вашей основной программе. Он также придерживается гибкого принципа СУХОЙ - не повторяйся.

Предложение № 2: Ошибка проверки системных вызовов.

Вы сделали это для создания FIFO, и это хорошо. Вы не для звонков open() или read() или write(). Вы, вероятно, должны. Я использую функцию, аналогичную следующей в моих программах:

#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

static const char *arg0 = "did not call err_setarg0(argv[0])";

void err_setarg0(const char *argv0)
{
    arg0 = argv0;
}

void err_exit(const char *fmt, ...)
{
    int errnum = errno;   /* Capture errno before it is changed */
    va_lists args;
    fprintf(stderr, "%s: ", arg0);
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
    exit(1);
}

Затем вы можете использовать:

if ((rdfd1 = open(PIPE1, O_RDONLY)) < 0)
    err_exit("Failed to open FIFO %s for reading: ", PIPE1);
if ((wrfd1 = open(PIPE5, O_WRONLY)) < 0)
    err_exit("Failed to open FIFO %s for writing: ", PIPE5);

Предложение № 3: Сделать итеративный сервер

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

Предложение № 4: Возможно, серверу нужны имена каналов в качестве аргументов

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

Действительно, необходимость генерирования имен ставит под сомнение весь дизайн - вы уверены, что использование FIFO - лучший способ сделать это? Для меня это похоже на случай, когда анонимные каналы будут вам полезнее; вам не нужно было бы придумывать имена, а сервер просто считывал данные со своего стандартного ввода и записывал (модифицированные?) данные в стандартный вывод, так что вы могли бы просто использовать cat или tr или sed или ... как ваш сервер.

Очевидно, что если вы используете каналы, вам нужно будет сделать некоторые аккуратные сантехнические работы, но вам также нужно сделать осторожные сантехнические работы с парами FIFO на сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...