从正在积极写入

时间:2017-06-04 05:52:58

标签: c

我有两个程序:一个(program1)连续写入文件,我希望另一个程序(program2)连续读取文件。发生了什么事情,我的第二个程序只读取第二个代码执行时写入的数据点,停止而不是连续读取。

有没有办法实现这个目标?

基本上,我希望将program1的输出用作program2的输入。有没有办法在RAM而不是文件中读写,因为磁盘读取需要更多的时间。

代码2:

#include <stdio.h>

int main(){

    FILE *fptr;

    fptr = fopen("gbbct1.seq","r");

    char c;
    c = fgetc(fptr);

    while (c != EOF){

        printf("%c", c);
        c = fgetc(fptr);

    }

}

我正在寻找独立于平台的方法。如果那是不可能的,我想知道Linux平台。一旦读取,我不需要保留数据。我不想阻止program1

2 个答案:

答案 0 :(得分:4)

代码的最基本版本需要在遇到EOF时重置文件流状态,然后暂停一段时间。例如,假设POSIX并且仅使用最简单(最普遍)的函数:

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

int main(void)
{
    const char filename[] = "gbbct1.seq";
    FILE *fptr = fopen(filename, "r");
    if (fptr == 0)
    {
        fprintf(stderr, "failed to open file '%s' for reading\b", filename);
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        int c;
        while ((c = fgetc(fptr)) != EOF)
            fputc(c, stdout);

        clearerr(fptr);
        sleep(1);
    }
    /*NOTREACHED*/
    return EXIT_FAILURE;
}

sleep()函数睡眠整数秒;如果你想要亚秒级睡眠,你可以考虑usleep()nanosleep()timer_create()和亲戚等

我有一个程序我称之为dribbler(因为它将数据传输到输出中):

Usage: dribbler [-hlntV][-s nap.time][-r std.dev][-f outfile][-i infile][-m message][-o openstr][-F format]
  -V           Print version information and exit
  -f outfile   Write to named file (dribbler.out)
  -h           Print this help message and exit
  -i infile    Read lines from input file
  -l           Loop back to start of input file on EOF
  -m message   Write message on each line of output
  -n           Number lines read from input file
  -o openstr   Flags passed to fopen() (a+)
  -s nap.time  Sleep for given interval between writes (1.000 second)
  -r std.dev   Randomize the time (Gaussian around nap.time with std.dev)
  -t           Write to standard output instead of file
  -F format    Printf format to use instead of %zu

我用过:

$ dribbler -s 3 -r 1.3 -f gbbct1.seq &
[1] 81129
$

写入program2编码为要读取的控制文件。然后我在它上面运行program2,并在它继续时产生输出。

很难在SO上显示时间顺序。我有一个名为tstamp的另一个程序(我的生活故事),它读取输入行并打印带有前缀为行的时间戳:

Usage: tstamp [-hV][-f num][-F format]
  -f num  Number of fractional digits (0, 3, 6, 9)
  -h      Print this help message and exit
  -F fmt  Time format (strftime(3)) to use
  -V      Print version information and exit

我尝试修改program2.c以在我的Mac上设置行缓冲模式(macOS Sierra 10.12.5,GCC 7.1.0),在while循环program2.c之前添加以下行但是它实际上被忽略了,有点令我惊讶和懊恼:

setvbuf(fptr, 0, _IOLBF, 0);

所以,我将while循环重写为:

    while ((c = fgetc(fptr)) != EOF)
    {
        fputc(c, stdout);
        if (c == '\n')
            fflush(stdout);
    }

然后我可以在后台运行dribbler,并program2 | tstamp -f 3获得如下输出:

