简体   繁体   English

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

[英]Child shell process bidirectional redirection to parent process

Hello stackoverflow I tried to create a program which execute a son shell process and redirect his I/O to a pipe in order to communicate with his father process. 您好stackoverflow我试图创建一个程序,该程序执行子外壳程序进程并将其I / O重定向到管道,以便与其父进程进行通信。

I can execute command via the write pipe (wpipefd) but I can't get the response from the shell process on the read pipe (rpipefd). 我可以通过写入管道(wpipefd)执行命令,但无法从读取管道(rpipefd)上的shell进程中获得响应。

I had 3 errors so far according to Strace : First the read function was blocking the program so I made ​​the read fd of the reading pipe non-blocking ( rpipe[0] ). 根据Strace到目前为止,我有3个错误:首先,read函数正在阻塞程序,因此我将读取管道的read fd设置为非阻塞( rpipe[0] )。 Then I had an EAGAIN error with the read function... Finally I got an EPIPE error when I close the read fd from rpipe ( close(rpipefd[0]) ) in the forked process just after the use of dup2() . 然后,我的读取函数出现了EAGAIN错误...最后,在使用dup2()之后,在派生进程中关闭了从rpipe( close(rpipefd[0]) )读取的fd时,我遇到了EPIPE错误。

I don't understand what I did wrong. 我不明白我做错了什么。 Here's what I did so far : 这是我到目前为止所做的:

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

Please help ! 请帮忙 !

The main issue doesn't come from the code itself: the command passed to the shell is incomplete, you missed the final '\\n' and thus the child process (your shell) is waiting for the rest of the command. 主要问题不在于代码本身:传递给shell的命令不完整,您错过了最后的'\\ n',因此子进程(您的shell)正在等待命令的其余部分。

The non-blocking part is not a good idea (or at least, you should spin around you pipe in order to retrieve its content.) 非阻塞部分不是一个好主意(或者至少,您应该在管道周围旋转以检索其内容。)

Once you're done with your command, you should close the output pipe so the shell get the end-of-file on its input. 完成命令后,应关闭输出管道,以便外壳程序在其输入中获取文件结尾。

Other remarks: you should wait for the child termination (using wait(2)), you should leave after your execl in the child process (use with err(3) for the error message) to handle exec errors. 其他说明:您应该等待子进程终止(使用wait(2)),您应该在execl之后退出子进程(与err(3)一起使用以显示错误消息)以处理exec错误。 And, seriously, calling strlen on string literal ? 而且,认真地,在字符串文字上调用strlen吗? I know that gcc is replacing it at compile time, but … 我知道gcc在编译时会替换它,但是…

Here is a modified version of your code: 这是您的代码的修改后的版本:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM