这个函数调用列表的第一个元素声明的系统调用(意思就是一次系统调用,而不是一个 shell 命令),同时把列表中其他元素作为参数传递给系统调用。(现在,许多这些调用可以通过 POSIX 模块更容易地使用。)如果 syscall(2) 未实现,那么该函数抛出一个例外。
这些参数按照下面的方式解释:如果一个给定的参数是数字,那么该参数就作为一个 C 整数传递。如果不是,那么就传递一个指向该字串值的指针。你有责任确保这个字串足够长,以便能够接收任何可能写到它里面去的结果;否则,你就等着核心倾倒吧。你不能拿一个字串文本(或者其他只读的字串)当作给 syscall 的参数,因为 Perl 已经假定任何字串指针都是可写的。如果你的整数参数不是文本并且在数字环境里从不会被解释,那么你可能需要给它们加 0 以强迫它们看起来象数字。
syscall 返回被调用的系统调用返回的任何数值。在 C 传统里,如果你那个系统调用失败,那么 syscall 返回 -1 并且设置 $!(errno)。有些系统调用在成功的时候合理地返回 -1。操作这样的的调用的正确方法是在调用之前赋值给 $!=0;然后如果 syscall 返回 -1 的话检查 $! 的值。
不是所有的系统调用可以用这个方法访问。比如,Perl 支持最多给你的系统调用传递 14 个参数。通常这么多已经足够了,但是,对于那些返回多个数值的系统调用就有问题了。比如 syscall($SYS_pipe):它返回创建的管道的读端文件号码。我们没有办法检查另外一端的文件号码。你可以用 pipe 避免这个例子里的问题。要解决一般性的问题,写直接访问系统调用的 XSUB(外部过程模块,一种 C 写的程序)。然后把你的新模块放到 CPAN,使之流行开来。
下面的子过程以浮点数返回当前时间,而不是象 time 那样返回整数秒。(它只能在那些支持 gettimeofday(2) 系统调用的机器上用。)
sub finetime() {
package main; # 用于下一个 require
require 'syscall.ph';
# 预先把缓冲区设置为 32 位长...
my $tv = pack("LL", ());
syscall(&SYS)gettimeofday, $tv, undef) >= 0
or die "gettimeofday: $!";
my($seconds, $microseconds) = unpack("LL", $tv);
return $seconds + ($microseconde/ 1_000_000);
}
假设 Perl 不支持 setgroups(2) 系统调用,(注:尽管它可以通过 $( 支持),但是你的核心支持。那么你就可以用下面的方法获得它的支持:
require 'syscall.ph';
syscall(&SYS_setgroups, scalar @newgids, pack("i*", @newgids))
or die "setgroups: $!";
你可能需要按照 Perl 安装指导里描述的那样运行 h2ph,检查 syscall.ph 是否存在。有些系统可能要求使用 "II" 模板。更头疼的是,syscall 假设 C 类型 int,long,和 char* 的尺寸是相等的。希望你不要把 syscall 当作移植性的体现。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-28372-17.html