我正在尝试使用命名管道解决此问题:
我有1个连续运行的进程。此过程仅应检查命名管道,如果那里没有可用数据。如果没有,我有替换数据(缓存的数据)可用于这种情况。
非常重要的是,此1个连续运行的进程不会阻塞,并且如果在命名管道的“另一端”没有附加进程,则该连续运行的进程应该使用缓存的数据。
然后我进行第二步。此过程可以随意启动,但通常会定期从cron脚本运行。此过程会将数据转储到命名管道中。
理想情况下,我希望将此数据仅转储到命名管道中,以等待可用于连续运行的进程在任何时候提取。如果可能的话,连续过程可以始终保持管道打开,或者在需要数据时可以打开管道。
但是,如果需要,此间歇运行的进程可以保持其管道打开,直到连续运行的进程处理数据为止。
有什么好主意可以做到这一点吗?我怀疑我可以以某种方式打开管道,即使在另一端没有阻塞的情况下也没有进程,但是在进程附加到命名管道的另一端并发送数据之前,当然不会有数据。
并且当该过程分离时,即使在分离后进行读取,缓冲的数据是否仍可用于读取应用程序?
我不确定您是否出于上述目的需要解决该麻烦。为什么不将信息转储到一个普通文件中,该文件可以在不断运行的进程中进行检查和读取?还是使用更加灵活的插座?但是,您的要求当然可以完成,并给出一些具体的意图。
如果读者不在,写者将无法打开FIFO,但从我在问题中所读的内容就可以了,就这样吧。读者可以使用select
以非阻塞方式进行检查。但是,这样一来,编写者首先创建该管道,并在完成后将其删除就更简单了,因此,如果没有可打开的文件,则读者可以继续操作。
作家
use warnings;
use strict;
use feature 'say';
my $fifo = 'test.fifo';
if (-e $fifo) { unlink $fifo or die "Can't unlink $fifo: $!" }
system('mkfifo', $fifo) and system('mknod', $fifo, 'p')
and die "Can't make $fifo: $!";
open my $fh, '>', $fifo or die "Can't open fifo $fifo: $!"; # Blocks here until
say $fh "Message to fifo from $$"; # there's a reader
close $fh;
unlink $fifo or die "Error unlinking $fifo: $!";
阅读器,正在运行的程序
use warnings;
use strict;
use feature 'say';
use Errno qw(ENOENT);
my $fifo = 'test.fifo';
while (1) {
say "\nDo work (sleep a little really), try for message ...";
sleep 3;
if (my $msg = read_fifo($fifo)) {
say $msg;
last; # done with this exercise
}
# Run the writer program in another terminal at some point
#
# Or, to simulate that:
#my $pid = fork // die "Can't fork: $!";
#if ($pid == 0) { exec 'writer_program_name.pl' }
}
sub read_fifo {
my ($fifo) = @_;
open my $fh, '<', $fifo or do {
if ($! == ENOENT) {
say "No file $fifo, that's OK, go back to my stuff";
return;
}
else { die "Can't open fifo $fifo: $!" } # some other error
};
return join '', <$fh>;
}
这省去了更多适当的测试,还有其他细节。
我个人认为,在这种情况下,通过纯文件进行通信要简单得多。