简体   繁体   English

通过fork和pipe调用gnuplot并更新图

[英]call gnuplot via fork and pipe and update plot

I want to do some realtime-plots during a simulation. 我想在模拟过程中进行一些实时绘图。 For this, i would like to use octave or gnuplot. 为此,我想使用八度或gnuplot。 My current approach is to use a frontend to gnuplot, feedgnuplot, which fits actually very well. 我当前的方法是使用前端来gnuplot,feedgnuplot,这实际上非常合适。

The Simulation is written in C++, so i thought about forking (new process for feedgnuplot) and piping the relevant data to feedgnuplot. 模拟是用C ++编写的,因此我考虑了分叉(feedgnuplot的新过程)并将相关数据传递给feedgnuplot。

The problem i have is that the output is only visible after the simulation. 我的问题是输出仅在仿真后可见。 But i want to see the plot updated during simulation. 但是我想看看模拟过程中的情节更新。

Here is a MWE: 这是MWE:

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

int main()
{
    FILE* stream = popen("feedgnuplot", "w");

    for(int i = 0; i < 10; ++i)
    {
        fprintf(stream, "%d\n", i * i);
        fflush(stream);
        sleep(1);
    }
}

The program stops after 10 secons, showing the plot. 程序在10秒后停止,显示该图。

When using feedgnuplot directly in the shell, everything works as expected. 直接在外壳中使用feedgnuplot ,一切都会按预期进行。 (That is, newly added data is plotted without the need to end the process) (也就是说,无需结束过程即可绘制新添加的数据)

What am i doing wrong? 我究竟做错了什么? I think i lack some understanding of how popen really works. 我认为我对Popen的工作原理缺乏了解。

First, let's write a fake feedgnuplot.c: 首先,让我们编写一个假的feedgnuplot.c:

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

int main()
{
    char *buf = NULL;
    size_t n = 0;

    while (getline (&buf, &n, stdin) != -1) {
        printf ("%s", buf);
    }

    free (buf);
    return 0;
}

With this, your code works, ie the lines are printed as they arrive. 这样,您的代码就可以工作,即行到达时将其打印出来。

I suspect the problem lies in the way your feedgnuplot program reads incoming data. 我怀疑问题出在您的feedgnuplot程序读取传入数据的方式上。 You should show the relevant part of that code. 您应该显示该代码的相关部分。

If I had to take a guess, you probably need to add 如果我不得不猜测,您可能需要添加

setvbuf (stdin, NULL, _IOLBF, 0);

in feedgnuplot before you start to read from stdin. 在您开始从stdin读取之前,在feedgnuplot中。

That is because by default, when stdin corresponds to a terminal it is line buffered, whereas when it corresponds to a pipe it is fully buffered. 这是因为默认情况下,当stdin对应于终端时,它被行缓冲,而当它对应于管道时,它被完全缓冲。 The code above makes stdin line buffered no matter what so there should be no difference between reading from a terminal or a pipe. 上面的代码无论如何都会使stdin行缓冲,因此从终端或管道读取之间应该没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM