C 使用dup2和管道重定向标准输入

C 使用dup2和管道重定向标准输入,c,pipe,exec,dup2,C,Pipe,Exec,Dup2,我有一个程序a,它从stdin中获取两个参数,并根据参数使用唯一的代码退出。我正在编写一个程序B,它使用fork和exec调用程序a,并让程序B打印出程序a退出时的代码。出于某种原因,程序A似乎没有在fork的子进程中获取我通过管道传送到它的数据。我不确定是否正在将正确的数据传输到子进程 有人能帮我吗?谢谢 这是我的密码: int program_B(void) { char var_a[256]; char var_b[256]; int fd[2]; // Read from stdin

我有一个程序a,它从stdin中获取两个参数,并根据参数使用唯一的代码退出。我正在编写一个程序B,它使用fork和exec调用程序a,并让程序B打印出程序a退出时的代码。出于某种原因,程序A似乎没有在fork的子进程中获取我通过管道传送到它的数据。我不确定是否正在将正确的数据传输到子进程

有人能帮我吗?谢谢

这是我的密码:

int program_B(void) {
char var_a[256];
char var_b[256];
int fd[2];

 // Read from stdin 
char *sendarray[2];
sendarray[0] = var_a;
sendarray[1] = var_b;


if(fgets(var_a, MAXLINE, stdin) == NULL) {
    perror("fgets");
    exit(1);
}

if(fgets(var_b, MAXLINE, stdin) == NULL) {
    perror("fgets");
    exit(1);
}

if (pipe(fd) == -1) {
  perror("pipe");
  exit(1);
}

int pid = fork();

// Child process -- error seems to be here. 
if (pid == 0) {

    close(fd[1]);

    dup2(fd[0], fileno(stdin));

    close(fd[0]);

    execl("program_A", NULL);

    perror("exec"); 
    exit(1);

} else {

    close(fd[0]);
    write(fd[1], sendarray, 2*sizeof(char*));
    close (fd[1]);

    int status; 

      if (wait(&status) != -1) {

        if (WIFEXITED(status)) {


            printf("%d\n", WEXITSTATUS(status));


        } else {
          perror("wait");
          exit(1);
        }
      }


}







return 0;
}

您将错误的数据传输到子进程

我假设
var_a
var_b
是要发送到程序a的字符串。它们都是字符数组类型,在C中,这与指向字符的指针是相同的(实际上指针和数组之间有一点区别,但这与这个问题无关). 所以它们实际上只是指向每个参数的第一个字节的指针
sendarray
,但是它是一个字符指针的数组,与指向字符指针的指针相同。请记住这一点

调用
write()
时,第二个参数告诉它数据在内存中的位置。通过传递
sendarray
,write认为该
sendarray
指向您要写入的数据,尽管它实际上指向另一个指针。因此,发生的情况是
var_a
var_b
(这是
sendarray
指向的)的指针值被写入管道

因此,您必须将
var_a
var_b
传递到
write()
,因为这些是指向您要发送的实际数据的指针。您还必须知道此数据的长度(字节数)。如果
var_a
var_b
指向以null结尾的字符串,则可以使用
strlen()
确定它们的长度

最后一件事:我不知道程序A是如何从连续字节流(如
stdin
)中获得2个参数的,但假设它逐行读取,显然也必须从程序B发送一个新行字符

因此,将所有这些放在一起,您的书面陈述应该如下所示:

write(fd[1], var_a, strlen(var_a));
write(fd[1], "\n", 1);
write(fd[1], var_b, strlen(var_b));

当然,如果我所做的任何假设是错误的,您必须适当地采用此代码。

请注意,通常不告诉程序它的名称。您的
execl()
行应该是
execl(“program_A”,“program_A”,“char*)NULL)。第一个参数是要执行的文件的路径名(当前目录中的
programA
),第二个参数是已执行程序的
argv[0]
中的值。请注意,没有任何东西可以阻止您使用
execl(“progam_A”,“假想用词不当”,“char*)NULL)
给它一个与路径名无关的
argv[0]
值。可能不需要换行符,因为
fgets()
调用会在输入数据中保留换行符(可能)。在输入行的中间,有过多的行等注意事项和空字节,以及可能被忽略的各种其他可能的故障。<代码> FGETSH()/代码>从输入中读取一行,还将结果中的新行字符存储在BTW中。所有C函数都有手册页,其中详细说明了类似的内容。在终端或谷歌中键入
man 3 FGET
,以查看它们您的代码向程序发送三行代码;我的印象是它只需要两行。因此,不需要中间的
write()
。这并不十分清楚(“一个从stdin获取两个参数的程序a”并没有使用正常的术语;它们是输入行而不是命令行参数),但是如果你很快的话……goolge-->Google。您最多可以编辑五分钟的评论。