Захват дочернего стандартного буфера в буфер

0

В настоящее время я разрабатываю кросс-платформенный проект. В windows у меня был класс, который запускал процесс/скрипт (используя командную строку), ждал его завершения и прочитал все из него stdout/stderr в буфер. Затем я распечатал вывод на пользовательскую консоль. Примечание. Это не было перенаправление дочернего stdout на родительский stdout, а только на канал от дочернего stdout до родителя.

Я новичок в OSX/unix-подобном api, но я понимаю, что канонический способ сделать что-то вроде этого - это разветвление и совместное использование stdouts. Тем не менее, я не хочу перенаправлять его на stdout, и я хотел бы захватить вывод. Он должен работать примерно так (псевдокод, сходство с функциями unix чисто совпадающее):

class program
{
    string name, cmdline;
    string output;
    program(char * name, char * cmdline)
        : name(name), cmdline(cmdline) {};

    int run()
    {
        // run program - spawn it as a new process
        int pid = exec(name, cmdline);
        // wait for it to finish
        wait(pid);
        char buf[size];
        int n;
        // read output of program stdout
        // keep appending data until there nothing left to read
        while (read(pid, buf, size, &n))
            output.append(buf, n);
        // return exit code of process
        return getexitcode(pid);
    }

    const string & getOutput() { return output;  }
};

Как я буду делать это на OSX?

E:

Хорошо, поэтому я изучил соответствующий api, и кажется, что какая-то комбинация fork/exec неизбежна. Проблема в том, что мой процесс очень велик, и нарисовать его действительно кажется плохой идеей (я вижу, что некоторые реализации unix не могут этого сделать, если родительский процесс занимает 50% + системного бара).

Разве я не могу избежать этой схемы? Я вижу, что vfork() может быть потенциальным соперником, поэтому, возможно, я попытаюсь имитировать функцию popen() с помощью vfork. Но опять же, на большинстве страниц man указано, что vfork вполне может быть просто fork()

  • 0
    Возможно, следовало бы отметить, что это был только псевдокод. exec должен выполнять командную строку.
Теги:
stdout
fork
child-process

1 ответ

0
Лучший ответ

У вас есть вызов библиотеки, чтобы сделать это: popen. Он предоставит вам возвращаемое значение дескриптора файла, и вы сможете прочитать этот дескриптор до eof. Это часть stdio, поэтому вы можете сделать это на OSX, но и на других системах. Просто запомните pclose() дескриптор.

 #include <stdio.h>

     FILE *     popen(const char *command, const char *mode);

     int    pclose(FILE *stream);

если вы хотите сохранить выход без переадресации, единственное, что мы можем подумать, это использовать что-то вроде "tee" - команды, которая разбивает вывод на файл, но сохраняет свой собственный stdout. Это довольно легко реализовать и в коде, но в этом случае это может и не понадобиться.

  • 0
    Это выглядит идеально. Два вопроса, когда я достигаю EOF, я полагаю, что сигналы прекращаются? Во-вторых, на man-страницах linux утверждается, что это обертка вокруг fork - окажет ли это огромное влияние на производительность (как, например, мой код находится в динамической библиотеке внутри огромного процесса?)
  • 0
    Чтобы создать процесс в системе UNIX, вы должны использовать fork () / execv () (или posix_spawn в OS X, почти то же самое). Но это не окажет слишком большого влияния на производительность, если вы не будете использовать это многократно десятки раз. Что касается EOF, то yes - pclose () также будет ожидать окончания процесса и вернет свое возвращаемое значение (то есть то, с чем он завершил работу ()).
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню