我有两个程序:一个(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
。
答案 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的问题 - 但是dribbler
和tstamp
都是在几个月之前将这个问题提前了。)
答案 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),Glib,QtCore,POCO,libevent)以帮助您编写可移植的代码在许多平台上运行。