各擬似端末(PTY)コンポーネント(ソフトウェア、マスター側、スレーブ側)の責任は何ですか?


59

ttyがどのように機能するかを把握しようとしています1(各要素のワークフローと責任)。私はそれについていくつかの興味深い記事を読みましたが、まだいくつかのぼやけた領域があります。

これは私がこれまでに理解していることです:

  • エミュレートされた端末は/dev/ptmx、擬似端末のマスター部分であるに異なるシステム呼び出しを行います。
  • 擬似端末のマスター部分は、/dev/pts/[0-N]廃止されたシリアルポートに対応するにファイルを割り当て、スレーブ擬似端末をそれに接続します。
  • スレーブ擬似端末は、セッションID、フォアグラウンドジョブ、画面サイズなどの情報を保持します。

私の質問は次のとおりです。

  1. スレーブ部分を割り当てる以外に、ptmxにはどんな目的がありますか?何らかの「インテリジェンス」を提供します、またはエミュレートされた端末(たとえばxterm)が端末のように動作するすべてのインテリジェンスを備えていますか?
  2. xtermはスレーブパーツのstdoutとstdinのみを転送するため、マスターパーツと対話する必要があるのはなぜですか?なぜptsファイルから直接読み書きできないの ですか?
  3. セッションIDは常に1つのPTSファイルに添付されますか?psコマンドを入力して、同じ/ dev / pts / Xの2つのsessionIdを見つけられますか?
  4. ptsストアには他にどのような情報がありますか?Xtermはすべてのフィールドを自分で更新しますか、それともptm何らかの「インテリジェンス」を追加しますか?

1. Linus Akessonによって謎解かれTTYAndries Brouwer投稿によるLinux Kernelに、これらのサイトの他のいくつかの質問のように、私の理解の基礎を置きます。

回答:


58

端末エミュレーター

マスター側は、端末に向かう回線(TX / RXワイヤーのペア)を置き換えます。

端末は、ワイヤの1つで受信した文字を表示し(制御文字であり、カーソルの移動、色の変更などを行います)、入力したキーに対応する文字を別のワイヤで送信します。

xtermのようなターミナルエミュレータは、ワイヤで文字を送受信する代わりに、ファイル記述子の文字をマスタ側に読み書きすることを除いて、違いはありません。彼らがスレーブ端末を生成し、その上でシェルを起動すると、彼らはもはやそれに触れません。ワイヤーのペアをエミュレートすることに加えて、xtermは、そのファイル記述子を介してマスター側への回線制御プロパティの一部を変更することもできます。たとえば、サイズ属性を更新して、SIGWINCHをスレーブptyと対話するアプリケーションに送信して、サイズの変更を通知できます。

それ以外は、端末/端末エミュレータにはほとんど知性がありません。

端末デバイス(ptyスレーブなど)に書き込むものは、そこに表示されることを意味し、そこから読み取るものはそこに入力したものであるため、端末エミュレーターがそれを読み書きすることは意味がありません。それらは、もう一方の端にあります。


ttyラインの規律

多くの知性はであるtty回線の規律。ラインディシプリンは、デバイスとライン/ワイヤ(ptyのマスター側)の間にあるシリアル/ ptyデバイスの上にプッシュされるソフトウェアモジュール(ドライバー内、カーネル内)です。

シリアル回線は、もう一方の端に端末を持つことができますが、マウスやネットワーク用の別のコンピューターも持つことができます。たとえば、SLIPラインディシプリンを接続して、シリアルデバイス(またはptyデバイス)の上にネットワークインターフェースを取得するか、ttyラインディシプリンを使用できます。tty回線制御は、少なくともLinuxでのシリアルおよびptyデバイスのデフォルトの回線制御です。Linuxでは、を使用して回線制御を変更できますldattach

