14

「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 ではありませんか? もしそうなら、WTH ?! キーボード入力は標準入力を介して送信されたと思いました。

興味深いことに、ls -l * | lessファイルのロードが完了した後でも、キーボードを使用して上下にスクロールできますがls -l * | vi、そうすると、標準入力から読み取らないため、vi が怒鳴ります。大きなアイデアは何ですか?stderr がエラーを画面に報告する方法とキーボードから読み取る方法の両方である、この奇妙な新しい土地にどうやってたどり着いたのでしょうか? もうカンザスにはいないと思う...

4

4 に答える 4

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

対話型端末にログインすると、3 つの標準ファイル記述子はすべて同じもの、つまり TTY (または疑似 TTY) を指します。

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

慣例により、0と から読み書きし1ます2。しかし、それ以外のことをすることを妨げるものは何もありません。

シェルが実行されると、 のファイル記述子からのファイル記述子へのls -l * | lessパイプが作成されます。明らかに、ファイル ディスクリプタからユーザーのキーボード入力を読み取ることができなくなりました。TTY を取得しようとしますが、可能です。ls1less0less0

lessが端末から切り離されていない場合はopen("/dev/tty")、TTY が与えられます。

しかし、それが失敗した場合...どうすればいいですか? リダイレクトされなかった場合にファイル記述子が接続されるのと同じものにlessファイル記述子が接続されていると仮定して、TTY を取得する最後の試行を行います。20

これはフェイルプルーフではありません:

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

ここでlessは、独自のセッションが与えられ (したがって、端末のアクティブなプロセス グループの一部ではなくなり、open("/dev/tty")失敗する原因になります)、そのファイル記述子2が変更されlessました。TTY に出力しているにもかかわらず失敗するため、すぐに終了します。ユーザー入力を取得します。

于 2009-09-17T21:08:50.713 に答える
3

ええと...まず、open()「/dev/tty」を開く呼び出しを見逃しているようです。open() の呼び出しが失敗した場合、ファイル記述子 2 のみを使用します。標準の Linux システム、およびおそらく多くの Unice では、「/dev/tty」が存在し、失敗する可能性はほとんどありません。

第二に、上部のコメントは、ファイル記述子 2 にフォールバックする理由についての限定的な説明を提供します。私の推測では、stdinリダイレクトされない限り、とにかく '/dev/tty/' にほとんど接続されています。また、 stdin および/または stdout の最も一般的なリダイレクト (パイプまたは/を介した) から、 の場合はそれほど頻繁ではありませんが、使用しても「キーボード」に接続される可能性が最も高い可能性があります。stdoutstderr<>stderrstderr

于 2009-09-17T20:59:11.963 に答える
2

とは少し異なるソースを引用していますが、同じ質問と最終的にはそれを尋ねた人からの回答がlinuxquestionslessにあります。いいえ、私はそのほとんどを理解していないので、それ以上のことはできません:)

于 2009-09-17T21:01:07.530 に答える
-2

キーボード入力を FD 2 に送信する Linux 固有の機能のようです。

于 2009-09-17T21:02:23.533 に答える