Perlを使用してできるだけ早くUnixソケットファイルに書き込もうとしますが、メッセージバッファ全体で失敗します。自動リフレッシュと手動リフレッシュを試みましたが、成功しませんでした。
use IO::Select;
use IO::Socket::UNIX;
my $sock = IO::Socket::UNIX->new(
Type => IO::Socket::SOCK_DGRAM,
Peer => "/dev/log",
) or die "$!\n";
$sock->autoflush(1);
my $sel = IO::Select->new($sock);
my $cnt = 0;
while(<>){
$sel->can_write or die "1 line $cnt: $!\n";
$sock->say($_) or die "2 line $cnt: $!\n";
$sock->flush or die "3 line $cnt: $!\n";
$cnt++;
}
$sock->close();
出力は常に2 line 64: No buffer space available
アップデート:私はPerlを使うつもりはありません。おそらく、IBM AIXのソケットに送信するより良い方法があるかもしれません。
答え1
観察されたように、すでにいっぱいのネットワークスタックにより多くのデータをより速く転送しようとすることは機能しません。少なくとも、すでにいっぱいのバスルームの排水口に多くのデータを注ぐよりも簡単です。それにもかかわらず、ここで送信者は条件が解決されるまで待たなければなりません。それ以外の場合は、ネットワークスタックのバッファが大きくなって処理されるまで、データは他の場所(たとえばカーネルの浄化槽)にプールされます。また、データグラムはフラッシュするストリームがあるかどうかを実際には知らず、$.
Perl変数はすでにアクションを実行している$cnt
ため
#!/usr/bin/env perl
use strict;
use warnings;
use Errno ':POSIX';
use IO::Socket::UNIX;
use Time::HiRes 'usleep';
my $peer = shift || die "Usage: $0 /dev/log\n";
my $sock = IO::Socket::UNIX->new(
Peer => $peer,
Type => IO::Socket::SOCK_DGRAM,
) or die "socket failed '$peer': $!\n";
LINE: while (<>) {
$sock->print($_) and next;
if ($!{ENOBUFS}) {
while (1) {
# exponential backoff might be more typical and less rude
# here, or the code could try to be smart about how long to
# wait for, but that takes more code and more memory and
# more effort on the part of the programmer
usleep(128);
$sock->print($_) and last;
# PORTABILITY and there may be a bunch of different error
# messages from trying to go too fast here with a full
# buffer, check for them ...
unless ($!{EMSGSIZE} or $!{ENOBUFS} or $!{ETIMEDOUT}) {
my $errno = 0 + $!;
die "print failed line $.: $! ($errno)";
}
}
} else {
my $errno = 0 + $!;
die "print failed line $.: $! ($errno)";
}
}