【问题标题】:Child shell process bidirectional redirection to parent process子shell进程双向重定向到父进程
【发布时间】:2015-04-23 13:07:09
【问题描述】:

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

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

根据 Strace 到目前为止我有 3 个错误:首先,读取函数阻塞了程序,所以我将读取管道的读取 fd 设为非阻塞(rpipe[0])。然后我的 read 函数出现 EAGAIN 错误...最后,当我在使用 dup2() 之后在分叉进程中关闭来自 rpipe (close(rpipefd[0])) 的 read 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);
}

请帮忙!

【问题讨论】:

    标签: c linux shell redirect pipe


    【解决方案1】:

    主要问题不在于代码本身:传递给 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;
     }
    

    【讨论】:

      猜你喜欢
      • 2020-09-01
      • 2011-11-16
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      相关资源
      最近更新 更多