tty回線制御を無効にした場合の効果は、発行することで確認できますstty raw -echo(bashプロンプトやvi、ターミナルを必要な正確なモードに設定するような他の対話型アプリケーションがありますcat。次に、スレーブ端末デバイスに書き込まれたものはすべて、xtermが読み取るためにすぐにマスター側に送られ、xtermによってマスター側に書き込まれたすべての文字はすぐにスレーブデバイスから読み取ることができます。

回線制御は、端末デバイスの内部回線エディターが実装される場所です。たとえば、stty icanon echo(デフォルトとして)を入力するとa、xtermはaマスターに書き込み、次にラインディシプリンそれをエコーバックします(表示のaために読み取り可能にxtermします)が、スレーブ側で読み取りのために何も利用可能にしません。あなたがバックスペースを入力するとその後、xtermが送信^?または^H(そのような文字、ラインの規律を^?^Hに該当eraseラインの規律の設定)マスタAに送り返し^Hspace^Hのためにxterm消去しますa画面に入力しただけで、まだスレーブ側から読み取ったアプリケーションに何も送信しません。内部ラインエディターバッファーを更新して、a以前に入力したものを削除します。

次に、Enterキーを押すと、xtermは^M(CR)を送信します。これは、入力時に回線制御が^ J(LF)に変換し、スレーブ側での読み取り用にこれまでに入力したものを送信します(アプリケーションの読み取り/dev/pts/xは、 LFを含めて入力したが、a削除してからではない)、マスター側ではCRとLFを送信して、カーソルを次の行と画面の先頭に移動します。

回線制御は、マスター側などでキャラクターを受信したときに、端末のフォアグラウンドプロセスグループに信号を送信するSIGINT役割も担います^C

多くの対話型端末アプリケーション、その回線制御のほとんどの機能を無効にして、それ自体を実装します。ただし、いずれにしても、端末(xterm)はほとんど関与していないことに注意してください(表示するよう指示された内容を表示する場合を除く)。

また、プロセスごと、および端末デバイスごとに1つのセッションしか存在できません。セッションには制御端末を接続できますが、接続する必要はありません(すべてのセッションは、端末を開くまで端末なしで開始されます)。xterm、シェルを実行するためにフォークするプロセスでは、通常、新しいセッションを作成し(したがって、起動元のターミナルがある場合はデタッチしxtermます)、/dev/pts/xそのターミナルデバイスを新しいセッションにアタッチすることによって、生成された新しいものを開きます。その後、そのプロセスでシェルが実行されるため、シェルがセッションリーダーになります。そのセッションのシェルまたは対話型シェルは通常、プロセスグループおよびを操作してtcsetpgrp()、その端末のフォアグラウンドジョブとバックグラウンドジョブを設定します。

以下のように情報を(シリアル又はPTY)TTY規律を有する端末装置により記憶されているもの、それは、典型的には、何sttyを表示するコマンドと変更します。すべてのディシプリン構成:端末画面サイズ、ローカル、入出力フラグ、特殊文字の設定(^ C、^ Z ...など)、入出力速度(ptyには関係ありません)。すなわち、に相当tcgetattr()/ tcsetattr()機能するのLinuxへマップ上TCGETS/ TCSETSのioctl、およびTIOCGWINSZ/ TIOCSWINSZ画面サイズ。現在のフォアグラウンドプロセスグループは、端末デバイス(tcsetpgrp()/ tcgetpgrp()TIOC{G,S}PGRPioctls)、または現在の入力または出力バッファーに格納されている別の情報であると主張するかもしれません。

端末デバイスに保存されている画面サイズ情報は、現実を反映していない可能性があることに注意してください。通常、ターミナルエミュレータは、ウィンドウのサイズが変更されると(マスターサイズの同じioctlを介して)設定しますが、アプリケーションがスレーブ側でioctlを呼び出すか、サイズ変更が送信されない場合(同期しない場合)を無視するsshd場合に生成される別のptyを意味するssh接続の例)。一部の端末は、エスケープシーケンスを介してサイズを照会できるため、アプリケーションはそのように照会し、その情報で回線制御を更新できます。sshSIGWINCH

詳細については、例えばDebianのtermiosおよびtty_ioctlmanページをご覧ください。

