通过管道和叉子

时间:2017-12-11 10:35:00

标签: c pipe fork bc

我试图通过管道使用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;
}

2 个答案:

答案 0 :(得分:1)

^@是空字符,即'\0'。这会建议您在将其写入bc时超出字符串的结尾。问题出在这里:

sizeof(expression)

expression不是一个数组,它是一个char指针,指向字符串"20*5\n"的第一个字符,如果你在64位机器上,它的大小是8.要获取要发送的字符串的长度,请改用strlen(expression)

您需要做的另一件事与您的问题无关,在父进程中,您已经阅读了答案,wait以完成子进程。否则,你将留下一个僵尸。

答案 1 :(得分:0)

这是错误的

if (write(pipe1[1], expression, sizeof(expression)) != sizeof(expression))

您正在使用sizeof运算符expression char*,如果您的系统是32位,则会生成4,其大小为代码中的任何指针变量。

您需要使用strlen(expression)代替sizeof

正如答案中所指出的,如果父进程有多个子进程,则需要等待子进程完成执行并终止。理想情况下,您还应检查wait的返回值,它为您提供有关子进程如何终止的更多背景信息。