次のページ 前のページ 目次へ

10. フロー制御 (ハンドシェイク)

フロー制御 (= ハンドシェイク = 歩調を合せること) とは、あまりに速いバ イトの流れにより端末、コンピュータ、モデムあるいは他の機器がオーバーラ ンするのを防ぐことです。オーバーランとは、機器が十分な余裕を持って受信 処理をできない時に、データの損失やその他の重大なエラーが生じることです。 フロー制御が何をするかと言うと、(例えば) 端末がデータ受信の準備ができ るまでバイトの流れを止めておいたりします。フロー制御とは、バイトの流れ を止めたい機器とは逆側の機器に対してフロー停止信号を送ることです。フロ ー制御は端末とコンピュータの両方で設定されねばなりません。

フロー制御にはハードウェアとソフトウェア (Xon/Xoff か DC1/DC3) の 2 つ のタイプがあります。ハードウェアフロー制御は RTS/CTS や DTR/DSR などの ような専用の信号線を使いますが、ソフトウェアフロー制御は、通常のデータ 線に DC1 や DC3 制御コードを送ります。ハードウェアフロー制御では、ケー ブルが正しく結線されていなければなりません。

2 つのシリアルポート間のデータの流れは 2 方向ですから、以下のような 2 つの異なるフロー (と結線) を考慮しなければなりません。

  1. コンピュータから端末へのバイトの流れ
  2. 端末のキーボードからコンピュータへのバイトの流れ

10.1 フロー制御がなぜ必要か ?

「なぜオーバランしない程度のそこそこのスピードで送らないの? そうすれ ばフロー制御なんて必要ないのに」と尋ねる人もいるでしょう。これは可能な んですが、フロー制御を使いながら高速で通信するより、はるかに低速になっ てしまうのです。一つの理由は、シリアルボーレートを 14,500 のようなお望 みのスピードに設定できなくて、飛び飛びの数の選択しかできないからです。 最善の選択は、機器が受信でき得るスピードより少しだけ速いレートを選択し ておき、それでもうまく動くようにフロー制御を使うことです。

フロー制御を使わないと決めたら、最悪のケースに備えてかなり遅いスピード に設定しなければなりません。端末では、複雑なやりとりをするためにエスケ ープシーケンスを送ると通常より時間がかかります。モデムの場合 (データ圧 縮付きでフロー制御なし) は、、コンピュータから端末へのスピードが、電話 線で使用できるのと同じくらいゆっくりしたものでなければならないので、最 悪のケースではデータはランダムであり、圧縮できません。フロー制御に失敗 したら、そのスピード (データ圧縮オンの時の) は圧縮をまったくしない場合 より遅くなります。

バッファは、短い間だけなら最悪の状況を処理する助けとなります。一度に処 理しきれないほど速く飛びこんできたデータをバッファに格納し、後で処理す るために溜めておくのです。

10.2 パディング

``最悪の場合'' の状況 (フロー制御やバッファを使わない) を処理する別な方 法は、エスケープシーケンスにヌルの束 (値 0) を付け加えるというものです。 他にどんな機能も与えられてないなら、DEL が使われることがあります。 Del の認識をご覧ください。

エスケープシーケンスは、端末が何かをするとき始まります。そして、端末が 作業中でビジーになったら、無視してよいヌルの束を端末から受け取ります。 最後のヌルを受け取ったとき、端末が作業を終えて次のコマンド待ちの状態と なっています。これをヌルパディングと呼びます。このようなヌルを正式には、 ``フィルキャラクタ'' と呼びます。このヌルは単に時間を ``浪費'' するだけに 挿入されますが、全てを浪費しているわけではなく、端末が何かをするためビ ジーとなったら相手はヌルを受信するのです。フロー制御がポピュラーになる 前はよく使われました。効果的であるように適切な数のヌルが挿入されるべき ですが、長ったらしいものになります。端末のマニュアルにはこれについての 説明が少しだけか、あるいはまるでなかったので、試行錯誤するしかありませ んでした。フロー制御がうまく働かないか、実装されていなければ、パディン グが解決策の一つとなるでしょう。stty コマンドのオプションにパディング があります。

