1

我有两个通过命名管道(使用 mkfifo() 生成)进行通信的 C++ 程序。

一段时间后,写作程序挂起。我认为 FIFO 的缓冲区已满。如果缓冲区已满,是否可以在写入 FIFO 之前进行检查?

提前致谢!

鲁本

4

2 回答 2

2

pipe手册页

如果一个进程试图写入一个完整的管道(见下文),那么 write(2) 会阻塞,直到从管道中读取足够的数据以允许写入完成。

解决方案是打开指定O_NONBLOCK标志的管道(参见open手册页)。

于 2013-05-24T09:38:44.333 回答
1

我担心O_NONBLOCK写入命名的fifo会导致linux上的内存不足问题:

我做了一个小实验,会发生什么,当作家进程......

  • 将损坏管道 ( SIGPIPE) 的过程信号设置为忽略,
  • 打开一个命名管道O_NONBLOCK
  • 然后将很多东西写入该管道。

这实际上是将此处发布的 ftee-program的想法集成到 writer 程序本身中。

另一方面,我会在一段时间后将命名 fifo 的内容读出到一个文件中并检查它 - 因此我的意思是“在编写器进程产生了超过 64K 的数据之后”。

结果是,该文件包含编写器进程的所有输出 - 这证明了超过 64K 已被 linux 缓冲。

这向我提出了一些问题:

  • 除了 64K 命名管道缓冲区大小之外,还有其他限制吗?
  • 还是会增加直到linux内存不足?

背景: - 那是我的作家计划writer.pl

#!/usr/bin/perl -w

use strict;
use Fcntl;

my $fifo_name = '/tmp/fifo1';

sub daemon()
{
    my $pid = fork();
    if ($pid < 0) { die "fork(): $! \r\n"; }    
    if ($pid > 0) { exit(0); }
    close(STDIN);
    close(STDOUT);
}

sub main()
{
    `mkfifo $fifo_name`;
    $SIG{'PIPE'}    = "IGNORE"; # ignoring SIGPIPE
    my $fifo_fh = undef;
    sysopen($fifo_fh, $fifo_name, O_NONBLOCK | O_RDWR) or die $!;

    my $n = 0;
    while (1)
    {
        my $line = "This is line $n...\n";
        syswrite($fifo_fh, $line, length($line));
        select(undef, undef, undef, 0.01); # sleep 1/100 second
        $n++;
    }
}

daemon();
main();

...这就是我测试的:

$ ./writer.pl

... 稍等片刻 ...

$ cat /tmp/fifo1 > dump.txt

...因为这永远不会终止,请在一段时间后按 Ctrl-C,然后

$ less dump.txt
This is line 0...
This is line 1...
This is line 2...
...
This is line 61014...
This is line 61015...

writer.pl 从一开始的所有输出都存储在某个地方!

于 2015-02-03T21:59:57.350 回答