一尘不染

从stderr获得键盘输入的更少?

linux

我正在研究“ less”实用程序的代码,特别是它如何获取键盘输入的代码。有趣的是,在ttyin.c的第80行,它将文件描述符设置为从以下文件读取:

     /*
      * Try /dev/tty.
      * If that doesn't work, use file descriptor 2,
      * which in Unix is usually attached to the screen,
      * but also usually lets you read from the keyboard.
      */
  #if OS2
      /* The __open() system call translates "/dev/tty" to "con". */
      tty = __open("/dev/tty", OPEN_READ);
  #else
      tty = open("/dev/tty", OPEN_READ);
  #endif
      if (tty < 0)
          tty = 2;

文件描述符2不是stderr吗?如果是这样,是什么?我以为键盘输入是通过stdin发送的。

有趣的是,即使这样做ls -l * | less,在文件加载完成后,您仍然可以使用键盘上下滚动,但是如果这样做ls -l * | vi,则vi会大吼大叫,因为它不会从stdin中读取。有什么大主意?我如何最终进入这个陌生的新大陆,在那里stderr既是向屏幕报告错误又是从键盘读取信息的一种方式?我不认为我已经在堪萨斯州了…


阅读 289

收藏
2020-06-03

共1个答案

一尘不染

$ ls -l / dev / fd /
lrwx ------ 1 me me 64 2009-09-17 16:52 0-> / dev / pts / 4
lrwx ------ 1 me me 64 2009-09-17 16:52 1-> / dev / pts / 4
lrwx ------ 1 me me 64 2009-09-17 16:52 2-> / dev / pts / 4

在交互式终端上登录时,所有三个标准文件描述符都指向同一件事:您的TTY(或伪TTY)。

$ ls -fl / dev / std {in,out,err}
lrwxrwxrwx 1根根4 2009-09-13 01:57 / dev / stdin-> fd / 0
lrwxrwxrwx 1根根4 2009-09-13 01:57 / dev / stdout-> fd / 1
lrwxrwxrwx 1根根4 2009-09-13 01:57 / dev / stderr-> fd / 2

按照惯例,我们读出0和写入12。但是,没有什么可以阻止我们采取其他行动。

当你的shell运行时ls -l * | less,它创建了一个从管道ls的文件描述符1less的文件描述符0。显然,less它不再能够从文件描述符中读取用户的键盘输入0-它会设法将TTY重新找回。

如果less尚未从终端上拆下,open("/dev/tty")将给它TTY。

但是,如果失败了,该怎么办? less尝试最后一次获取TTY,假设文件描述符2附加到了文件描述符附加的同一对象0上(如果未重定向的话)。

不是 故障预防:

$ ls -l * | 少setsid 2> / dev / null

在这里,less为其分配了自己的会话(因此它不再是终端活动进程组的一部分,从而导致open("/dev/tty")失败),并且其文件描述符2已更改-
现在less立即退出,因为它正在输出到TTY,但无法获取任何用户输入。

2020-06-03