10.3 シリアルポートのオーバラン

19,200 bps (bit/sec) のようなスピードで送信データがセットされている送 受信シリアルポートで、オーバランはどのようにして起り得るのでしょう。理 由は、受信シリアルポートは電気的に入ってくるフローレートを取り扱えます が、シリアルポートからのバイト列を取り込み処理するハードウェア / ソフ トウェアが高速なフローレートに対処しきれなくなるからです。

原因の一つは、シリアルポートのハードウェアバッファがあまりにも小さいこ とです。古いシリアルポートのハードウェアバッファサイズは、たった 1 バ イト (UART チップ内) しかありません。もし受信バッファ内のバイトが次の バイトを受信する前に CPU 命令で取り除かれなければ (フェッチされなけれ ば)、それは消え失せます (バッファーオーバーラン)。16550 のような新しい UART には 16 byte のバッファ (1 byte バッファとしてもエミュレートでき ます) がありますので、オーバランしそうもありません。バッファに 1,4,8 または 14 バイトのデータが到着したら割り込みが発生します。他のコンピュ ータチップ (普通は コンピュータのメイン CPU) が小さなハードウェアバッ ファから取り出して処理します (他のタスクの振舞いと同じ)。

ハードウェア受信バッファが、指定の制限 (古い UART は 1 byte) 一杯とな ったら割り込みがかかります。コンピュータはしていたことを中断して、ソフ トウェアが何が起ったか見つけるためにチェックをします。最後に、シリアル ポートのバッファから 1byte (かそれ以上) を取り出そうと決めます。これら のバイトを取り出し、カーネルがメインメモリ内に準備している大きなバッフ ァ (シリアルポートバッファよりも大きい) に入れます。送信バッファでは、 シリアルハードウェアはバッファが空っぽ (またはそれに近い状態) になった ら割り込みを発行し、送信データをもっとバッファに入れてよいことを CPU に伝えます。

端末にもコンピュータに似たシリアルポートやバッファがあります。端末への フローレートは、キーボードからホストコンピュータへの逆方向フローよりは るかに大きな値となるので、オーバーランが起りそうなのは端末側です。もち ろん、コンピュータを端末として使っているなら (エミュレーション)、同じ ようにオーバランが発生することがあるでしょう。

オーバーランが発生しそうな危険な状況は、1. 他のプロセスが割り込みを不 可にした場合 (コンピュータでの話) か、2. メイン (または、端末) メモリ のシリアルポートバッファがオバーフローした場合です。

10.4 送信停止

洪水のように入ってくるデータを受信処理しきれなくなった時に、送信側に送 信停止の信号を送ります。これがフロー制御で、フロー制御信号は、コントロ ールするデータの流れとは逆側に送ります (同じチャネルでも結線上でもあり ません)。この信号は、データ線に普通のデータとして送られる制御文字 (^S = DC3 = Xoff) か、DTR と CTS (あるいは他の) などの信号線とは別の専用信 号線の正から負への電圧変化として伝送されます。Xoff を使う方法は "ソフ トウェアフロー制御" と呼び、専用信号線 (ケーブル内) を使った電圧変位に よる方法はハードウェアフロー制御と呼びます。

10.5 キーボードロック

端末でもっともありふれた ``送信停止'' は、端末がこれ以上の文字を送り続 けられない場合で、PC に ``停止'' を送るケースです。別なケースは誰かが CTRL + S (訳注 CTRL キーと S キーを同時に押す) を押した場合です。一般 には稀ですが、PC がキーボードのタイプスピードについてゆけずに、端末に 停止を送ることがあります。端末はキーボードを ``ロック'' し、このことを メッセージかライトで知らせるはずです。キーボードロックがかかったら何を タイプしても無視されます。

