C 使用dup2和管道重定向标准输入
我有一个程序a,它从stdin中获取两个参数,并根据参数使用唯一的代码退出。我正在编写一个程序B,它使用fork和exec调用程序a,并让程序B打印出程序a退出时的代码。出于某种原因,程序A似乎没有在fork的子进程中获取我通过管道传送到它的数据。我不确定是否正在将正确的数据传输到子进程 有人能帮我吗?谢谢 这是我的密码: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
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。您最多可以编辑五分钟的评论。