web-dev-qa-db-ja.com

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

私は理解しようとしていますttyの動作1 (各要素のワークフローと責任)。興味深い記事をいくつか読んだことがありますが、まだぼやけた部分があります。

これは私がこれまでに理解したことです:

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

ここに私の質問があります:

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

1.私は私の理解を、 Linus Akessonによって謎解きのTTY および-Andries Brouwerによる Linuxカーネル 投稿に基づいて、これらのサイトの他のいくつかの 質問と同様に

63
Pierre-Jean

端末エミュレータ

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

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

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

それ以外には、端末/端末エミュレータにはインテリジェンスがほとんどありません。

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


Ttyラインの規律

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

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

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

ラインディシプリンは端末デバイスの内部ラインエディタが実装されている場所です。たとえば、_stty icanon echo_(デフォルト)の場合、aと入力すると、xtermはaをマスターに書き込み、次にラインディシプリンechoesを書き込みますそれは戻ります(表示用にaによるxtermの読み取りを可能にします)が、スレーブ側では何も読み取り可能にしません。次に、backspaceと入力すると、xtermは_^?_または_^H_文字を送信し、ラインディシプリン(_^?_または_^H_はeraseラインディシプリン設定に対応するため)を送り返します。マスターは、_^H_、space、および_^H_を使用して、xtermが画面に入力したaを消去し、スレーブ側から読み取るアプリケーションに何も送信せず、スレーブ側から読み取るだけです。以前に入力したaを削除するための内部ラインエディターバッファー.

次に、Enterキーを押すと、xtermは_^M_(CR)を送信します。これは、入力でラインディシプリンが^ J(LF)に変換し、これまでに入力したものをスレーブ側で読み取るために送信します(アプリケーション_/dev/pts/x_を読み取ると、LFを含めて入力した内容が受信されますが、削除したため、aは受信されません)、マスター側では、CRとLFを送信して移動しますカーソルを次の行と画面の先頭に移動します。

ラインの規律は、マスター側で_^C_文字を受信したときにSIGINTシグナルを端末のフォアグラウンドプロセスグループに送信するも担当します。

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

また、プロセスおよび端末デバイスごとに1つのセッションしか存在できません。セッションには制御端末を接続できますが、接続する必要はありません(すべてのセッションは、端末を開くまで端末なしで開始されます)。 xtermは、シェルの実行をフォークするプロセスで、通常、新しいセッションを作成します(したがって、xtermを起動したターミナルから切り離します)、生成された新しい_/dev/pts/x_を開きます。新しいセッションへの端末デバイス。次に、そのプロセスでシェルを実行し、シェルがセッションリーダーになります。シェルまたはそのセッションのインタラクティブシェルは、通常、プロセスグループおよびtcsetpgrp()と連携して、その端末のフォアグラウンドジョブとバックグラウンドジョブを設定します。

tty規律(シリアルまたはpty)を備えた端末デバイスによって格納される情報については、通常、これがsttyコマンドで表示および変更されます。すべての専門分野の構成:端末画面サイズ、ローカル、入出力出力フラグ、特殊文字の設定(^ C、^ Z ...など)、入出力速度(ptyには関係ありません)。これは、LinuxではTCGETS/TCSETS ioctlにマップされるtcgetattr()/tcsetattr()関数に対応し、画面サイズにはTIOCGWINSZ/TIOCSWINSZに対応します。現在のフォアグラウンドプロセスグループは、端末デバイス(tcsetpgrp()/tcgetpgrp()、_TIOC{G,S}PGRP_ ioctls)、または現在の入力または出力バッファーに格納されている別の情報であると主張するかもしれません。

なお、端末装置に記憶されている画面サイズ情報は、実際のものとは異なる場合があります。端末エミュレータは通常、ウィンドウのサイズが変更されたときに(マスターサイズの同じioctlを介して)設定しますが、アプリケーションがスレーブ側でioctlを呼び出した場合、またはサイズ変更が送信されなかった場合(同期しない場合)たとえば、sshdsshを無視した場合にSIGWINCHによって生成された別のptyを意味するssh接続の例)。一部の端末ではエスケープシーケンスを使用してサイズを照会することもできるため、アプリケーションはその方法でクエリを実行し、その情報で回線規則を更新できます。

詳細については、たとえば、Debianのtermiosおよび_tty_ioctl_のマニュアルページを参照してください。

他の回線分野で遊ぶには:

  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を、マウスシステムプロトコルでno button pressed, delta(x,y) = (10,0)を意味する0x87 0x0a 0x00を書き込むプロセス(シェル)に接続します。ここで、私たち(シェル)は端末をエミュレートしていませんが、マウス、送信した3バイトはアプリケーションによって端末デバイスから読み取られません(変換される可能性があります)(mouseは、socatによって作成されたシンボリックリンクです_/dev/pts/x_ device)、ただしマウス入力イベントとして解釈されます。

  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
    _

    上記のシリアルワイヤは、socatによって、hostAとhostBの間のTCPソケットとしてエミュレートされます。 SLIP回線規律は、仮想回線で交換されたバイトを、_sl0_インターフェースでの配信用のSLIPカプセル化IPパケットとして解釈します。

62

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


たくさん読んだ後、これは私が理解したことです。

  • スレーブ部分を割り当てる以外にptmxには目的がありますか?それはある種の「知性」を提供しますか、それともエミュレートされた端末(xtermなど)は端末のように動作するすべての知性を持っていますか?

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

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

    スレーブパーツ(pts)は、/dev/pts/Nここで、Nは数値です。

    Ptsは、grandptunlockptptsname。( Source )の連続呼び出しによってptmから取得されます。

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

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

    そして、これはPTMに接続されたttyのグラフです TTY communication with PTM

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

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

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

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

    • read関数は、端末からエントリを読み取るためにプロセスによって使用されます
    • write関数は、プロセスが出力を端末に送信するために使用されます

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

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

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

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

  • Ptsは他にどのような情報を保存しますか? Xtermはすべてのフィールドを自分で更新しますか、それともptmはそれに「知能」を追加しますか?

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

別館

31
Pierre-Jean

sshdがどのように機能するかについて、前に作成したスキームを以下に示します。これは、回線の規律などの操作には関係ありませんが、実際に誰が何と相互作用するかを示す実例を追加します。

enter image description here

13
Boris Burkov

man ptsさんのコメント:

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

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

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

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

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

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

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

/dev/pts/X indexingについて:

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

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

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

なぜスレーブがマスターを挿入したのか:http://commons.wikimedia.org/wiki/File:Termios-script-diagram.png

1
PersianGulf