为什么Perl的sysopen报告成功,但是$!有错误吗?

时间:2010-10-08 17:52:45

标签: perl

我的sysopen失败了:

sysopen(DEV, "/dev/ttyS0", O_NONBLOCK|O_RDONLY)

返回1,这是成功的!然后,为什么$!在其中有错误“非法搜寻”(在通话之前它是undef)

before sysopen $!:
after sysopen $!: Illegal seek

编辑: 这是完整的脚本:(使用实际的O_NONBLOCK | O_RDONLY值2048)

 #!/usr/bin/perl -w
 use Device::SerialPort;
 my $ob;

 $ob = new Device::SerialPort("/dev/ttyS0");

 print $!, "\n";
 $! = 0;

 my $ret = sysopen(DEV, "/dev/ttyS0", 2048);

 print $!, "\n";
 $! = 0;

 print "ret from sysopen: ", $ret, "\n";
 #my $dev = <DEV>;
打印出来的

: ./filehandle.pl 非法寻求 非法寻求 从sysopen退出:1

2 个答案:

答案 0 :(得分:16)

这就是C errno变量的工作原理。引用man errno

  

只有当它的价值才有意义   返回值   该呼叫表示错误(即,来自大多数系统的-1)   电话;大多数库函数的-1或NULL);一个功能   成功的 允许更改errno

$!只是Perl与errno的接口,并且有same behavior

  

这意味着$!的值是   a之后只有立即才有意义   的失败

您必须检查sysopen的返回值以确定它是否失败。如果失败,$!将告诉您原因失败,但您无法使用$!来确定 是否失败(除非特定记录下您正在使用的函数在成功时将$!设置为0.大多数情况下都没有,包括sysopen)。

答案 1 :(得分:1)

Perl中的许多类似的特殊变量在它们必须之前不会改变它们的值。你总是应该检查实际设置变量的条件。两个最常见的例子是在出现错误时重置错误变量或在成功匹配时重置正则表达式捕获变量。

 unless( sysopen( ... ) ) {
      die "Error was $!";
      }

 if( m/(...)(...)/ ) {
      print "Found $1 and $2\n";
      }

这肯定是Perl的瑕疵之一,因为它依赖于远程全局变量的副作用来表示本地发生的事情。在某些情况下,它甚至会更糟糕,因为在您有机会查看它之前,其他东西可以更改特殊变量,因此您应该在运行任何其他语句之前立即检查它。