如何将管道设置为 O_NONBLOCK perl

How can I set a pipe to O_NONBLOCK perl

这很好用:

#!/usr/bin/perl -w
# 

#pipe2 - use pipe and fork so child can send to parent

use IO::Handle;

pipe(READER, WRITER);
WRITER->autoflush(1);

if ($pid = fork) {
    close WRITER;


    chomp($line = <READER>);
    print "Parent Pid $$ just read this: `$line'\n";
    close READER;
    waitpid($pid,0);
} else {
    die "cannot fork: $!" unless defined $pid;
    close READER;
    print WRITER "Child Pid $$ is sending this\n";
    close WRITER;  # this will happen anyway
    exit;
}

但是当我尝试使 reader 不被 fcntl 阻塞时,如下所示:

use IO::Handle;
use Fcntl;

pipe(READER, WRITER);
WRITER->autoflush(1);

if ($pid = fork) {
    close WRITER;
    fcntl(fileno(READER),F_GETFL,$flags)
        or die "Couldn't get flags for READER : $!\n";
    $flags |= O_NONBLOCK;
    fcntl(fileno(READER), F_SETFL, $flags)
        or die "Couldn't set flags for READER $!\n";
    chomp($line = <READER>);
    print "Parent Pid $$ just read this: `$line'\n";
    close READER;
    waitpid($pid,0);
} else {
    die "cannot fork: $!" unless defined $pid;
    close READER;
    print WRITER "Child Pid $$ is sending this\n";
    close WRITER;  # this will happen anyway
    exit;
}

我得到:

fcntl() on unopened filehandle 3 at pip2.pl line 14.
Couldn't get flags for READER : Bad file descriptor

我需要“观察”child 并在它在特定时间内没有正确响应时采取措施。我需要与 child.

进行异步通信
fcntl(fileno(READER),F_GETFL,$flags)

fcntl 获取文件句柄,而不是文件编号。使用 fcntl(READER,... 而不是 fcntl(fileno(READER), ....

除此之外,建议不要对文件句柄使用全局符号。最好使用局部变量,即

 pipe(my $reader, my $writer); 
 $writer->autoflush();
 ...
 

除了不会与其他全局符号发生潜在冲突并避免未捕获拼写错误的风险外,这还将关闭变量超出范围的相应文件句柄。