通过管道和叉子使用 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 值,这为您提供了有关子进程如何终止的更多上下文。