我为系统事件文件的非阻塞输入设置了一些代码。
sysopen(FILE, $targetInput, O_NONBLOCK|O_RDONLY) or die "Failed to open $targetInput, quitting.n";
binmode(FILE);
#More assignments and preparations here...
while (1) {
#Code that justifies non-blocking I/O here...
$rBytes = sysread(FILE, $buffer, 16);
printf("%d vs %dn", $!, EAGAIN);
print defined($rBytes) ? "Defined!n" : "Undef!n";
if (!defined($rBytes) && $! == EAGAIN) {
#Nothing actually read in non-blocking mode:
usleep(1000);
} else {
#Got an event, moving on:
print "Got it!n";
print "$rBytes!n";
last;
}
}
#Logic using $buffer here...
这是一个非常标准的设置,有几十个例子可以用于这个事情。然而,我发现,100%的时间,$rBytes
仍然是未定义的,$!
被设置为代码22,EINVAL(无效参数)。很多测试都是为了确保是sysread
函数引起的,而不是在它之前。
问题是,它有效。正如您所看到的,我的代码假设任何不是的东西,$rBytes
的组合是未定义的(始终为真)和 $!
是EAGAIN
(始终为假)只是假设一切都很好,因为我没有添加任何错误处理。这个代码块后面是一个巨大的开关/案例;不存在的数据会"无害地"跳过所有的数据,并以尽可能快的速度循环再做一次。
当收到有效输入为时,$rBytes
为仍未定义。但是由于$!
仍然不是EAGAIN
,它也传递给程序的其余部分,并精确地按预期工作,$buffer
包含它应该包含的内容。如果我没有看一下我的CPU使用率表,我实际上根本不会注意到这个问题,如果它是一个快速的一次性脚本,我可能不会尝试修复它。
我可以肯定地说,"无效论证"的指控是虚假的。问题是,为什么它给出错误代码,为什么$rBytes
总是未定义?
当我拼凑一个快速脚本来模拟到目前为止所做的假设时,我实际上偶然发现了自己的答案;果然,所有必要的信息一直都在问题中。
典型的系统事件文件处理长度为24字节的消息。当然,这段代码试图从这些事件中提取16位时间戳,而将其余部分留到以后使用。由于我自己也不明白的原因,sysread
不喜欢那样。
通过确保所需长度大于或等于24,sysread
将报告读取的字节数,$!
将报告所记录的字节数。24可能是一个神奇的数字,或者它可能只是在从非阻塞资源读取部分消息时出现问题(阻塞模式下不会发生错误)。它仍然将适当的数据放入$buffer
,大概是因为底层代码通过引用传递它,并且在发生错误时不会将其归零,这就是为什么所示块之后的所有内容都工作得很好。