私の知る限り、/dev/pts
ファイルは ssh または telnet セッション用に作成されます。
答え1
には何も保存されません/dev/pts
。このファイルシステムは純粋にメモリ内に存在します。
のエントリー/dev/pts
は擬似端末(略してpty)。Unixカーネルには、端末端末はアプリケーションが出力を表示したり、端末を介して入力を受け取ったりする方法を提供します。端末装置プロセスには、制御端末— テキスト モード アプリケーションの場合、これはユーザーと対話する方法です。
端末は、ハードウェア端末 (“tty”, “teletype” の略) または擬似端末 (“pty”) のいずれかです。ハードウェア端末は、シリアル ポート ( ttyS0
、…) や USB ( ttyUSB0
、…) などのインターフェイス、または PC 画面とキーボード ( tty1
、…) を介して接続されます。擬似端末は、アプリケーションである端末エミュレータによって提供されます。擬似端末には、次のような種類があります。
- xterm、gnome-terminal、konsole などの GUI アプリケーションは、キーボードとマウスのイベントをテキスト入力に変換し、出力を特定のフォントでグラフィカルに表示します。
- screen や tmux などのマルチプレクサ アプリケーションは、別の端末との間で入出力を中継し、テキスト モード アプリケーションを実際の端末から切り離します。
- sshd、telnetd、rlogind などのリモート シェル アプリケーションは、クライアント上のリモート ターミナルとサーバー上の pty 間の入力と出力を中継します。
プログラムが書き込みのために端末を開くと、そのプログラムからの出力が端末に表示されます。複数のプログラムが同時に端末に出力することはよくありますが、出力のどの部分がどのプログラムから来たのかが分からないため、混乱が生じることがあります。制御端末に書き込もうとするバックグラウンドプロセスは、SIGTTOU信号により自動的に停止。
プログラムが読み取り用に端末を開くと、ユーザーからの入力はそのプログラムに渡されます。複数のプログラムが同じ端末から読み取りを行っている場合、各文字は独立していずれかのプログラムにルーティングされます。これは推奨されません。通常、特定の時点で端末から読み取りを行っているプログラムは1つだけです。前景はSIGTTIN信号によって自動的に停止される。
実験するには、tty
ターミナルで を実行して、ターミナルデバイスが何であるかを確認します。 であるとします/dev/pts/42
。別のターミナルのシェルで を実行しますecho hello >/dev/pts/42
。文字列hello
が他のターミナルに表示されます。次に、 を実行してcat /dev/pts/42
、他のターミナルに入力します。そのcat
コマンドを終了するには (他のターミナルが使いにくくなります)、Ctrl+を押しますC。
別の端末に書き込むと、通知を表示するために便利な場合があります。たとえば、write
コマンドはそれを実行します。別の端末からの読み取りは通常は行われません。
答え2
内のファイルは/dev/pts
「疑似端末」です。ある程度は名前付きパイプに似ていますが、VT-100 のような古いシリアル接続端末も模倣しています。疑似端末は、キーボードからプログラムへ、プログラムから出力デバイスへバイトを転送する作業を行います。これは単純に聞こえます。しかし、これで明確な質問への回答になります。/dev/pts/0
たとえば、カーネルは に何も保存しません。疑似端末に接続されたプログラムの stdout からのバイト ストリームのみが入り、stdin が同じ疑似端末に接続されているプログラムはそれらのバイトを読み取ります。
疑似 tty は、これらのバイト ストリームに間接レイヤーも追加します。カーネルはバイトを検査して、「Control-C」や「Control-D」や「Control-U」などの特別な値 (これらはすべて設定可能です。 を参照man stty
) を探し、SIGINT を送信したり、stdin にファイルの終わりを設定したり、入力の行を消去したりできます。また、どこかにバッファリング機能があるため、「何も保存しない」という私の表現は多少間違っていますが、数キロバイトの違いだけです。
カーネルは出力のバイト値を検査し、改行 (ASCII ラインフィード、LF または"\n"
) を 2 バイト、復帰とラインフィード (CRLF または"\r\n"
)、またはシリアル端末ハードウェアが必要とする任意のバイトに変換するなどの処理を実行できます。疑似 tty の間接化により、ハードウェアからの独立が可能になります。
疑似 tty は、すべての「ボーレートの設定」、「パリティの設定」などのioctl()
システム コールも許可しますが、おそらくそれらに対して何もしません。これにより、VT-100、ADM-3、Wyse などの時代に書かれたプログラムがエラーを出さずに動作し続けることができます。ソフトウェア、疑似 tty デバイス ドライバーは、ハードウェアのように動作します。
疑似 tty はsshd
およびで使用されることがありますが、端末エミュレータ ( やなど) と、通常は xterm 内で実行されるシェルtelnet
の間でも使用されます。xterm
rxvt
Linux や多くの Unix には疑似 tty があります。Plan 9 にはありません。疑似 tty は、シリアル ケーブルで接続されたハードウェア端末の時代から残った、いわば遺物です。
答え3
/dev/
デバイス ファイル用の特別なディレクトリです。これらは抽象化されており、ディスク上の実際のファイルではありません。このディレクトリは起動時に作成され、カーネルとユーザー空間デーモンによって作成および破棄される既存のデバイス インターフェイスを反映するように変更される可能性がありますudevd
。
このように表されるデバイスの多くは仮想です。これには/dev/pts
、コンソール デバイスである のエントリが含まれます。これが、リモート セッション用に 1 つ作成される理由です。また、ローカル GUI 端末を開いたときにも 1 つ作成されます。
あまり役に立ちませんが、ファイルとして開くこともできます。/dev/pts
シェルが接続されているノードを取得するには、次を使用しますtty
。
> tty
/dev/pts/4
次に、別のコンソールに切り替えて試してください。
> echo "duck!" > /dev/pts/4
いいですね。では試してみましょう:
> cat /dev/pts/4
次に、/dev/pts/4 でシェルを使用してみます。反対側を終了するまでスタックしますが、pts/4 で入力した内容のほとんどは通過します (たとえば、 pts/4 とコンソールでcat
最終的に表示された「hello world」を試します)。hl
ello word
cat
ここでの私の推測は、デバイスがシェルから入力を受け取り、それをシステム経由で出力し、その結果画面に表示されるということです。つまり、シェルがハードウェアを扱うのではなく、システムが扱うのです。試してみてください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
文字を入力するたびに、標準入力から読み取りが行われ、標準出力に書き込みが行われます。しかし、シェルの標準出力はどこに接続されているのでしょうか。次に、strace
GUI ターミナルで試してみましょう。名前がわからない場合は、自分で調べる必要があります。たとえば、KDE では でkonsole
、GNOME では だgnome-terminal
と思います。その出力はおそらくもっとわかりにくいでしょう。私の出力にはやstrace
がたくさん出てきます。書き込みは見られませんが、別のターミナルでこのトリックを実行すると、入力時に cat によって読み取られるキー ストロークに対して strace 出力でまったく応答がないことに気が付くでしょう。ターミナルがキーを受け取っていないのです。つまり、GUI ターミナル アプリと cat は、シェルが出力している同じデバイスから読み取りを競合しているのです。poll()
recvfrom()
cat