通过管道和叉子使用 bc
Using bc through pipes and fork
我正在尝试通过管道使用 bc 获取 char 表达式的答案。
我想先在 pipe1 中写入表达式,bc 将在 pipe2 中读取和写入答案。为此,我正在更改输入和输出。如果我不使用 char[] 而只是将表达式放在 write :
中,这确实有效
write(pipe1[1], "20*5\n", sizeof("20*5\n")-1) != sizeof("20*5\n")-1)
但是如果我声明一个选项卡,我会不断收到错误消息:
(standard_in) 2: illegal character: ^@
有时是1而不是2
我做错了什么?如果有人能解释一下,谢谢。
代码:
#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);
}
char* expression = "20*5\n";
if (resultat_fork != 0)
{
//printf("I am the parent\n");
close(pipe1[0]);
close(pipe2[1]);
if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))
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;
}
^@
是 nul 字符,即 '[=12=]'
。这表明您在将字符串写入 bc
时超出了字符串的末尾。问题在这里:
sizeof(expression)
expression
不是数组,它是一个 char
指针,指向字符串 "20*5\n"
的第一个字符,如果您使用的是 64 位计算机,它的大小为 8。要获取要发送的字符串的长度,请改用 strlen(expression)
。
另一件与您的问题无关的事情是,在父进程中,在您阅读答案后,wait 让子进程完成。否则,你将只剩下一个僵尸。
这是错误的
if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))
您正在使用 sizeof
运算符和 expression
,这是一个 char*
,如果您的系统是 32 位,它将导致 4
,这是代码中任何指针变量的大小。
您需要使用 strlen(expression)
而不是 sizeof
。
正如答案中所指出的,如果父进程有多个子进程,则需要等待子进程完成执行并终止。理想情况下,您还应该检查 wait
的 return 值,这为您提供了有关子进程如何终止的更多上下文。
我正在尝试通过管道使用 bc 获取 char 表达式的答案。 我想先在 pipe1 中写入表达式,bc 将在 pipe2 中读取和写入答案。为此,我正在更改输入和输出。如果我不使用 char[] 而只是将表达式放在 write :
中,这确实有效write(pipe1[1], "20*5\n", sizeof("20*5\n")-1) != sizeof("20*5\n")-1)
但是如果我声明一个选项卡,我会不断收到错误消息:
(standard_in) 2: illegal character: ^@
有时是1而不是2
我做错了什么?如果有人能解释一下,谢谢。
代码:
#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);
}
char* expression = "20*5\n";
if (resultat_fork != 0)
{
//printf("I am the parent\n");
close(pipe1[0]);
close(pipe2[1]);
if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))
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;
}
^@
是 nul 字符,即 '[=12=]'
。这表明您在将字符串写入 bc
时超出了字符串的末尾。问题在这里:
sizeof(expression)
expression
不是数组,它是一个 char
指针,指向字符串 "20*5\n"
的第一个字符,如果您使用的是 64 位计算机,它的大小为 8。要获取要发送的字符串的长度,请改用 strlen(expression)
。
另一件与您的问题无关的事情是,在父进程中,在您阅读答案后,wait 让子进程完成。否则,你将只剩下一个僵尸。
这是错误的
if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))
您正在使用 sizeof
运算符和 expression
,这是一个 char*
,如果您的系统是 32 位,它将导致 4
,这是代码中任何指针变量的大小。
您需要使用 strlen(expression)
而不是 sizeof
。
正如答案中所指出的,如果父进程有多个子进程,则需要等待子进程完成执行并终止。理想情况下,您还应该检查 wait
的 return 值,这为您提供了有关子进程如何终止的更多上下文。