2015-04-23 1 views
0

Привет, stackoverflow Я попытался создать программу, которая выполняет процесс оболочки сына и перенаправляет его ввод-вывод в канал, чтобы общаться с его отцом.Преобразование двунаправленного процесса дочерней оболочки в родительский процесс

Я могу выполнить команду через трубу записи (wpipefd), но я не могу получить ответ от процесса оболочки на канале чтения (rpipefd).

У меня было 3 ошибки до сих пор в соответствии со Strace: сначала функция чтения блокировала программу, поэтому я сделал чтение fd канала чтения без блокировки (rpipe[0]). Тогда у меня была ошибка EAGAIN с функцией чтения ... Наконец, я получил ошибку EPIPE, когда я закрыл read fd из rpipe (close(rpipefd[0])) в разветвленном процессе сразу после использования dup2().

Я не понимаю, что я сделал не так. Вот что я сделал до сих пор:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <unistd.h> 
#include <fcntl.h> 
#define BUF_SIZE 1024 

int main(int argc, char **argv) 
{ 
    int rpipefd[2], wpipefd[2], pid; 
    pipe(rpipefd); 
    pipe(wpipefd); 
    char buffer[BUF_SIZE] = {0}; 

    int flags = fcntl(rpipefd[0], F_GETFL, 0); 
    fcntl(rpipefd[0], F_SETFL, flags | O_NONBLOCK); 

    pid = fork(); 
    if(pid == 0) 
    { 
     close(rpipefd[0]); 
     dup2(rpipefd[1],1); 
     dup2(rpipefd[1],2); 
     close(wpipefd[1]); 
     dup2(wpipefd[0],0); 
     close(rpipefd[1]); 
     close(wpipefd[0]); 
     execl("/bin/sh","/bin/sh",NULL); 
    } 
    close(wpipefd[0]); 
    write(wpipefd[1],"echo helloWorld",strlen("echo helloWorld")); 
    close(rpipefd[1]); 
    read(rpipefd[0],buffer,BUF_SIZE);  
    //perror("read()"); 
    printf("%s",buffer); 


    exit(0); 
} 

Помогите!

ответ

0

Основная проблема исходит не от самого кода: команда, переданная в оболочку, является неполной, вы пропустили окончательный «\ n», и, таким образом, дочерний процесс (ваша оболочка) ожидает остальную команду ,

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

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

Другие замечания: вы должны дождаться окончания дочернего процесса (с использованием wait (2)), вы должны выйти после выполнения execl в дочернем процессе (используйте с ошибкой (3) для сообщения об ошибке) для обработки ошибок exec. И, серьезно, вызывая strlen на строковом литерале? Я знаю, что НКУ заменяет его во время компиляции, но ...

Вот модифицированная версия кода:

#include <err.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#define BUF_SIZE 1024 

int main(int argc, char **argv) 
{ 
     int rpipefd[2], wpipefd[2], pid; 
     pipe(rpipefd); 
     pipe(wpipefd); 
     char buffer[BUF_SIZE] = {0}; 

     pid = fork(); 
     if(pid == 0) 
     { 
       close(rpipefd[0]); 
       dup2(rpipefd[1],STDOUT_FILENO); 
       dup2(rpipefd[1],STDERR_FILENO); 
       close(wpipefd[1]); 
       dup2(wpipefd[0],STDIN_FILENO); 
       close(rpipefd[1]); 
       close(wpipefd[0]); 
       execl("/bin/sh","/bin/sh",NULL); 
       err(1, "execl()"); 
     } 
     close(wpipefd[0]); 
     close(rpipefd[1]); 
     write(wpipefd[1], "echo helloWorld\n", 16); 
     close(wpipefd[1]); // we're done, say it to the shell 
     int r; 
     while ((r = read(rpipefd[0],buffer,BUF_SIZE))) 
     { 
       if (r == -1) 
       { 
         if (errno == EAGAIN || errno == EINTR) continue; 
         err(1, "read()"); 
       } 
       write(STDOUT_FILENO, buffer, r); 
     } 
     wait(NULL); 
     return 0; 
} 
+0

Это очень хорошая работа, спасибо !! – user3046275

+0

Добро пожаловать. –

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