为什么要复制文件描述符却从未使用它?

3

以下是相关内容:

extern fin;
char line[64];

if (argc<2 || ttyn(0)!='x') {
        write(1, "goto error\n", 11);
        seek(0, 0, 2);
        return;
}
seek(0, 0, 0);
fin = dup(0);

请注意,整个代码中只有上面部分出现了“fin”。那么为什么要复制标准输入(在这种情况下是文件/脚本)并将其存储在fin中而不使用它呢?
您可以在此处找到完整的代码http://v6shell.org/history/goto.c,带有语法高亮的代码请参见http://pastebin.com/uAvANLdR 附注:这是K&R-C。 这里描述了使用的dup命令:http://man.cat-v.org/unix-6th/2/dup 更新: 我发现,实际上需要用到getchar命令。请看这里http://man.cat-v.org/unix-6th/3/getchar 但我仍然不明白为什么需要它。现在有人能解释一下吗?

4
请注意,fin 是一个外部变量,可能在其他地方被使用。 - P.P
你能想象它在哪里以及为什么会被使用吗?这段代码是Unix命令goto的源代码。 - Joey
1
你尝试在代码中搜索过吗? - Etan Reisner
它用于命令getchar!看这里:http://man.cat-v.org/unix-6th/3/getchar 但我仍然不明白为什么需要它。 - Joey
也许在调用能关闭另一个文件描述符的函数之前,您需要它,以便拥有描述符的实时副本。正如已经注释的那样,“fin”被声明为“extern”,因此它可以在其他地方使用。 - Luis Colorado
2个回答

3
如果您查看getchar(3)的手册页面,http://man.cat-v.org/unix-6th/3/getchar,会发现有这样一小段:

与此例程相关的是一个名为fin的外部变量,它是一个包含缓冲区的结构,例如在getc(III)下描述。

因此,如果我们更仔细地看getc(3),http://man.cat-v.org/unix-6th/3/getc,我们会发现:
struct buf {
  int fildes;     /* File descriptor    */
  int nleft;      /* Chars left in buffer */
  char *nextp;    /* Ptr to next character */
  char buff[512]; /* The buffer */
};

goto.c中的代码现在通过告诉编译器"fin"是int类型来实现了一个hack。实际上,"fin"的类型是struct buf,但由于"int filedes;"是该结构体的第一个成员,因此该代码实际上执行的与以下代码相同:

extern struct buf fin;

...

seek(0, 0, 0);
fin.fildes = dup(0);

正如我所说,这是一种“hacky”解决方案,但是这段代码似乎非常陈旧,其中有许多goto语句。


1
原始代码可以在此处找到:http://minnie.tuhs.org/Archive/PDP-11/Distributions/research/Dennis_v6/v6src.tar.gz。`getchar()`的源代码位于`s4/getchr.s`中。如果tarball中的时间戳是正确的,那么源文件应该是来自1975年。因此,不足为奇的是,该代码不遵循今天被认为是“最佳实践”的规范 - 该代码来自迷你计算机的黎明时期。 - Michael Burr
只有路径中的PDP-11表明这是一个非常过时的代码。而Dennis_v6可能反映了Unix v6版本。 - Luis Colorado

1

我能想到的一个原因是,如果文件描述符0(标准输入)是管道(2)的读取端,并且在execve(2)调用后关闭,那么尝试向该管道写入数据的任何人都将继续被阻塞,并且不会收到SIGPIPE信号。


我刚才查看了代码并得出结论,这可能只是从外部使用。否则,程序将无法链接,必须在某处进行定义。 - s1kam4n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接