私の言葉は正しいですか?キーボードのすべての入力は制御端子?これは、プログラムが制御端末なしで実行されるとユーザー入力を受け取ることができないことを意味します。これはLinuxのすべてのプログラムに適用されますか?
アップデート#1:質問を明確にするために私のPythonポケットベルモジュール標準入力リダイレクト時に競合が発生する:
$ ./pager.py < README.rst
...
File "pager.py", line 566, in <module>
page(sys.stdin)
File "pager.py", line 375, in page
if pagecallback(pagenum) == False:
File "pager.py", line 319, in prompt
if getch() in [ESC_, CTRL_C_, 'q', 'Q']:
File "pager.py", line 222, in _getch_unix
old_settings = termios.tcgetattr(fd)
termios.error: (25, 'Inappropriate ioctl for device')
これは、キーボード入力をに設定するために記述子を取得しようとするためですfd = sys.stdin.fileno()
。リダイレクト後、対応するstdin
ファイル記述子はキーボード入力に関連付けられなくなり、設定しようとするとinput-output control
エラーが発生します。
これを得るように言ったが、controlling terminal
どこから出たのか分からないですね。ユーザーから実行中のプロセスにシグナルを送信することは一種のチャンネルであることを知っていますが、同時にシグナルなしでプロセスを実行できます。
だから質問は - 常にキーボード入力を読む必要がありますかcontrolling terminal
?ポケットベルプロセスがポケットベルプロセスなしで実行されるとどうなりますか?キーボード入力はまだユーザーにとって重要ですか?別のソースからインポートする必要がありますか?
答え1
習慣。ターミナルアプリケーションは、使用しているキーボードターミナルに対応するデバイスファイル(Linuxの場合はシリアルデバイス、疑似ターミナルデバイスの場合.../dev/ttyS0
などのファイル)からキーボード入力を読み込みます。/dev/ttyUSB0
/dev/pts/0
デバイスは必ずしも必要ではありません。制御端子プロセス(またはその問題に対するすべてのプロセス)。
デバイスファイルに対する読み取り権限があり、cat /dev/pts/x
相手端末に入力された内容(ある場合)を読み取ることができる限り、これを行うことができます。
実際には、プロセスを制御するターミナルであり、そのプロセスがその端末のフォアグラウンドプロセスグループにない場合、プロセスは通常プロセスからデータを読み取ろうとしたときに中断されます(フォアグラウンドプロセスグループに存在する場合、プロセスは中断されます。 )。停止しました)。^C
//送信すると、^Z
プロセスが端末デバイスからデータを読み取るかどうかに関係なく、SIGINT / SIGTSTP / SIGQUITを受け取ります。^\
最終装置が最終装置でなければ、これは起こらないでしょう。制御端子プロセス名(プロセスが別のセッションの一部である場合)制御端子それについて。これは職業管理対話型シェルで実装されたメカニズム。 SIGTTIN / SIGTTOUおよびSIGINT / SIGTSTP / SIGQUIT信号に加えて、制御端末は端末がハップを停止したときにSIGHUP送信に参加します。これは/dev/tty
リダイレクトされるttyデバイスでもあります。
とにかく、これは端子入力にのみ機能します。シリアルケーブルを介して接続されたターミナルデバイスのように実際に動作するか、X11ターミナルエミュレータのようにエミュレートされるか(擬似ターミナルデバイスを使用する) xterm
、Linux対話型プロセスを持つ仮想ターミナルのようにカーネルによってエミュレートされます。/dev/tty<x>
(そして標準のターミナルインターフェースよりも多くの機能をサポートします)
Xサーバなどのアプリケーションは、通常、キーボードドライバからキーボード入力を取得します。 Linuxでは、汎用入力抽象化レイヤを使用します。 Xサーバーは、接続されたアプリケーションにキーボードイベントを配信するイベントメカニズムを提供します。たとえば、xterm
X11キーボードイベントは受信され、擬似端末デバイスのマスターに文字を書き込むことに変換され、これはxterm
その擬似端末スレーブから読み取られたときにその文字を読み取る「内部的に」実行されるプロセスに変換されます(/dev/pts/x
)。 。
今そんなことはありません端末アプリケーション。私たちが言ったこと端末アプリケーション上記は、端末に表示され、端末(vi
インタラクティブシェルやシェルなど)から入力を受け取ると予想される端末で一般的に使用されるアプリケーションですless
。ただし、すべてのアプリケーションは端末によって制御でき、ファイルまたはそのstdin / stdout / stderrを読み書きするすべてのアプリケーションは端末装置へのI / Oを実行できます。
たとえば、firefox
実行中のシェルからユーザーI / O用にXサーバーに接続するアプリケーションは、xterm
firefox
制御端子シェル親から。^C
シェルがフォアグラウンドで開始すると、端末で終了します。また、ファイルのファイル記述子0、1、2(stdin、stdout、およびstderr)を開きます/dev/pts/<x>
(再度シェルの親から継承されます)。そしてfirefox
fd 2(stderr)に何らかのエラーを記録する可能性が高いです(バックグラウンドに置いてエンドデバイスを設定するとstty tostop
SIGTTOUを受信して中断されます)。
対照的に、firefox
XセッションマネージャまたはWindows管理者によって実行されると(一部のメニューでFirefoxアイコンの一部をクリックした場合)、制御端末が取得されず、ファイル記述子が端末に接続されません(ps -fp <firefox-pid>
ディスプレイが表示されます)。ファイルディスクリプタや表示がない?
ためtty
です。)しかし、それをブラウズすると、エンドデバイスへのいくつかのI / Oを引き続き実行できます。フラグなしでファイルを開き、セッションリーダーであり、まだセッションを接続していない場合、デバイスは最終的にプロセスの制御端末になります。lsof -p <firefox-pid>
/dev/pts/*
/dev/tty*
file:///dev/pts/<x>
firefox
O_NOCTTY
/dev/pts/<x>
firefox
追加資料:
編集する
いくつかの問題を明確にし、いくつかのコンテキストを追加するために編集されました。
上記のことから、プロセスは、必要なすべての端末デバイス(プロセスがフォアグラウンドプロセスグループに属していない場合は制御端末を除く)から入力を読み取ることができることを明らかにすることができますが、実際には興味のあるものではありません。
あなたの質問は、対話型ターミナルアプリケーションの場合、stdinがターミナルを指していなくなったときにユーザー入力を取得できる場所です。
tr
アプリケーションは標準入力から入力を受け取り、標準出力に書き込むのが好きです。 stdin/stdout がもう一方の端に端末がある tty デバイスの場合、ユーザーからデータを読み取るか、ユーザーにデータを書き込むため、対話型になります。
一部の端末テキストエディタ(たとえばed
、ex
いくつかの実装)は、stdinがもはや端末ではなくなったときにstdinから入力を読み続けてスクリプトを書くことができます。vi
ページャは、ユーザーの入力が端末ではなく(少なくとも出力がまだ端末に到達している場合)、ユーザーとの対話が必要な一般的なアプリケーションです。だから別のチャンネルが必要です。これ端末装置はユーザ入力を受け入れる。問題は、どの端末デバイスを使用すべきかです。
はい、制御端末でなければなりません。なぜなら、それは一般に制御端末が意味するバイヤーであるからです。 Ctrl-C / Zを押すと、デバイスはポケットベルにSIGINT / SIGTSTPを送信するため、ポケットベルが同じ端末から別のキーストロークを読み取るのは妥当です。
制御端末からファイル記述子を取得する一般的な方法は、ファイルを開いて/dev/tty
そこにリダイレクトすることです。 (プロセスがeuidを変更して元のデバイスへの読み取りアクセスを持っていなくても、これはうまくいきます。これははるかに優れています。元のデバイス(とにかくポータブルではない)へのパスを見つけるよりも)。
stdinがttyデバイスの場合でも、一部のポケットベルはそれを気に入ったり開くことができますless
(most
最終/dev/tty
的にless < /dev/ttyS0
シリアル経由で送信される内容は、ターミナルエミュレータ内で見ることができます)。
オープンに/dev/tty
失敗した場合は、通常端末を制御できないためです。誰かがこれがあなたが明示的に持っているからだと言うかもしれません。優れた端末でユーザー対話を試みてはいけませんが、端末装置を制御することはできませんが、stdin / stdoutがまだtty装置であり、まだユーザー対話を望む潜在的な(異常な)状況があります(例:initrdの緊急シェル)。
したがって、端末の場合は、標準入力からユーザー対話を取得する方法に戻ることができます。
stdoutが端末デバイスであることを確認したいと言うこともできます。そしてman -l /dev/stdin < /dev/ttyS0 > /dev/ttyS1
これは、制御装置と同じ最終装置を指しますが(ユーザーの対話のためにポケットベルを作成したくないなど、実行中の作業を考慮するためにman
)、特に簡単ではないことを考慮すると、面倒になる価値はありません。持ち運びが良く。これはまた、標準出力が端末装置である限り、ページャが対話する可能性がある他の奇妙なユースケースを破る可能性があります。