2016-11-23 7 views
0

Я пытаюсь сделать exec() дочерний процесс из родительского процесса. В этом дочернем процессе я прошу пользователя ввести сообщение, чтобы оно могло быть распечатано родительским процессом, но я не могу найти способ сделать это ...Как подключить stdin от дочернего к родительскому?

До сих пор мой код:

parent.c

int main(int argc, char **argv) { 
    int fd[2]; 
    char line[80]; 

    pipe(fd); 

    pid_t pid = (pid_t)fork(); 

    if(pid > 0) { 
     waitpid(pid, NULL, 0); 
     close(fd[0]); 
     int size = read(fd[1], line, 79); 
     close(fd[1]); 
     line[size] = '\0'; 
     printf("[parent] Received \"%s\", size = %d\n", line, size); 
    } 
    else { 
     close(fd[1]); 
     close(stdin); 
     dup2(fd[0], stdin); 
     close(fd[0]); 
     exec("./child", 0, NULL); 
    } 

    return 0; 
} 

child.c

int main(int argc, char **argv) { 
    char line[80]; 

    printf("[child] Enter message: "); 
    gets(line, 80); 
    printf("[child] line = %s\n", line); 

    return 0; 
} 

При запуске родительского процесса , он отображает [child] Enter message:, но когда я пытаюсь ввести что-то, ничего не появляется, даже если я нажимаю клавишу возврата.

Вы знаете, как я могу заставить его работать?

Благодарим за помощь.

+2

В родительском доме не дожидайтесь, пока ребенок закончит, прежде чем читать из трубы. Он может работать в этом случае, потому что вы, вероятно, недостаточно писали, чтобы заполнить буфер труб, но если он будет заполнен, писатель будет блокироваться, и у вас есть тупик. –

+1

Кроме того, какая версия функции 'gets' имеет размер буфера? Вы используете какой-то вариант 'gets_s'? –

+0

Есть также некоторые другие проблемы с вашей родительской программой. Например, он не должен компилироваться чисто. –

ответ

0

Я нашел обходное решение. Моя фактическая цель состояла в том, чтобы передать информацию между родителем и ребенком. Моя ошибка была dup2 на stdin. Делая это, я не мог ничего вводить, когда программа спрашивала. Поэтому я передал значение дескрипторов файла в argv, и моя проблема была решена.

Еще раз спасибо за помощь!

1

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

Это потому, что в процессе ребенка вы говорите, что вход должен поступать от трубы .

Кроме того, в родительском процессе вы пытаетесь выполнить с из письменного конца трубы.

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

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

+0

Благодарим вас за ответ. К сожалению, я не могу переосмыслить дизайн, так как меня попросят сделать это, как я объяснил. Но, может быть, мой подход не очень хорош, и я должен переосмыслить это. Я буду держать вас в курсе! – Dayrona

0

Ваш код имеет несколько проблем:

  • вы смешиваете целое (низкий уровень) дескрипторов файлов и (высокий уровень) FILE * константы.
  • вы меняете стандартный ввод и стандартный вывод, а также порядок дескрипторов, полученных через pipe
  • вы пишете сообщение на стандартный вывод, когда вы собираетесь перенаправить его (используйте STDERR)

Вот фиксированная версия (я изменил ваш отделывается fgets, а также ваш Exec с execl иметь все, чтобы компилировать):

parent.c:

int main(int argc, char **argv) { 
    int fd[2]; 
    char line[80]; 

    pipe(fd); 

    pid_t pid = (pid_t)fork(); 

    if(pid > 0) { 
     waitpid(pid, NULL, 0); 
     close(fd[1]); 
     int size = read(fd[0], line, 79); 
     close(fd[0]); 
     line[size] = '\0'; 
     printf("[parent] Received \"%s\", size = %d\n", line, size); 
    } 
    else { 
     close(fd[0]); 
     close(1); 
     dup2(fd[1], 1); 
     close(fd[1]); 
     execl("./child", NULL); 
    } 

    return 0; 
} 

ребенок.c

int main(int argc, char **argv) { 
    char line[80]; 

    fprintf(stderr, "[child] Enter message: "); 
    fgets(line, 80, stdin); 
    printf("[child] line = %s\n", line); 

    return 0; 
}