2013-07-18 2 views
2

РЕДАКТИРОВАТЬ: Растворпереадрессации дочернего процесса и стандартный вывод для труб

int c1=dup2(pipes[0][1],STDOUT_FILENO); 
int c2=dup2(pipes[1][0],STDIN_FILENO); 


setvbuf(stdout,NULL,_IONBF,0); 

Это SETVBUF установить стандартный вывод, чтобы быть не буфером. Несмотря на то, что я печатал символ новой строки, если пункт назначения не является фактическим экраном, я думаю, он становится буферизированным.



EDIT: Когда я ставлю fflush (стандартный вывод) после LINE 1 и fflush (FOUT) после линии 4 работает, как ожидалось. Тем не менее, он не работает без fflush (stdout) после LINE 1. Проблема в том, что я не смог бы поставить fflush в программу, которую планирую запустить.


Я пытаюсь запустить другую программу из своего процесса. У меня нет доступа к его коду, но я знаю, что он использует stdin и stdout для взаимодействия с пользователем. Я пытаюсь запустить эту программу, создав 2 трубы, разворачивая и перенаправляя дочерний stdin/stdout на соответствующие концы труб. Дело в том, что родитель должен иметь возможность общаться с ребенком через дескрипторы файлов, в то время как его stdin/stdout должен быть неповрежденным. Сценарий POPEN открывает только однонаправленную трубу. Следующий код почти работает.

Есть 4 линии, обозначенные как ЛИНИЯ 1..4.

ЛИНИЯ 1 ребенок посылает к трубе, ЛИНИЯ 2 ребенок получает от трубы, ЛИНИИ 3 родитель посылает к трубе, линии 4 родитель получает от трубы,

Это просто игрушка пример убедитесь, что все работает. Проблема заключается в том, что все 4 линий LINE1..4 являются раскомментированы выходом я вижу на терминале

PARENT1: -1 
FD: 1 0 4 5 0 1 
DEBUG1: 0 
DEBUG2: 0 

В то время как, если ЛИНИЯ 1 и ЛИНИЯ 3 являются раскомментированы только я вижу непрерывный поток данных. То же самое происходит, если только LINE 2 и LINE 4 раскоментированы. Однако мне нужна полная двунаправленная связь. Также добавление комментария SLEEP не изменяет поведение.

Что может быть проблемой здесь. Интересно, почему нет двунаправленного ПОПЕН.

int pid; 
int pipes[2][2]; 

pipe(pipes[0]); 
pipe(pipes[1]); 

pid=fork(); 

if(pid==0) 
    { 
    //usleep(1000000); 
    close(pipes[0][0]); 
    close(pipes[1][1]); 

    int c1=dup2(pipes[0][1],STDOUT_FILENO); 
    int c2=dup2(pipes[1][0],STDIN_FILENO); 
    //int c2=dup2(STDIN_FILENO,pipes[1][0]); 

    fprintf(stderr,"FD: %d %d %d %d %d %d\n",c1,c2,pipes[0][1],pipes[1][0],STDIN_FILENO,STDOUT_FILENO); 

    //FILE*fout=fdopen(pipes[0][1],"w"); 
    //FILE*fin =fdopen(pipes[1][0],"r"); 
    while(1) 
    { 
    static int c1=0; 
    fprintf(stderr,"DEBUG1: %d\n",c1); 
    printf("%d\n",c1);      // LINE 1 
    fprintf(stderr,"DEBUG2: %d\n",c1); 
    scanf("%d",&c1);      // LINE 2 
    fprintf(stderr,"DEBUG3: %d\n",c1); 
    c1++; 
    } 
    //fclose(fout); 
    //fclose(fin); 
    return 0; 
    } 

close(pipes[0][1]); 
close(pipes[1][0]); 

char buffer[100]; 
FILE*fin=fdopen(pipes[0][0],"r"); 
FILE*fout=fdopen(pipes[1][1],"w"); 
while(1) 
    { 
    int c1=-1; 
    printf("PARENT1: %d\n",c1); 
    fscanf(fin,"%d",&c1);       // LINE 3 
    printf("Recv: %d\n",c1); 

    fprintf(fout,"%d\n",c1+1);     // LINE 4 
    printf("PARENT3: %d\n",c1+1); 
    } 
fclose(fin); 
fclose(fout); 
+0

Не стесняйтесь отвечать на свой вопрос! Вместо того, чтобы редактировать исходный вопрос с помощью своего решения, вы должны отправить его в качестве ответа, а затем принять его. –

ответ

1

Ваш код довольно долго, так что я не уверен, что я все понимаю, но почему вы не используете select? Вы хотите перенаправить вывод ребенка в третий процесс или использовать его в своем родительском процессе?

Ниже приведен пример использования cat в дочернем процессе.

#include <unistd.h> 
#include <stdlib.h> 

int  main() 
{ 
    pid_t pid; 
    int p[2]; 


    pipe(p); 
    pid = fork(); 
    if (pid == 0) 
    { 
     dup2(p[1], 1); // redirect the output (STDOUT to the pipe) 
     close(p[0]); 
     execlp("cat", "cat", NULL); 
     exit(EXIT_FAILURE); 
    } 
    else 
    { 
     close(p[1]); 
     fd_set rfds; 
     char  buffer[10] = {0}; 

     while (1) 
     { 
      FD_ZERO(&rfds); 
      FD_SET(p[0], &rfds); 
      select(p[0] + 1, &rfds, NULL, NULL, NULL); //wait for changes on p[0] 
      if(FD_ISSET(p[0], &rfds)) 
      { 
       int  ret = 0; 
       while ((ret = read(p[0], buffer, 10)) > 0) //read on the pipe 
       { 
        write(1, buffer, ret); //display the result 
        memset(buffer, 0, 10); 
       } 
      } 
     } 
    } 
} 
+0

На самом деле я понял решение. SETVBUF устанавливает, чтобы stdout не был буферизирован (хотя я печатал символ новой строки, это место назначения не является фактическим экраном, я думаю, он становится буферизированным. – user1068779

+0

Причина, по которой я делаю это так, заключается в том, что в программе, которую я запускаю, есть цикл PRINT-EVAL, к которому я хочу запрограммировать. – user1068779

+0

@ user1068779 Рад, что вы нашли решение. Вы все еще можете в родительском процессе записать в p [1] ответ – Alexis

Смежные вопросы