端末エミュレーター
マスター側は、端末に向かう回線(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に送り返し^H
、space
と^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}PGRP
ioctls)、または現在の入力または出力バッファーに格納されている別の情報であると主張するかもしれません。
端末デバイスに保存されている画面サイズ情報は、現実を反映していない可能性があることに注意してください。通常、ターミナルエミュレータは、ウィンドウのサイズが変更されると(マスターサイズの同じioctlを介して)設定しますが、アプリケーションがスレーブ側でioctlを呼び出すか、サイズ変更が送信されない場合(同期しない場合)を無視するsshd
場合に生成される別のptyを意味するssh接続の例)。一部の端末は、エスケープシーケンスを介してサイズを照会できるため、アプリケーションはそのように照会し、その情報で回線制御を更新できます。ssh
SIGWINCH
詳細については、例えばDebianのtermios
およびtty_ioctl
manページをご覧ください。
他のライン分野で遊ぶには:
擬似端末でマウスをエミュレートします。
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
デバイス) 、ただし、マウス入力イベントとして解釈されます。
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パケットとして解釈します。