子shell进程双向重定向到父进程

时间:2015-04-23 13:07:10

标签: c linux shell redirect pipe

Hello stackoverflow我试图创建一个程序,它执行一个子shell进程并将他的I / O重定向到一个管道,以便与他的父进程通信。

我可以通过写管道(wpipefd)执行命令,但我无法从读取管道(rpipefd)上的shell进程获得响应。

根据Strace,我到目前为止有3个错误:首先,read函数阻止了程序,因此我将读取管道的读取fd设为非阻塞(rpipe[0])。然后我的读取函数出现了EAGAIN错误...最后,当我在使用close(rpipefd[0])之后在分叉进程中关闭来自rpipe(dup2())的读取fd时,出现了EPIPE错误。 / p>

我不明白我做错了什么。这是我到目前为止所做的:

#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);
}

请帮忙!

1 个答案:

答案 0 :(得分:0)

主要问题不是来自代码本身:传递给shell的命令是不完整的,你错过了最终的&#39; \ n&#39;因此子进程(你的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;
 }