$ program2 | tstamp -f 3
2017-06-03 23:52:44.836: 0: message written to file
2017-06-03 23:52:44.836: 1: message written to file
2017-06-03 23:52:44.836: 2: message written to file
2017-06-03 23:52:44.836: 3: message written to file
[…more similar lines with the same time stamp…]
2017-06-03 23:52:44.836: 22: message written to file
2017-06-03 23:52:44.836: 23: message written to file
2017-06-03 23:52:44.836: 24: message written to file
2017-06-03 23:52:44.836: 25: message written to file
2017-06-03 23:52:50.859: 26: message written to file
2017-06-03 23:52:54.866: 27: message written to file
2017-06-03 23:52:58.880: 28: message written to file
2017-06-03 23:53:02.888: 29: message written to file
2017-06-03 23:53:05.902: 30: message written to file
2017-06-03 23:53:07.907: 31: message written to file
2017-06-03 23:53:09.913: 32: message written to file
2017-06-03 23:53:12.925: 33: message written to file
2017-06-03 23:53:14.935: 34: message written to file
2017-06-03 23:53:15.938: 35: message written to file
2017-06-03 23:53:19.954: 36: message written to file
2017-06-03 23:53:21.964: 37: message written to file
2017-06-03 23:53:23.972: 38: message written to file
^C
$ kill %1
[1]+  Terminated: 15          dribbler -s 3 -r 1.3 -f gbbct1.seq
$

当我开始dribbler(它被修改并重新编译 - 我的懊恼的一部分)时,你可以看到我program2运行了一段时间,所以有相当多的要立即读取的日期(因此带有时间戳2017-06-03 23:52:44.836:的多行),但它等待dribbler写更多,正如您所看到的,它有时会在行之间等待近6秒,并且其他时间约为1秒,并且介于两者之间。通过program2一次睡眠一秒钟,使间隙更均匀。 (是的,我编写了这些工具来帮助回答关于SO的问题 - 但是dribblertstamp都是在几个月之前将这个问题提前了。)

答案 1 :(得分:2)

  

我有两个程序:一个(program1)连续写入文件,我希望其他程序(program2)连续读取文件。

然后会发生什么是特定于平台的。顺便说一下,processes提供了一次运行多个程序的能力(在operating system中){并且未在中定义,因为在{{}之外3}}标准)。阅读C11(可免费下载的章节)。

IIRC,在Windows上(我不知道,从未使用过)不允许发生(其中一个程序会被阻止或者文件打开失败)。

但是,如果在具有本机本地文件系统的Linux(例如Ext4)上,您可以考虑使用Operating Systems : Three Easy Pieces工具(这些工具不适用于NFS的远程文件系统,并且可能无法工作在FAT文件系统上,例如某些USB密钥;但你需要检查)。

  

基本上,我希望program1的输出用作program2的输入。有没有办法在RAM而不是文件中读写,因为磁盘读取需要更多的时间。

(我假设你写了 program1 program2 ,或者至少有他们的源代码并且可以修改它)

BTW,应用程序不能直接从RAM中读取 ;它们在inotify(7)中工作,每个virtual memory都有自己的process。请参阅virtual address space

您肯定希望拥有一些由您的操作系统提供的this answer

在Linux上有很多方法可以做到这一点(你应该阅读inter-process communications ,其章节可以免费下载)。我建议考虑一些Advanced Linux Programming或一些fifo(7)(如果两个正在运行的程序都可以从一个公共进程启动)或一些pipe(7)套接字。 你肯定需要多路复用I / O(在两个进程中),例如在unix(7)附近设置一些event loop

poll(2)设施。但我不认识他们。

(我强烈建议您花几天时间阅读,特别是Windows also has inter-process communication或其他类似的书籍,然后再编写一行代码。您缺乏关于操作系统和Linux的整体情况。

我建议使用Advanced Linux Programming,或者使用一些名为pipe(7)的内容,或者使用一些fifo(7)套接字。然后,您可以在所有unix(7)系统上编写可移植代码。我不建议使用文件和POSIX(这是复杂的,特定于Linux的)。另请参阅inotify(7)

您可能会发现一些框架库(例如来自GTK的popen(3)GlibQtCorePOCOlibevent)以帮助您编写可移植的代码在许多平台上运行。