Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用perl中的命名管道在两个进程之间通信?_Perl_Named Pipes - Fatal编程技术网

使用perl中的命名管道在两个进程之间通信?

使用perl中的命名管道在两个进程之间通信?,perl,named-pipes,Perl,Named Pipes,我正在尝试使用命名管道解决此问题: 我有一个连续运行的进程。如果有可用的数据,这个过程应该只检查命名管道。如果没有,我有替换数据(缓存数据)用于这种情况 非常重要的是,这个持续运行的进程不会阻塞,如果在命名管道的“另一端”没有附加任何进程,那么这个持续运行的进程应该求助于缓存数据 然后我有第二个过程。此过程可以随意启动,但通常会定期从cron脚本运行。此进程将数据转储到命名管道中 理想情况下,我希望将这些数据转储到指定的管道中,等待它可供连续运行的进程随时提取。如果可能的话,进程可以随时保持管道

我正在尝试使用命名管道解决此问题:

我有一个连续运行的进程。如果有可用的数据,这个过程应该只检查命名管道。如果没有,我有替换数据(缓存数据)用于这种情况

非常重要的是,这个持续运行的进程不会阻塞,如果在命名管道的“另一端”没有附加任何进程,那么这个持续运行的进程应该求助于缓存数据

然后我有第二个过程。此过程可以随意启动,但通常会定期从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_path }
}
    
sub read_fifo {
    my ($fifo) = @_;
    open my $fh, '<', $fifo  or do {
        if ($! == ENOENT) {
            say "No file $fifo -- no new data, carry on and use default";
            return;
        }
        else { die "Can't open fifo $fifo: $!" }  # some other error
    };
    return join '', <$fh>;
}
这可以通过与最初的作者相同的方式,使用相同的读者进行测试


作者的孩子在阻塞的
打开的
中等待管道,直到读者开始阅读。当读卡器打开管道以读取写卡器的
open
时,数据被写入并被读卡器接收。或者根本没有FIFO,读卡器的
打开
失败(使用
enoint
),因此读卡器知道没有新数据,可以使用其默认值。

aah,写入器也不能阻止,因为是写入器稍后导致读取。但是,由于读者可以永久打开文件,因此不应该担心这个问题。但是在这种情况下删除文件是行不通的。@sebastiannielsen问题中所说的和现在所说的加起来是不可能的。命名管道块。它们看起来确实像普通文件,但实际上有一个程序应该在另一端,所以如果实际上没有程序,它就必须阻止。根据你在这里所说的,你真的想要一个简单的文件,就像我在答案的开头和结尾所建议的那样。(这有什么不对?@sebastiannielsen Re:“是作者后来让它被阅读”——呵呵?所以作者转储信息。。。但直到后来(不知何故)才让它被阅读。。。?那真的没有道理。也许你可以解释一下整个设计?在这一点上,我怀疑您可能根本不需要命名管道。问题是磁盘IO速度很慢。所以我有一个短时间运行的进程,它创建数据X,然后将其转储到第二个进程。然后,短时间运行的进程通知第三方验证数据X,然后与连接到长时间运行的进程的服务器进行对话。但有一个陷阱:第三方从不同的位置多次读取数据X,比如30-40次。我必须从磁盘读取数据,以确定是否有新数据,而不管是否缓存了数据。因此,我对select()解决方案感兴趣。因此,长时间运行的进程可以检查fifo管道是否可用(因此,短时间运行的进程是活动的)。如果是,我想读取短时间运行的进程转储的任何内容,并将其缓存。在后续读取时,我可以知道我已经“获取”了数据,因为fifo管道暂时是空的,因此可以回退到缓存数据。在基于文件的场景中,这可以与读取后删除文件进行比较,但检查文件是否存在仍然需要磁盘IO,但检查空FIFO管道只需要在RAM中进行一些挖掘。
use warnings;
use strict;
use feature 'say';

my $fifo = 'test.fifo';

my $pid = fork // die "Can't fork: $!";

if ($pid == 0) {  
    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: $!"; # awaits reader
    say $fh "Message to fifo from $$";
    close $fh;
    
    unlink $fifo or die "Error unlinking $fifo: $!";

    exit;
}

# parent can now do its work

# Always reap -- but now also must not leave until FIFO's been read
my $gone = waitpid $pid, 0;
if ($gone > 0) { say "FIFO-handling child exited with $?" }