在C中多次从stdin读取相同的数据

时间:2015-04-21 05:00:05

标签: c pipe stdin scanf

我正在C中编写一个基于跟踪文件的缓存模拟器,我希望通过stdin将其传递到程序中。这些跟踪文件最长可达150亿行,因此我不希望将它们存储在活动内存中的任何位置。我想使用在程序输入中指定的配置文件,从一次调用中为不同的内存配置多次运行模拟。程序调用应如下所示:

cat | (trace file) ./MemorySimulator -f (config file)

现在,程序运行的方式是它使用配置文件设置模拟的参数,然后使用scanf()从stdin读取格式化数据中的管道,直到它到达跟踪文件的末尾。然后,它从配置文件继续进行下一个配置设置,并尝试再次从跟踪文件中读取数据。此过程将继续,直到各种配置选项用尽为止。

我遇到的问题是,一旦我运行跟踪文件一次,我就无法再从配置文件中为以下内存配置捕获数据。

有没有办法在我的C程序中回收管道数据,以便我可以从单个程序执行中多次运行模拟?到目前为止,我还没有找到实现这个目标的方法。

3 个答案:

答案 0 :(得分:2)

不,这不起作用。这就是管道的本质。

您无法要求数据未被缓存,同时可以重新请求数据。

在一个管道中,一个数据已写入,它已经消失,所以你必须将它存储在某个地方,以免迷路。

你能做到这一点的唯一方法是"模仿"另一个程序的行为 - 在cat案例中应该是微不足道的。

确切地说,您的代码是着名的UUOC(不合理使用cat)的一个很好的例子。

如果要求您从标准输入读取 - 好吧,那不是一个管道。而不是

cat file | program

你可以做到

program < file

这并没有给你一个管道,但可以直接访问该文件,包括寻找的能力。

如果可能,您可以使用此功能,如果没有,请自行缓存数据或拒绝运行。

但是,如果要求您接受所有种类的标准输入,则此功能无效。

答案 1 :(得分:0)

你问:

  

有没有办法在我的C程序中回收管道数据,以便我可以从单个程序执行中多次运行模拟?

如果您愿意将跟踪文件用作程序的输入参数,则可以完成所需的操作。

而不是

cat <tracefile> | ./MemorySimulator -f (config file)

你可以使用:

./MemorySimulator <tracefile> -f (config file)

main中,使用fopen打开跟踪文件。完成一次配置后,使用frewind后退并重新使用FILE*进行下一次配置。

您还可以在每个配置的跟踪文件中使用fopen/fclose

答案 2 :(得分:0)

鉴于您的评论,您需要从stdin读取数据(并且,我认为,不能要求stdin直接从文件重定向),您可以选择缓存数据自己。由于该数据超过40GB,因此缓存最好是磁盘文件。

我要做的是,在第一遍中打开一个临时文件进行读/写,当你从FILE*变量集中读取等于stdin时,也要写入数据到你的临时文件。在第一遍结束时,将临时文件fp复制到输入fp。

现在,对于剩余的传递,您可以开始重写输入(临时)文件并读取它以进行输入。

您可以使用循环计数器确定每次通过时需要执行的操作。

以下是此代码的概述:

infp = stdin;
for (loop = 0; loop < NUM_LOOPS; loop++) {
    if (loop == 0) {
        tmpfp = fopen("tmpfile.tmp", "w");
        //check for errors here
    }
    for (;;) {
        num_read = read(infp, buf, sizeof(buf));
        // check for EOF here and break if so
        if (loop == 0) {
            num_written = write(tmpfp, buf, num_read);
            //check for write errors here
        }

        // Main input processing code
    }

    if (loop == 0) {
        infp = tmpfp;
    }
    rewind(infp);
}