【问题标题】:Using bc through pipes and fork通过管道和叉子使用 bc
【发布时间】:2017-12-11 10:34:59
【问题描述】:

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

【问题讨论】:

  • 变量expression 是一个指针,而不是一个数组。使用strlen() 而不是sizeof。 (我确实在我之前对这个问题的前一个变体的回答的评论中提到了使用strlen()。)
  • 好吧,请接受我的道歉,我当时真的没有明白。
  • 已接受道歉——很难在评论的碎屑中发现有用的信息块(无论是在回答中还是回答后)。

标签: c pipe fork bc


【解决方案1】:

^@ 是 nul 字符,即'\0'。这表明您在将字符串写入bc 时超出了字符串的结尾。问题出在这里:

sizeof(expression)

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

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

【讨论】:

  • 感谢您的回答,我会尝试使用wait。
  • 请注意,如果父进程先于子进程退出,系统进程(通常为 PID 1,init)会继承孤立子进程,并且不会创建僵尸进程。唯一出现僵尸的情况是父进程直到子进程退出后才退出,但父进程在任何阶段都没有等待子进程。如果父级创建了许多僵尸,这将成为一个问题;一个僵尸很少有问题,许多进程会很快退出,因此系统会自动清理潜在的僵尸。
【解决方案2】:

这是错误的

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

您将sizeof 运算符与expression 一起使用,这是一个char*,如果您的系统是32 位的,它将导致4,这是您代码中任何指针变量的大小。

您需要使用strlen(expression) 而不是sizeof

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

【讨论】:

  • 好的我也试试,谢谢帮忙,很有用。
猜你喜欢
  • 2018-05-23
  • 2018-05-26
  • 2017-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
相关资源
最近更新 更多