dup2: write() перенаправляется, но не fprintf() или puts()

Я пытаюсь прочитать STDOUT дочернего процесса.

Вот функция fork (да, С++).

bool ForkAvecBus::start() {
    child_pid = fork();

    if(child_pid == -1)
        return true;

    if(child_pid == 0) {
        /* Child process closes up input side of pipe */
        close(child_stdin[WRITE]);
        dup2 (child_stdin[READ], STDIN_FILENO);

        close(child_stdout[READ]);
        dup2 (child_stdout[WRITE], STDOUT_FILENO);
        close(child_stdout[WRITE]);

        execl("/bin/sh", "/bin/sh", "-c", ExecName.c_str(), NULL);
        exit(0);

    } else {
        /* Parent process closes up output side of pipe */
        close(child_stdin[READ]);
        close(child_stdout[WRITE]);

        signal(SIGTERM,exit_on_parent_quit);
    }
}

Вот (простой) тест в дочернем процессе:

int main() {
    fprintf(stdout, "fromFprintf\n", 12);
    puts("auieauie");
    write(STDOUT_FILENO, "fromWrite", 9);
}

А вот и метод чтения:

void ForkAvecBus::readFromChild() {
    FILE* fp = fdopen(child_stdout[READ], "r");
    // Tests
    int bytes_read = -1;
    char readbuffer[1000];
    while (1) {
        //char c=getc(fp);
        //std::cout << "From child: <<" << c << ">>" << std::endl;

        bytes_read = read(child_stdout[READ], readbuffer, 999);
        if (bytes_read <= 0)
            break;
        readbuffer[bytes_read] = '\0';
        std::cout << "From child: <<" << readbuffer << ">>" << std::endl;
    }
}

Как видите, я тоже пробовал getc(). И все, что я получаю, это:

From child: <<fromWrite>>

Почему fprintf (и printf) и puts не перенаправляются?


person Salamandar    schedule 24.04.2016    source источник
comment
Вы уверены, что это работает execl("/bin/sh", "/bin/sh", "-c", ExecName.c_str(), NULL); - Почему бы не заглушить несколько pritnf, прежде чем проверить, что проводка в порядке?   -  person Ed Heal    schedule 24.04.2016
comment
stackoverflow.com/questions/25516375/   -  person stark    schedule 24.04.2016
comment
Разве это не проблема с буферизацией? Как насчет того, чтобы поиграться с setvbuf или fflush?   -  person alagner    schedule 24.04.2016
comment
@EdHeal, да, я полностью уверен, что это работает, используя fprintf (stderr);)   -  person Salamandar    schedule 24.04.2016


Ответы (1)


Поведение, которое вы здесь наблюдаете, вероятно, связано с буфером. Так как write(STDOUT_FILENO,...) обходит буфер времени выполнения, поэтому он напрямую достигает канала. Два других буферизуются внутри среды выполнения.

Разница между puts, fprintf(stdout,...) и write(STDOUT_FILENO,...) объясняется в этом сообщении: Разница между stdout и STDOUT_FILENO в LINUX C

Просто вызовите fflush в конце вашей дочерней программы.

Чтобы проверить теорию:

#include<cstdio>
#include<unistd.h>
int main() {
  fprintf(stdout, "fromFprintf\n", 12);
  puts("auieauie");
  write(STDOUT_FILENO, "fromWrite", 9);
  return 0;
}

Программа печатает:

fromWritefromFprintf
auieauie

Смотрите порядок не то, что вы ожидаете. Мое предложение: не пропустите STDOUT_FILENO и stdout в своей программе. Придерживайтесь одного из них и не забудьте позвонить fflush.

person gdlmx    schedule 24.04.2016