我正在尝试使用管道和叉子在c中使用这样的东西: 回声“像10 + 10的操作”| BC
确切地说,我试图创建2个管道,一个用于服务器将写入操作并且bc将读取,另一个用于操作的结果(通过bc),服务器将读取并打印它。为此,我正在更改父进程和子进程的输出和输入。
这是我的代码:
int main(){
int t1, t2;
char resultat[5];
int pipe1[2];
int pipe2[2];
pipe(pipe1);
pipe(pipe2);
int resultat_fork = fork();
if(resultat_fork == -1){
exit(EXIT_FAILURE);
}
if(resultat_fork!=0){
printf("I am the parent\n");
close(pipe1[0]);
close(pipe2[1]);
//We only want to write into pipe1 and read from pipe2, we can close the two other
write(pipe1[1], "20*5\n", 20);
//write on pipe1 the expression
read(pipe2[0], resultat, sizeof(resultat));
//read from pipe2 the answer (written by bc)
printf("resultat : %s\n",resultat);
close(pipe1[1]);
close(pipe2[0]);
}else{
printf("I am the children\n");
close(pipe1[1]);
close(pipe2[0]);
//We only want to write into pipe2 and read from pipe1, we can close the two other
dup2(pipe1[0], 0);
//redirection standard input to pipe1[0]
dup2(pipe2[1], 1);
//redirection standard output to pipe2[1]
execlp("bc", "bc", NULL);
//execute bc, which normaly will read the operation from pipe1 and write the answer into pipe2, but I think it's here the problem come out
close(pipe1[0]);
close(pipe2[1]);
}
return 0;
}
我得到了正确答案,但错误: “(standard_in)2:非法字符:^ @” “(standard_in)2:非法字符:” 加上我必须按CTRL C退出。 我猜它来自BC,但为什么......
我做错了什么?谢谢! 我已经看过很少例,但只扔了一根烟斗。
答案 0 :(得分:1)
这很有效。请注意它如何指定要写入的数据的大小,以及它如何检查写入和读取,以及它如何关闭文件描述符。 (请记住:sizeof("string literal")
计算空字节,与strlen()
不同。它也是编译时常量。但是,更通用的代码会在当前表达式字符串上使用strlen()
。)
经验法则:如果您使用dup2()
将管道文件描述符复制到标准输入或标准输出,请关闭 两者 管道末端。
如果您使用dup()
或fcntl()
代替F_DUPFD
或F_DUPFD_CLOEXEC
,这也适用。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
char resultat[5];
int pipe1[2];
int pipe2[2];
pipe(pipe1);
pipe(pipe2);
int resultat_fork = fork();
if (resultat_fork == -1)
{
exit(EXIT_FAILURE);
}
if (resultat_fork != 0)
{
printf("I am the parent\n");
close(pipe1[0]);
close(pipe2[1]);
if (write(pipe1[1], "20*5\n", sizeof("20*5\n") - 1) != sizeof("20*5\n") - 1)
fprintf(stderr, "write to child failed\n");
int nbytes = read(pipe2[0], resultat, sizeof(resultat));
if (nbytes <= 0)
fprintf(stderr, "read from child failed\n");
else
printf("resultat: [%.*s]\n", nbytes, resultat);
close(pipe1[1]);
close(pipe2[0]);
}
else
{
printf("I am the child\n");
close(pipe1[1]);
close(pipe2[0]);
dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
close(pipe1[0]); /* More closes! */
close(pipe2[1]); /* More closes! */
execlp("bc", "bc", NULL);
fprintf(stderr, "Failed to execute bc\n");
exit(EXIT_FAILURE);
}
return 0;
}
仍然有改进错误处理的空间;在报告了一些错误后,代码会继续播放,这可能不是最好的行为。
输出:
I am the parent
I am the child
resultat: [100
]
(注意:如果您将程序的输出传送到某处,则看不到I am the child
消息。出于原因,请参阅printf()
anomaly after fork()
。)