他のライン分野で遊ぶには:

  1. 擬似端末でマウスをエミュレートします。

    socat pty,link=mouse fifo:fifo
    sudo inputattach -msc mouse # sets the MOUSE line discipline and specifies protocol
    xinput list # see the new mouse there
    exec 3<> fifo
    printf '\207\12\0' >&3 # moves the cursor 10 pixels to the right
    

    上記では、ptyのマスター側はsocatによって名前付きパイプ(fifo)で終了しています。そのfifoを、マウスシステムプロトコルで0x87 0x0a 0x00を書き込むプロセス(シェル)に接続しますno button pressed, delta(x,y) = (10,0)。ここで(端末装置からのアプリケーションによって(潜在的に形質転換された)、我々 (シェル)は、端末をエミュレートされず、マウスは、我々が送信する3つのバイトが読み取られるようにされていないmouseことによって作られたシンボリックリンクであり、その上socat、いくつかの/dev/pts/xデバイス) 、ただし、マウス入力イベントとして解釈されます。

  2. SLIPインターフェースを作成します。

    # on hostA
    socat tcp-listen:12345,reuseaddr pty,link=interface
    # after connection from hostB:
    sudo ldattach SLIP interface
    ifconfig -a # see the new interface there
    sudo ifconfig sl0 192.168.123.1/24
    
    # on hostB
    socat -v -x pty,link=interface tcp:hostA:12345
    sudo ldattach SLIP interface
    sudo ifconfig sl0 192.168.123.2/24
    ping 192.168.123.1 # see the packets on socat output
    

    上記では、シリアルワイヤはsocathostAとhostBの間のTCPソケットとしてエミュレートされています。SLIP回線制御は、その仮想回線上で交換されたバイトを、sl0インターフェイスで配信するためのSLIPカプセル化IPパケットとして解釈します。


1
これが最良の答えです。私はそれを正しいとマークし、それを支持します。PTSが保存する情報に関する最後の部分を追加できますか?このページ(TTYデバイスを構成する章)によると、ptsは行数や行数などの値を保存します。彼らが保存する他の情報はありますか?
ピエールジャン14年

@ Pierre-Jean、詳細を追加しました。
ステファンシャゼル14年

あなたの答えは満足のいくものではありませんが、実際に/ dev / pts / Mを作成する方法に関する簡単な例を見るのは面白いでしょう。cat /dev/ptmx &which を使用して新しいptyを開いてみましたが、それに関連付けられたプロセスを見つけることができませんでしたので、どのように使用しますか?次に、で試しましたがecho "1" >/dev/ptmx、何もしませんでした...なぜこれに興味がありますか?多くの場合ssh、たとえば(経由で)リモートで接続すると、ジョブの制御を妨げるエラーPTY allocation request failedまたはNo controlling tty: open /dev/ttyエラーが発生します。それらをよりよく理解できたらうれしいです。
not2qubit 14

@ user1147688、ptyの作成方法は別の質問になります。これは、すでに一度に多くの質問になりすぎています。ただし、詳細については、ptymanページを参照してください。
ステファンシャゼル14

@StéphaneChazelas小さな説明: 1.あなたは、フローがphysical term---- tty---- bash端末では、pty(m)---- tty---- pty(s)---- bash端末エミュレーターであると言っているのですか?物理的な端末で文字ttyエコーするのは、この分野の責任ですか?2.入力を管理するためにキーボード/スクリーンに接続するのはターミナルエミュレータプログラムですか?3.理解したことによると、bashコマンド/すべての端末入力の行バッファリングはtty、CI / O関数のI / Oバッファではなく、行単位で行われます。これは正しいです?
forumulator

29

編集:この答え以来、私は私のブログに、より詳細に興味がある人のために、専用の記事を書きました。