端末の "ロック" は、コンピュータが端末へ送信停止を告げるときなどの一般 的な場合にもよく使われます。キーボードはロックされていないので、タイプ した文字はコンピュータに送られます。コンピュータが何も送りかえさなけれ ば、タイプした文字は表示されず、キーボードがロックしたように思うかもし れません。スクロールはロック (スクロールロック) しますが、キーボードは ロックしません。

10.6 送信再開

受信側が処理に追いついて、データを受信できるようになったら送信側に信号 を送ります。ソフトウェアフロー制御でのこの信号は、正規のデータ線で送出 される制御文字 ^Q = DC1 = Xon です。ハードウェアフロー制御では、信号線 の電圧が負 (否定) から正 (肯定) に変ります。端末に送信再開を告げると、 キーボードのロックが解かれ使用可能となります。

10.7 ハードウェアフロー制御 (RTS/CTS 等)

古い端末の幾つかにはハードウェアフロー制御がありませんが、他の端末では、 シリアルポートの異なるピンを組み合わせてフロー制御を行ないます。様々な ピンとその名前のリストについては 標準的なヌルモデムケーブルのピン配置を ご覧ください。かなりポピュラーに使われるピンに DTR ピン (または、 DTR ピンと DSR ピンの両方) があります。

RTS/CTS, DTR そして DTR/DSR フロー制御

Linux PC は RTS/CTS フロー制御を使いますが、DTR/DSR フロー制御 (いくつ かの端末で使われる) も同じ働きです。DTR フロー制御では DTR/DSR フロー 制御の DTR 部分だけとなります。

RTS/CTS は、シリアルコネクタ (EIA-232) の RTS ピンと CTS ピンを使用し ます。 RTS は ``送信要求 (Request To Send)'' を意味します。受信側でピンの 状態が肯定(正電圧) である時、「こっちに送ってもいいよ」という意味です。 もし RTS が否定 (負電圧) なら、それは ``送信要求 (Request To Send)'' を 否定することであり、「こっちに送らないで (送信停止)」という意味になり ます。受信側で受信準備可能となったら、送信再開を他方へ要求するべく RTS を肯定 (正電圧) にします。コンピュータと端末で (両方共 DTE タイプの装 置)、RTS ピンはケーブルの反対側の CTS ピン (Clear To Send) にフロー制 御信号を送ります。すなわち、ケーブルの一方の RTS ピンはもう一方の CTS ピンに接続されるのです。

モデム (DCE 装置) の場合は、RTS ピンが信号を受信し、CTS ピンは送信する ので、また違うやり方となります。これについて紛らわしく思われるかもしれ ませんが、ここでの議論の必要がないほど歴史的に正当な理由があるのです。

端末は普通、DTR か DTR/DSR のどちらかのフロー制御を使います。 DTR フロ ー制御は DTR/DSR フロー制御と同じですが、一方向のみで、DSR ピンは使わ れません。端末での DTR/DSR フロー制御では、DTR 信号は RTS ピンから送ら れる信号のようであり、DSR ピンは CTS ピンのような働きです。

DTR か DTR/DSR フロー制御で接続

端末の幾つかは DTR フロー制御だけを使います。これは、端末のオーバラン を防ぐ一方向のフロー制御にすぎません。誰かが、コンピュータが扱える以上 に速くタイプし過ぎると、コンピュータを守れなくなります。標準的なヌルモ デムケーブルでは、端末側の DTR ピンをコンピュータ側の DSR ピンに接続し ますが、Linux では DTR/DSR フロー制御はサポートしていません (マルチポ ートボードのドライバが DTR/DSR フロー制御をサポートしているかもしれま せん)。この問題の迂回策は、端末側の DTR ピンとコンピュータ側の CTS ピ ンとを接続して、 RTS/CTS フロー制御をセットする (stty crtscts) ことで す。なんら影響を受けない唯一の方法をとれば、ホストは洪水のようなタイプ から免れるし、キーボードをロックするために RTS を落すような無駄な試み もしなくてよいでしょう。 キーボードロック をご覧ください。DTR/DSR フロ ー制御 (端末が 2 方向のフロー制御をサポートしているなら) で上記のよう なことをするには、端末の DSR ピンをコンピュータの RTS ピンに接続します。

