在“传统”Unix 中,pipe(2) 系统调用是如何工作的

在“传统”Unix 中,pipe(2) 系统调用是如何工作的

这就是说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),所以syscall 42, $p, 0)。

fs/pipe.cLinux 内核源码中的评论说:

/*
 * sys_pipe() is the normal C calling standard for creating
 * a pipe. It's not the way Unix traditionally does this, though.
 */

那么什么是“传统”方式呢?是否有任何现代系统仍然存在这种情况?

答案1

Perl 文档中的这一段是在Perl 5.004_041997 年 9 月。我不熟悉SYS_pipe当时特定的 Unix 内核的处理方式;但 Unix V6 中的原始实现在寄存器中返回两个文件描述符,然后库的pipe实现将这些值存储在整数数组中。V6pipe(2)联机帮助页简要记录这一点:

(管道 = 42。)
系统管道
(读取r0中的文件描述符)
(写入r1中的文件描述符)

提交消息于Linux补丁其中统一了各种sys_pipe实现也提到了这一点:

传统的 UNIX 实现通常返回寄存器中的两个文件描述符

大概 Perl 的注释syscall来自于这样的事实:传统SYS_pipe上,无论使用什么寄存器来返回函数的结果(上面的 r0、PC 上的 AX/EAX/RAX 等),都会返回读取的文件描述符,这可以从 Perl 代码中访问,但您无法读取 r1 中返回的值。

我不知道有哪个现代系统仍然以这种方式返回文件描述符。我也不清楚 1997 年有多少 Unix 系统有这种行为;我的印象是至少 Solaris (2.6) 没有。

相关内容