私の知識によると、/dev/pts
ファイルは、sshまたはtelnetセッション用に作成されます。
/dev/pts
には何も保存されていません。このファイルシステムは純粋にメモリ内にあります。
/dev/pts
のエントリは pseudo-terminals (略してpty)です。 Unixカーネルには terminals の一般的な概念があります。端末は、アプリケーションが 端末装置 を介して出力を表示し、入力を受け取る方法を提供します。プロセスにはcontrolling terminalがある場合があります—テキストモードアプリケーションの場合、これがユーザーとのやり取りです。
端末は、ハードウェア端末(「tty」、「teletype」の略)または疑似端末(「pty」)のいずれかです。ハードウェア端末は、シリアルポート(ttyS0
、…)またはUSB(ttyUSB0
、…)などのインターフェイス、またはPC画面とキーボード(tty1
、…)を介して接続されます。疑似端末は、アプリケーションである端末エミュレータによって提供されます。疑似端末には、次のタイプがあります。
プログラムが書き込み用に端末を開くと、そのプログラムからの出力が端末に表示されます。複数のプログラムが同時に端末に出力するのが一般的ですが、出力のどの部分がどのプログラムからのものであるかを見分ける方法がないため、これは時々混乱する可能性があります。制御端末に書き込もうとするバックグラウンドプロセスは、 SIGTTOUシグナルによって自動的に中断 になる可能性があります。
プログラムが読み取り用の端末を開くと、ユーザーからの入力がそのプログラムに渡されます。複数のプログラムが同じ端末から読み取っている場合、各文字はプログラムの1つに独立してルーティングされます。これはお勧めできません。通常、特定の時間に端末からアクティブに読み取るプログラムは1つだけです。 フォアグラウンド にないときに制御端末から読み取ろうとするプログラムは SIGTTINシグナルによって自動的に中断 です。
実験するには、ターミナルでtty
を実行して、ターミナルデバイスを確認します。 /dev/pts/42
だとしましょう。別のターミナルのシェルでecho hello >/dev/pts/42
を実行します。文字列hello
が他のターミナルに表示されます。ここでcat /dev/pts/42
を実行し、他のターミナルに入力します。そのcat
コマンド(他の端末を使いにくくする)を強制終了するには、 Ctrl+C。
別の端末への書き込みは、通知を表示するのに役立つ場合があります。たとえば write
コマンドはそれを行います。別の端末からの読み取りは通常行われません。
_/dev/pts
_のファイルは「疑似tty」です。それらはある程度名前付きパイプに似ていますが、VT-100などの古いシリアル接続端子も模倣しています。疑似ttyは、キーボードからプログラムへ、およびプログラムから出力デバイスへバイトを転送する作業を行います。これは簡単に聞こえます。しかし、それはあなたの明確な質問に答えます。たとえば、カーネルは_/dev/pts/0
_に何も格納しません。疑似ttyに接続されているプログラムのstdoutからのバイトのストリームだけが入り、stdinが同じ疑似ttyに接続されているプログラムはそれらのバイトを読み取ります。
Pseudo-ttysはまた、これらのバイトストリームに間接層を挿入します。カーネルは「Control-C」、「Control-D」、「Control-U」などの特別な値のバイトを検査し(すべて構成可能、_man stty
_を参照)、SIGINTを送信し、ファイルの終わりを設定できます。 stdinで、または入力の行を消去します。どこかにバッファリング機能もあるので、「何も保存しない」というのは少し間違っていますが、数キロバイトしかありません。
カーネルは出力のバイト値を検査し、改行(ASCII改行、LFまたは_"\n"
_)をキャリッジリターンと改行(CRLFまたは_"\r\n"
_)、またはシリアル端末ハードウェアが必要とする任意のバイト疑似ttyの間接指定により、ハードウェアからの独立が可能になります。
疑似ttyでは、「ボーレートの設定」、「パリティの設定」などのすべてのioctl()
システムコールも許可されており、おそらくそれらに対して何も行いません。これにより、VT-100、ADM-3、およびWyseの日に書き戻されたプログラムがエラーなしで機能し続けます。 pseudo-ttysデバイスドライバーであるソフトウェアは、ハードウェアのように動作します。
疑似ttyはsshd
およびtelnet
で使用できますが、ターミナルエミュレーター(xterm
またはrxvt
など)とシェルの間でも使用されます。これは通常、xterm内で実行されます。
Linuxと多くのUnixには疑似ttyがあります。プラン9にはありません。疑似ttyは、シリアルケーブルで接続されたハードウェア端末の時代から残っている、ちょっとした遺物です。
_/dev/
_は、デバイスファイル用の特別なディレクトリです。これらは抽象化であり、ディスク上の実際のファイルではありません。ディレクトリはブート時に読み込まれ、カーネルとユーザースペースデーモンudevd
によって作成および破棄される既存のデバイスインターフェイスを反映するように変更される可能性があります。
そのように表されるデバイスの多くは仮想です。これには、コンソールデバイスである_/dev/pts
_のエントリが含まれます。これが、リモートセッション用に作成される理由です。ローカルGUI端末を開いたときにも作成されます。
ファイルとして開くことはできますが、あまり役に立ちません。シェルが接続されている_/dev/pts
_ノードを取得するには、tty
を使用します。
_> tty
/dev/pts/4
_
次に、他のコンソールに切り替えてみてください。
_> echo "duck!" > /dev/pts/4
_
賢い。今試してください:
_> cat /dev/pts/4
_
次に、/ dev/pts/4にあるシェルを使用してみます。反対側のcat
を終了するまで立ち往生していますが、pts/4で入力するほとんどの文字は通過します(たとえば、「hello world」を試してみると、hl
がオンになりますcat
コンソールのpts/4および_Ello Word
_)。
私の推測では、デバイスはシェルから入力を受け取り、システムを介して出力しています。これは、画面に表示されるものです。シェルはハードウェアを処理していないので、システムはそうです。 _strace bash
_を試してください(それが何であるかわからない場合は_man strace
_を参照してください); bashが起動すると、予備の呼び出しが発生します。ここでキーを押し始めます:
_read(0, "h", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "h", 1h) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "e", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "e", 1e) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "y", 1) = 1
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "y", 1y) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
_
入力するすべての文字に対して、標準入力からの読み取りと標準出力への書き込みがあります。しかし、シェルの標準的な接続は何ですか?次に、GUI端末でstrace
を試してください。名前がわからない場合は、名前を確認する必要があります。 KDEではkonsole
で、GNOMEには_gnome-terminal
_があります。そのstrace
からの出力はおそらくより不可解です-鉱山にはpoll()
とrecvfrom()
がたくさんあります。書き込みは表示されませんが、別の端末からcat
トリックをプルすると、入力したときに、catによって読み取られたキーストロークがstrace出力でまったく応答しないことに気付くでしょう-端末はそれらを受信していません。したがって、GUI端末アプリと猫は、シェルが出力している同じデバイスからの読み取りを競合しています。