【问题标题】:Delay in Unix chain of pipesUnix管道链延迟
【发布时间】:2014-11-28 01:58:58
【问题描述】:

我正在尝试为 3 个进程和当前程序创建一个管道链,以便:

1 - 执行 P1 并将 P1 的输出发送到 P2 的输入

3 - 将 P2 的输出发送到 P3 的输入

4 - 在标准输出中显示 P3 的输出

5 - 将当前/主/驱动程序的标准输入传递给 P3 的输入

我正在使用 2 个管道。对于任务 #5,主程序从标准输入读取并写入 P3 读取的管道。

我已经设法让进程相互通信。然而,我注意到在 P1 写入和 P2 在其 STDIN 上检测到此写入之间存在很大延迟,即 P1 在 P2 检测到写入之前可能已经写入了数百次,并且在开始时错过了许多 P1 写入。我已经通过打印消息确认 P2 实际上是按时启动的,但是,它没有及时检测/读取输入(这是一个 Python 脚本循环:“for line in sys.stdin:”)

这是我的代码:

int pipe1[2];
int pipe2[2];
if (pipe(pipe1) < 0 || pipe(pipe2) < 0  )
{
    perror("Error: pipe");
}   


pid_t procIDC = fork();
if (procIDC == 0)
{       
    dup2(pipe2[0], 0);
    execv("procC", argv);           
}   
else
{       
    pid_t procIDB ;
    procIDB = fork();   

    if (procIDB == 0)
    {       
        dup2( pipe1[0], 0);  
        dup2( pipe2[1], 1);


        if (execl("/usr/bin/python", "/usr/bin/python", "./test.py", (char *)NULL) < 0)
        {
            perror("execl"); return 0;
        }
    }
    else
    {           
        pid_t procIDA = fork(); 
        if (procIDA ==0)
        {       
            dup2( pipe1[1], 1);
            execv("proc1", argv);       
        }   
        else
        {                   
            dup2( pipe2[1], 1);

            //print any input so it sends to p3
            ssize_t read;   
            char *inputLine = NULL;
            size_t len = 0;        
            while ((read = getline(&inputLine, &len, stdin)) != -1) 
            {
                printf(inputLine);
            }               
        }
    }

【问题讨论】:

    标签: c linux unix pipe


    【解决方案1】:

    我注意到 P1 写入和 P2 在其 STDIN 上检测到此写入之间存在很大延迟

    是的。您的问题大概是“为什么会有延迟”?

    答案:stdio(大多数程序使用)检测到输出进入管道时使用全缓冲输出。

    要防止这种缓冲,请使用fflushsetvbuf

    一些补充阅读here

    其实fflush显然是在写程序里做的

    您没有向我们展示带有fflush 的写作程序。如果你有,我们也许可以指出你的错误(fflush 如果操作正确,会有所帮助)。

    无论如何,查看正在发生的事情的一种方法是运行strace -p &lt;pid-of-writer&gt;,并观察立即在作者实际执行write(2) 系统调用之后,读者得到它的输入。这将证明它实际上是在导致延迟的写入器中缓冲。

    这个:

    setbuf(stdout, NULL);

    不禁用缓冲。你真的需要打电话给setvbuf(或fflush)。

    【讨论】:

    • 我实际上已经尝试过了,但它似乎没有帮助。另外:我在想,如果在 printf 和 flush 之后我在后续打印之前进入睡眠状态,最终这将被 P2 拾取。但是,看起来这只会增加 P2 最终检测到读取之间的时间。我不明白!
    • @cppNoob 您只向我们展示了阅读程序。将fflush 添加到 it 不会有任何区别:延迟发生在 writing 中。而且当然让已经很慢的程序进入睡眠状态只会让它变慢。
    • 其实fflush显然是在写程序里做的,sleep AFTER也是这样写的
    • 我原以为如果在 P1: printf 然后 fflush(stdout) 然后会有一些延迟,最终这将在 P2 上读取。但是延迟使情况变得更糟,即似乎只有在您所说的一定量的缓冲后才在 P2 上读取它,但我正在调用 flush 和 setbuf(stdout, NULL);
    • 我已经尝试过 setvbuf 以及: printf("hi\n"); fflush(stdout);
    【解决方案2】:

    在 P2 的 STDIN 上有输入缓冲

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多