我遇到了一个使用非常旧版本的程序线路噪声图书馆。一切都write()
完成了STDIN_FILENO
,像这样:
write(STDIN_FILENO,prompt,plen)
write
失败并返回 -1 并errno
设置为EBADF
。我编写了一个 C 程序,该程序在系统启动时在交互启动之前/etc/init.d/rcS
依次执行。 C 程序列出目录,其输出为:Busybox init
sh
/proc/self/fd
l-wx------ 1 root root 64 Jan 1 00:00 2 -> /dev/console
l-wx------ 1 root root 64 Jan 1 00:00 1 -> /dev/console
lr-x------ 1 root root 64 Jan 1 00:00 0 -> /dev/console
正如您所看到的 0 没有w
设置位,我认为这就是write
失败的原因。但是,正常sh
shell 启动后:
lrwx------ 1 root root 64 Jan 1 00:00 2 -> /dev/ttyS0
lrwx------ 1 root root 64 Jan 1 00:00 1 -> /dev/ttyS0
lrwx------ 1 root root 64 Jan 1 00:00 0 -> /dev/ttyS0
现在 0 已w
设置。为什么会发生这种情况?
答案1
因为你可以拥有多个终端设备。
因此,作为参数专门getty
调用。ttyS0
所以它使用自己的代码来初始化所有的FD。这恰好与/dev/console
打开init
.人们可能会猜测getty
用 打开 tty 一次O_RDWR
,然后dup
引用 FD。
我可以看到一个明显的原因代码这样工作。 agetty
也可以用-
stdin 来调用。所以始终使用dup()
是最简单的实现。
我不确定为什么支持该选项。标准 System V 不一定使用或支持它inittab
。似乎符合BSD 下使用的旧方法,其中init
将终端设备作为打开的 FD 而不是参数传递。旧方法是init
初始化所有 FD(关联,仅注意stderr
下一个版本中添加的 2 个 FD)。
由于问题被编辑为指定 busybox,并且提到了 cttyhack,因此在 busybox 的情况下明显的解释是“它使代码更小”。这也是历史 Unix 代码的一个驱动特征。