2009-09-17 13 views
12

「less」ユーティリティのコード、具体的にはキーボード入力の仕組みを見ていきます。興味深いことに、ttyin.cのライン80に、それはからの読み取りにファイル記述子を設定します。lessはキーボード入力をstderrから受け取りませんか?

 /* 
     * 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標準エラー出力をファイルではありませんか?もしそうなら、WTH ?!私はキーボード入力がstdinを通して送られたと思った。ファイルのロードが完了した後

興味深いことに、あなたがls -l * | lessを行う場合でも、あなたはまだ上下にスクロールするために、キーボードを使用することができますが、あなたがls -l * | viをすれば、それが標準入力から読み取らないので、その後、viがあなたに叫ぶだろう。大きなアイデアは何ですか?私はstderrがスクリーンにエラーを報告する方法とキーボードから読む方法の両方であるこの奇妙な新しい土地でどうして終わりましたか?私はもうカンザスにいるとは思わない...

+0

ところで、 'ls -l * | vim -'は、同様の魔法を実行します。 – ephemient

答えて

19
 
$ 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 

にキーボード入力を送信Linuxの特定の機能のように見えます中間の端末では、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から読み取られ、12に書き込みます。しかし、何も私たちが他のことをするのを妨げるものはありませ

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

lessが端末から取り外されていない場合、open("/dev/tty")はTTYを返します。

しかし、失敗した場合はどうすればいいですか? lessは、ファイルディスクリプタ2が、ファイルディスクリプタ0がリダイレクトされていない場合と同じものに添付されていると仮定して、TTYの取得を最後に試行します。

この failproofではありません。ここで

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

lessは独自のセッションを与えられていない(ので、それは失敗するopen("/dev/tty")を引き起こし、もはや端末のアクティブプロセスグループの一部である)、およびそのファイルデスクリプタ2が変更されました–今すぐlessが終了しました。これはTTYに出力していますが、ユーザー入力を取得できないためです。

+3

+1、非常に完了しました。 –

+0

ああ、私は今それを参照してください。 stderrは実際に端末に接続されているファイル記述子を突き止めるだけであるため、気に入っているように読み書きできます。カッコいい!一生懸命にありがとう、ありがとう。 – Michael

+0

ファイル記述子 '2'は書き込み専用にオープンしませんか? –

2

まあ...まず、 '/ dev/tty'を開くopen()コールが欠落しているようだ。 open()の呼び出しが失敗した場合にのみファイル記述子2を使用します。標準的なLinuxシステムで、おそらく多くのUnixでは '/ dev/tty'が存在し、失敗する可能性は低いです。

私の推測ではstdinstdout、およびstderrはほとんど「は/ dev/ttyの/」に接続されていることである彼らは記述子2をファイルにフォールバックする理由として第二に、一番上のコメントは、説明の限られた量を提供とにかく、リダイレクトされない限り。また、stdinやstdout(配管経由または</>)の最も一般的なリダイレクトは、stderrの頻度が少なくなるため、stderrを使用すると「キーボード」に接続する可能性が最も高くなります。

+0

stderrを使用する理由は、stdin/stdoutが産卵シェルによって作成されたパイプである可能性が高いからです。パイプの出し入れはノープですが、動作します。しかし、lessコマンドのstderrをリダイレクトすることは、特に価値がなく、実行される可能性は低いです。だから、stderrが "本当に"ターミナルデバイスであることを賭けることは合理的な推測です。 –

1

尋ねられた人から最終的に同じ質問がlinuxquestionsにありますが、少し異なるソースをlessから引用していますが、そして、いや、私はそれを超えて助けることができないので、それのほとんどを理解していない:)

-2

にログインしたときには、FD 2.

+1

はっきりと偽です。他のUNIXでこれを試してみてください。 – ephemient

関連する問題