popen 没有按预期工作

popen not working as expected

我有一个程序,我需要通过它的标准输入和输出与另一个程序通信。我可以使用管道向其发送输入并将其输出重定向到指定文件以在完成后读取,并且工作正常。我没有使用 pipe 和 dup2,因为我希望我的程序至少可以在 windows 和 linux.

上工作

我的问题是我想使用管道来传输数据。

我尝试了以下片段:

#include <stdio.h>

int main()
{
    while (!feof(stdin)) {
        int x;
        scanf("%d", &x);
        printf("%x ", x);
        fflush(0);
    }

    return 0;
}

结合:

#include <unistd.h>
#include <stdio.h>

int main()
{
        int x;
    FILE *p = popen("./test > tmp.datafile", "w");
    FILE *f = fopen("tmp.datafile", "r");

    for (int i = 0; i < 100; ++i) {
        fprintf(p, "%d", i);

        sleep(1);
        x = fgetc(f);
        printf("%c ", x);
        fflush(0);
    }

    fclose(f);
    pclose(p);

    return 0;
}

但是无论我做什么,我总是从文件中获取空值。我怀疑可能存在并发问题,因为我尝试在测试可执行文件完成刷新之前读取文件,但是我不确定如何解决这个问题。

有没有更好的方法通过 c 中的标准流与程序通信?

一旦达到 EOF,fgetc() 将不会读取过去的 EOF — 这可能会在第一次读取时发生。做类似

的事情
if(feof(f)) {
    clearerr(f);
    sleep(1);
} else {
    printf("%c ", x);
}

应该可以通过繁忙的循环来解决问题。

一个更好的主意是在达到 EOF 后等待文件更改,但这需要系统特定的调用。

注意另一个竞争条件:fopen 可能发生在通过 popen 启动的命令创建文件之前。

while(!(f = fopen(..., "r"))
    sleep(1);

这是另一个繁忙的循环,总体而言不是一个好的解决方案,只有在 dup2() 不可用时才应使用。

您的代码中的一个问题是您没有将任何白色 space 写入 p 的输入,因此 scanf() 在 [=14= 中调用] 正在等待输入完成,以便它可以读取值。因此 ./teststdout 仍然是空的。通过这样的方式修复它:

fprintf(p, "%d\n", i);

此外,考虑在 ./test 程序中使用无缓冲的 I/O 函数。 printf 是缓冲 I/O 函数系列的一部分,输出可能不会立即写入文件。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
    while (!feof(stdin)) {
        int x;
        char s;
        scanf("%d", &x);
        sprintf(&s, "%x", x);
        write(STDOUT_FILENO, &s, 1);
        fflush(stdout);
    }

    return 0;
}