这perldoc -f syscall
就是说:
有一个问题
syscall(SYS_pipe())
:它返回它创建的管道的读取端的文件号,但是没有办法检索另一端的文件号。您可以通过使用来避免此问题pipe
。
但是,这并没有检查出来。syscall
与SYS_pipe
任何其他系统调用一样工作,我完全能够检索两端:
perl -e '
require "syscall.ph";
my $p = pack "i2";
syscall SYS_pipe(), $p;
print join(",", unpack "i2", $p), "\n"
'
3,4
那是在linux上,在openbsd和solaris上是一样的,只要你注意一些差异(在solaris上,系统调用实际上是pipe2(2)
, so syscall 42, $p, 0
)。
fs/pipe.c
linux内核源代码中的评论说:
/* * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way Unix traditionally does this, though. */
那么这种“传统”方式是什么?是否有任何现代系统仍然如此?
Perl 文档中的这一段是在 1997 年 9 月的Perl 5.004_04中引入的。我不熟悉当时特定的 Unix 内核的处理方式
SYS_pipe
。但是 Unix V6 中的原始实现在寄存器中返回了两个文件描述符,然后库的pipe
实现将这些值存储在一个整数数组中。V6pipe(2)
手册页简要记录了这一点:统一各种实现的 Linux 补丁上的提交消息
sys_pipe
也提到了这一点:大概 Perl 注释
syscall
来自这样一个事实,即传统SYS_pipe
在任何寄存器中返回读取的文件描述符,用于返回函数的结果(上面的 r0,PC 上的 AX/EAX/RAX 等),可以从 Perl 代码访问,但您将无法读取 r1 中返回的值。我不知道任何现代系统仍然以这种方式返回文件描述符。我也不清楚 1997 年有多少 Unix 系统以这种方式运行。我得到的印象至少 Solaris (2.6) 没有。