古い RTS/CTS ハンドシェイクは異なる

混乱するのは、RTS のそもそもの使い方には上記で説明したのと反対の意味が あることです。オリジナルの意味は「送信要求」で、送信要求は、端末 (また は、コンピュータ) からモデムに送られます。要求を許可するなら、「送信要 求を確認しました (Cleared To Send)」との意味で CTS を肯定してコンピュ ータ側の CTS ピンに送り返します。最近の RTS/CTS 双方向フローと比較する と、コンピュータ (や、端末) からモデムへの単方向のフローに対する保護で しかありません。

古い端末での RTS にはこんな意味があり、端末がデータを送信する時に正電 圧をかけます。上記の使い方がフロー制御の方式の一つですから、モデムがコ ンピュータに送信を停止してほしい場合は、CTS (コンピュータ側の CTS に接 続) 信号を落すと、コンピュータが送信を止めます。

リバースチャネル

古いハードコピー端末にはリバースチャネルピン (19番ピンのような) があり、 これは RTS/CTS フロー制御での RTS ピンのような働きです。この端子は、紙 やリボンがなくなった時にも否定になります。このピンはまた、ホストコンピ ュータの CTS ピンとも接続したりします。信号極性を変えるディップスイッ チがあるかもしれません。

10.8 ハードウェアフロー制御はハード的になされるか?

一部の人は、ハードウェアフロー制御はハード的になされていると考えていま す (複数のポートを備えたインテリジェントシリアルカードを使ってない場 合)が、実際はオペレーティングシステムが行っているのです。UART チップと 関連のハードウェアは、ハードウェアフロー制御について何も知りませんから。 ハードウェアフロー信号を受信すると、信号線の極性が変り、ハードウェアは 電気的な割り込みを CPU に与えます。しかし、ハードウェア自体は割り込み の意味について関知しません。CPU は何をしていようが停止して、メインメモ リ内の割り込みテーブルのある場所へジャンプし、そこで割り込みプログラム の場所を知ります。このプログラムは、なにが起こり何をすればよいかを知っ ています。

別な手段で実装されているのは、極性が変ったときに CPU に電気的な割り込 み信号を送る方法です。それが発生したら CPU は現在の作業を一時中断し、 シリアルドライバのサービスルーチンへ処理が移り、何が起ったかを知るため にシリアルハードウェアのレジスタを調べます。そのサービスルーチンの処理 が終了した後は、フローを再送出しないように指令します。こちらの方法のほ うがいくらか効率的ですが、Linux ではこのようにしていません。私は一時、 Linux ではそうしていると思っていました。

どちらの方法でもバイトの流れがほぼ即座に止ることに注意してください。し かし、シリアルポートのハードウェア送信バッファ内にすでにあるバイト (最 大 16 バイト) は送り続けられるでしょう。ソフトウェアフロー制御を使うな ら、受信データに ``オフ'' バイトがあるかチェックする必要があります。こ れらのバイトが 16 バイトの受信バッファを通ることで遅延が生じます。``オ フ'' バイトがこのバッファの最初にあっても、15 以上のバイトを受信してい る間ウエイトし、16 バイト全部を読んだら、``オフ'' バイトを見つけるでし ょう。このような特殊な遅延はハドウェアフロー制御では起りません。

10.9 ETX/ACK や ENQ/ACK フロー制御はもはや廃れかけてる ??

これもソフトウェアフロー制御で、それができるデバイスドライバが必要です。 バイトはパケットとして送られ (非同期シリアルポートを経由して)、各パケ ットの終端には ETX (End of Text) 制御コードがあります。端末が ETX を受 信したら、次のパケットを受信する準備ができるまで待ち、それから ACK(Ack nowledge) を返します。コンピュータは ACK を受信すると、次のパケットを 送ります。以上のことを繰り返します。これは Linux ではサポートされてい ないのでしょうか ?? HP の端末では ENQ の代りに ETX を使って同じことを します。


次のページ 前のページ 目次へ