2015-04-23 128 views
0

你好stackoverflow我試圖創建一個程序,執行一個兒子shell進程並將其I/O重定向到一個管道以便與他的父進程進行通信。子shell進程雙向重定向到父進程

我可以通過寫入管道(wpipefd)執行命令,但是我無法從讀取管道(rpipefd)上的shell進程獲得響應。

到目前爲止,根據Strace,我有3個錯誤:首先,讀取功能阻止了程序,所以我使讀取管道的讀取fd非阻塞(rpipe[0])。然後我有一個EAGAIN錯誤與讀取功能......最後,當我在使用dup2()後,在分叉進程中關閉從rpipe(close(rpipefd[0]))讀取的fd時發生EPIPE錯誤。

我不明白我做錯了什麼。這是我到目前爲止所做的:

#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

主要問題並不來自代碼本身:傳遞給shell的命令不完整,你錯過了最後的'\ n',因此子進程(你的shell)正在等待命令的其餘部分。

無阻塞的部分是不是一個好主意(或者至少,你應該不停地旋轉,你管,以便檢索它的內容。)

一旦你與你的命令做,你應該關閉輸出管道,以便shell在其輸入上獲取文件結尾。其他註釋:您應該等待子終止(使用wait(2)),您應該在您的execl之後離開子進程(與錯誤消息的err(3)一起使用)以處理exec錯誤。嚴重的是,在字符串文字上調用strlen?我知道,GCC在編譯時替換它,但是......

這裏是你的代碼的修改版本:

#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

不客氣。 –

相關問題