2014-04-12 4 views
2

я столкнулся неприятная проблема:Posix C Piping Задержка

Пусть я одна программы, давайте называть его HelloProgram, какой код очень прост:

void print_bullshit() { 
int i; 
for (i = 0; i < 10; ++i) { 
    printf("hello!"); 
    sleep(3); 
} 
printf("bye!"); 
} 

И у меня есть другая программа, давай назовем его редиректор , что код немного сложнее:

#define READ_END 0 
#define WRITE_END 1 

int pipe_fd[2]; 
void child_proc(const char* prg_name) { 
close(pipe_fd[READ_END]); 

dup2(pipe_fd[WRITE_END], STDOUT_FILENO)); 
execl("/bin/sh", "sh", "-c", prg_name, NULL); 
//error 
exit(1); 
} 

void parent_proc() { 
close(pipe_fd[WRITE_END]); 
char buffer[256]; 
while (read(pipe_fd[READ_END], buffer, sizeof(buffer)) > 0) { 
    printf(buffer); 
} 

wait(NULL); 
} 

int main(int argc, const char* argv[]) { 
pipe(pipe_fd); 
pid_t chpid = fork(); 
if (chpid != 0) { 
    parent_proc(); 
} else { 
    child_proc(argv[1]); 
} 

return 0; 
} 

Некоторые ошибки провер не указаны там, это сделать код более простым. Я до сих пор не могу понять эту вещь:

Когда Redirector используется с HelloProgram для перенаправления вывода, весь текст «Hello» отображается на экране консоли только после 3 * 10 (== количество итераций) = = 30 секунд,

Какое черт это? Я предположил, что это будет какая-то параллель, поэтому я получаю каждую строку «Hello», отображаемую на консоли через каждые 3 секунды.

Помогите мне, пожалуйста.

+1

Если вы хотите, чтобы вывод отображался, завершите строку символом новой строки. В противном случае он будет находиться в ожидании до тех пор, пока вы не будете 'fflush()' или 'fclose()' stream, или вы печатаете новую строку. После использования 'dup2()' для создания стандартного вывода вам также необходимо закрыть дескриптор файла pipe. –

ответ

3

Если вы хотите, чтобы вывод в HelloProgram появляться своевременно, вы должны либо включать в себя символ новой строки в конце каждого printf(), или использовать fflush(), чтобы заставить его. Если вывод с HelloProgram идет к терминалу, то новые строки являются достаточными; если он идет к трубе, вам нужно fflush().

Следовательно:

void print_bullshit(void) 
{ 
    int i; 
    for (i = 0; i < 10; ++i) 
    { 
     printf("hello!\n"); 
     fflush(stdout); 
     sleep(3); 
    } 
    printf("bye!\n"); 
    fflush(stdout); 
} 

Это будет посылать материал в стандартный вывод, как своевременно, насколько это возможно.

В вашей другой код, у вас есть:

void child_proc(const char* prg_name) 
{ 
    close(pipe_fd[READ_END]); 
    dup2(pipe_fd[WRITE_END], STDOUT_FILENO)); 
    execl("/bin/sh", "sh", "-c", prg_name, NULL); 
    //error 
    exit(1); 
} 

Вам нужно, в общем, добавить:

close(pipe_fd[WRITE_END]); 

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