将管道作为exec中的参数传递

时间:2011-03-04 03:56:50

标签: c exec fork pipe

我正在尝试将管道传递给另一个使用execv创建的进程。到目前为止,这是我的代码,但它不起作用。我到处寻找信息,但我找不到任何具体的关于通过管道vie exec。任何帮助表示赞赏。感谢

int fd[2];
pipe(fd);

char passwrite[1];
sprintf(passwrite, "%d", fd[0]);

char arg[1];
arg[1]=passwrite;

int x;
x=fork();
if (x==0) {
execv("NewProg",arg);
}

4 个答案:

答案 0 :(得分:6)

管道是单向连接,通常最终位于由共同祖先关联的两个进程之间,通常是要创建的两个进程中的第一个,除非它是shell,在这种情况下shell创建管道并且有两个使用烟斗的孩子。管道有一个写入端,由一个过程使用;它具有另一个使用的读取结束。通常最简单的方法是将一个过程的标准输出连接到另一个过程的标准输入。使用文件描述符而不是标准I / O文件流也是最简单的。

操作顺序为:

  1. 调用pipe()创建管道。
  2. 致电fork()创建一个孩子。
  3. 子进程(从fork()返回值0)执行:
    • close()管道的写入结束
    • dup2()管道的读取端到标准输入
    • close()管道的读取结束
    • execve()将从管道读取的子进程(其标准输入)
  4. 父进程(来自fork()的返回值> 0)执行:
    • close()管道的读取结束
    • dup2()管道的写入端到标准输出。
    • close()管道的写入结束
    • execve()将写入管道的进程(标准输出)
  5. 请注意,在这种情况下,您最终会关闭pipe()调用返回的文件描述符,并关闭它们两次(一次在父级中,一次在子级中)。

    如果父进程应该通过文件流写入子进程,请在写文件描述符上使用fdopen()调用(不要在其上使用dup2(),或close()它 - 您在fclose()返回的文件流上使用fdopen()关闭它,或者退出)。

    如果你想告诉子进程它可以读取哪个文件描述符号来从管道获取输入,那么你不需要在子进程中执行dup2();你可以简单地格式化一个字符数组中的字符串(复数 - 你至少需要字符,并且应该允许十几个,因为它非常便宜),然后你可以安排将参数传递给{{1功能。请记住,孩子至少需要三个指针:一个用于argv [0],程序名称;一个用于文件描述符号;和一个用于终止空指针。这就是execve()知道何时到达参数列表的结尾。如果您仅使用execve(),则同样的评论适用;你只是无法确定孩子的环境(例如,它收到的环境变量列表);它只会获得父进程在execv()时的相同环境。

    ¶3和¶4各自的第一步是关键步骤。如果省略它们,管道将无法正常工作。

答案 1 :(得分:1)

您的代码存在一些潜在问题,甚至在您进行管道处理之前(请参阅Jonathan Leffler's answer)。首先,您需要一个更大的缓冲区,因为单个字符不足以容纳整数终止NUL:

char passwrite[10];

然后,arg需要是一个指针数组,而不是一个字符数组,它还需要更大:

char *arg[3];

你需要在args中添加特定内容:

arg[0] = "NewProg"; // name of program
arg[1] = passwrite;
arg[2] = NULL;

我系统上execv的手册页更详细地解释了这一点:

  

execl(),execlp()和execle()函数中的const char * arg和后续省略号可以被认为是arg0,arg1,...,argn。它们一起描述了一个或多个指向以null结尾的字符串的指针的列表,这些字符串表示执行程序可用的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。参数列表必须以NULL指针终止,并且由于这些是可变参数函数,因此必须将此指针强制转换为(char *)NULL。

答案 2 :(得分:1)

man pipe

在这里您可以找到使用管道的示例

答案 3 :(得分:0)

您需要使用dup()系统调用才能实现此目的。此外,您还需要根据需要更改父级和子级的STDIN,STDOUT。这是我创建的Unix Shell的摘录

void pipe() {int z;
int w=fork();

 if(w==0)
 {    
     int pfd[2];
     pipe(pfd[2]);
     z=fork();
     if(z==0)
     {
         close(pfd[0]);
         close(1);
         dup(pfd[1]);
         close(pfd[1]);
         execlp(token[0],token[0],NULL);
     }
     else
         {
               close(pfd[1]);
               close(0);
               dup(pfd[0]);
               close(pfd[0]);
               execlp(token[2],token[2],NULL);
         }     
  }
  else
       wait();

}

在上面的代码中,你需要替换token [0],token [2]和token [1],它们是你想要运行的命令的字符串指针(在我的shell中)的元素。我已经完成了解析因此,我的shell中的coomand行必须使用Token [0/1/2]来获取各种命令行参数。但是你可以用它们代替它来完成这项工作