多くの読書の後、これは私が理解したことです。

  • スレーブ部分を割り当てる以外に、ptmxには目的がありますか?それはある種の「インテリジェンス」を提供しますか、またはエミュレートされた端末(例えばxterm)は端末のように振る舞うすべての知性を持っていますか?

    /dev/ptmxスレーブ部分を割り当てません。「疑似端末マスター部分」を割り当てます。の/ dev / ptmxはないマスター疑似ターミナル:それは擬似端末マスタ・マルチプレクサ。これは、マスター擬似端末(source)を割り当てる際の競合状態を回避するために、Unix98 PTY標準で作成されました。

    擬似端末のマスターパーツ(ptm)は、ファイルシステムに表示されません。ファイル記述子で表されます。

    スレーブ部(PTS)は、ファイルによって表される/dev/pts/N場合Nの数です。

    PTSは、の連続呼び出しを介してPTMから得られるgrandptunlockptptsname。(出典

    ptmは、デバイスとの通信専用のAURドライバーとラインエディションを置き換えます。したがって、端末をエミュレートすることはありませんが、ラインエディションの機能を提供し、ptsと視覚化して通信する方法を提供します。(ソース

    これは、ハードウェアデバイスに接続されたTTYのグラフです AURとのTTY通信

    そして、ここにptmに接続されたttyのグラフがあります PTMとのTTY通信

    ptmファイルは、ptsとは異なるIoctl引数(ISPTM、UNLKPT、TIOCREMOTE、TIOCSIGNAL)を処理します。

  • xtermはスレーブパーツのstdoutとstdinのみを転送するため、マスターパーツと対話する必要があるのはなぜですか?なぜptsファイルから直接読み書きできないのですか?

    プロセスは、仮想ファイルに対して実行されるアクション(読み取り、書き込み、ioctl ..)を通じてデバイスと対話します。ファイル自体は存在せず、ドライバーはファイルを使用して読み取りまたは書き込みメソッドが呼び出されたときにアクションをトリガーします。(ドライバーについては、Annexeを参照してください)

    TTYは、それと対話する正確な方法を定義します。プロセスはデバイスからの読み取りと読み取りを行い、どのようなTTYが実装されているかに関係なく同じ動作を期待します。

    • 読み取り機能、端末からエントリを読み取るプロセスによって使用されます
    • 書き込み関数、出力を端末に送信するためにプロセスによって使用されます

    PTSはTTYドライバーのように動作します。その読み取りおよび書き込みメソッドは、TTYドライバーの動作を実装するために使用されます。データを送信する実際のデバイスがないため、ストリームペアが作成され、ptmは、ptsからストリームに送信されるデータを読み取る読み取り関数と、使用可能なストリームにデータを送信する書き込み関数を実装します。 PTSがそれを読むとき。

    デバイスを表すファイルはクラシックファイルではなく、ファイルにxterm書き込まれたものを確認したい場合は、単に開いて読み取るだけではできません。これらの関数の動作はここではまったく異なるためです。

  • セッションIDは常に1つのptsファイルに添付されていますか?psコマンドを入力して、同じ/ dev / pts / Xの2つのsessionIdを見つけられますか?

    そうは思いませんが、セッションIDはPTSをアタッチする最初のプロセス(通常はbash)によって定義され、別のセッションを作成して同じPTSにアタッチする方法がわかりません。たぶん、socatこれができるようなツールは?

  • PTSは他にどのような情報を保存しますか?Xtermはすべてのフィールドを自分で更新しますか、それともptmが何らかの「インテリジェンス」を追加しますか?

    ptsは、通信している端末に関する2つのカテゴリの情報を保存します:the TerminfoTermcap。通常、多くのターミナルエミュレータは、それらのtermcap情報を管理するライブラリに基づいています(たとえば、VTX100をエミュレートするすべての機能値を提供します)。このようなライブラリの例はlibvteです。編集(Stephane Chazelasコメントを参照):端末の機能はPTSによって保存されません。

別館


termcapとterminfoは、端末または端末エミュレータの機能に関するデータベースであり、ttyまたはptyデバイスとは関係ありません。
ステファンシャゼル

はい、答えを編集します。コメントありがとう。あなたがそれを知っている場合、あなたはあなたの答えにptsに関するこの情報を追加できますか(たとえば、ptsは画面サイズを保存します)?
ピエールジャン14年

6
これらは素晴らしい画像です。それらを作るためにどのソフトウェアを使用しましたか?
ジル「SO-悪であるのをやめる」14

5
@Gillesありがとう。私は、オープンソースのベクターグラフィックエディターであるInkscapeでそれらを行いました。この種のグラフィックスを作成するのに最も効率的な方法ではないかもしれませんが、もし興味があれば、この種の等角図を作成する方法に関する記事を書きました
ピエールジャン14年

私はあなたが制御端末に二つのセッションをattchまたは1つのセッションが複数の制御端末を持たせことができるとは思わない
炸鱼薯条德里克

9

ここに、私が先ほど作った仕組みを示しsshdます。これは、ラインの規律などの操作には関係しませんが、誰が何とやり取りするかを示す実例を追加します。

ここに画像の説明を入力してください


これに感謝します。私はそれを理解しようとして2日間過ごしました。ptyがインスタンス化されていない場合はどうなるのかと思っています。stdinは存在しませんが、問題ありませんが、stdoutとstderrはどこに書き込まれますか?
少しおい

@emmasculateurはあなたを助けてくれてうれしいです。申し訳ありませんが、「ptyがインスタンス化されていない場合」の意味を理解できません。ptyがインスタンス化されない場合の例を挙げることができますか?
ボリスブルコフ

1
「ptyがインスタンス化されない」とは、sshを-Tで実行したときに、擬似端末割り当てを無効にするということです。例えば:ssh -T emasculateur@localhost "sleep 10" その後、 ps aux|grep sleepこの示しています。 emasculateur 21826 0.0 0.0 23032 3728 ? Ss 02:49 0:00 zsh -c sleep 10 その場合にはbashが書きないのstdoutstderr?私の質問が理にかなっていることを願っています。
少し男

@emmasculateur hm、それは良い質問です、理にかなっています、私はそれを以前に考えていませんでした。私はそれが方法だと思います、あなたは関連する端末なしで、リモートマシン上のデーモンとしてプロセスを開始します。私の推測では、標準の入力/出力/エラー/dev/nullは通常のデーモンのようになりますが、確かではありません。参照:serverfault.com/questions/593399/...
ボリスBurkov

@emmasculateurまた、あなたとは別のケースに出くわしました:プロセスに端末があったが、その端末が閉じていた場合、プロセスはstdout / stdinへの読み取り/書き込みの試行時にカーネルからSIGHUPを受け取ります。これは、nohupまたはscreen/ なしでsshを介して開始されるジョブを強制終了しますtmux
ボリスブルコフ

0

man pts 言う:

ファイル/ dev / ptmxは、メジャー番号5とマイナー番号2の文字ファイルで、通常はモード0666で、root.rootのowner.groupです。擬似端末のマスターとスレーブのペアを作成するために使用されます。

プロセスが/ dev / ptmxを開くと、擬似端末マスター(PTM)のファイル記述子が取得され、擬似端末スレーブ(PTS)デバイスが/ dev / ptsディレクトリに作成されます。/ dev / ptmxを開いて取得した各ファイル記述子は、PTSに関連付けられた独自のPTMであり、そのパスは記述子をptsname(3)に渡すことで見つけることができます。

疑似端末スレーブを開く前に、マスターのファイル記述子をgrantpt(3)およびunlockpt(3)に渡す必要があります。

擬似端末マスターとスレーブの両方が開いたら、スレーブはプロセスに実際の端末のインターフェイスと同一のインターフェイスを提供します。

スレーブに書き込まれたデータは、入力としてマスター記述子に表示されます。マスターに書き込まれたデータは、入力としてスレーブに提示されます。

実際には、擬似端末は、xterm(1)などの端末エミュレータを実装するために使用されます。擬似端末マスターから読み取られたデータは、実際の端末がデータを解釈するのと同じ方法でアプリケーションによって解釈され、リモートを実装するために使用されます-sshd(8)などのログインプログラム。疑似端末マスターから読み取られたデータは、ネットワークを介して、端末または端末エミュレータに接続されているクライアントプログラムに送信されます。

擬似端末は、パイプ(su(8)やpasswd(8)など)からの入力の読み取りを通常拒否するプログラムに入力を送信するためにも使用できます。

について/dev/pts/X indexing

各Xは、それを開くセッションなので、スレーブはインデックスを作成する必要があります。

についてTeteType (/dev/ttyN):

実際のコンソールは、などのブートシステムによって生成されていますsysV

スレーブがマスターを要求した理由について: http ://commons.wikimedia.org/wiki/File:Termios-script-diagram.png


申し訳ありませんが、質問に返信しませんでした。私はすでにマニュアルページを読んでこのグラフを見ましたが、動作は明確ではありませんでした。illuminÉが示唆するように、質問に従って回答を拡張できますか?
ピエールジャン14年


疑似TTYサブシステムを使用するには、マスター側ドライバーのノード/ dev / ptmxおよびN個のスレーブドライバー(Nはインストール時に決定されます)をインストールする必要があります。スレーブデバイスの名前は/ dev / pts / Mで、Mの値は0〜N-1です。ユーザーは、クローンドライバーを介してアクセスされるマスターデバイス(ptmと呼ばれる)を介して擬似TTYデバイスにアクセスします。マイナーデバイス番号は、ptmドライバーのメジャーです。
ペルシャ湾14年

はい、man panページを読みます。...!
ペルシャ湾14年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.