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

14. 割り込みの問題に関する詳しい説明

トラブルシューティングの章では症状 別に問題点を挙げていますが、この章では割り込みの設定を誤っている場合に 何が起こるのかを説明します。この章は、何がその症状を起こすのか、同じ原 因で他のどんな症状が出るのか、これらにどう対処すべきなのかを理解する助 けになるでしょう。

14.1 割り込みの問題の種類

"setserial" プログラムは、シリアルドライバが考えている割り込みの 設定を表示します。シリアルドライバ(と setserial)が正しい情報を持ってい れば、割り込みに関することは全てうまく行くはずです。もちろん、 デバイスに対応する /dev/ttyS ファイルは存在しなければなりませんし、 プラグ&プレイ(またはジャンパ)でハードウェアにアドレスと IRQ を設定 していなければなりません。Linux は割り込みの衝突を知っていて許可するこ とはないので、衝突を起こすような設定を試みると "Device or resource busy" というエラーメッセージが表示されます。

ユーザが割り込みを衝突させそうになるとカーネルは割り込みの衝突を避けよ うとして "resource busy" というメッセージを出します。 すると割り込みの衝突が起こることはあり得ないのでしょうか? いいえ、簡単に起こります。 ハードウェアの設定が本当に衝突を起こしそうなときに setserial が判断を 誤り、「衝突はない」と嘘をつくこともあるのです。 このような場 合、"... busy" というメッセージは出ませんが、性能が著しく悪くなります。 2 つのデバイスは同じ割り込み信号を同じ信号線に送るので、CPU は割り込み が 1 つのデバイスからしか来ていないと勘違いします。 これについては以降の節で詳しく説明します。

2 つのデバイスに同じ IRQ を割り当てても、どちらのデバイスも使われてい なければ Linux は文句を言いません。それぞれのデバイスは開始(初期化)の 際に、Linux にハードウェア割り込みを使う許可を求めます。Linux はどの 割り込みがどのデバイスに割り当てられているかを管理しているので、その 割り込みが既に使われていると、"... busy" のエラーメッセージが出力され ることになります。したがって、2 つのデバイスが同じ IRQ を使っていても、 1 つのデバイスしか使わなければ、何も問題はありません。しかし、(最初の デバイスを終了させずに)次のデバイスを使おうとすると、"... busy" の エラーメッセージが出ることになります。

14.2 割り込みの誤設定や衝突で起こる症状

起きる症状は、最近の FIFO バッファを持っているシリアルポートを使っ ているかどうか、あるいは FIFO バッファを持たない古いシリアルポートを使っ ているかどうかで変わってきます。古いシリアルポートで起こる症状を理解す ることも重要です。なぜなら、同じことが新しいシリアルポートで起こること が時々あるようだからです。

古いシリアルポートの場合には、数秒ごとに 1 文字しか通過できません。こ れは非常に遅いので、ほとんど動作していないように見えます(特に、空白文字 や改行文字などの見えない文字が通過する場合)。FIFO バッファを持つ新しい シリアルポートの場合には、数秒後の間に 16 文字までが流れていくのが見 えるでしょう。

ポートにモデムが繋がっていて電話番号をダイアルしても、CONNECT メッセー ジが通らないため、接続していないように見えます。しかしずっと待ってか ら接続し、ログインメッセージ(あるいはその類)の一部が最終的に表示される かもしれません。接続のあなた側からの応答が遅れて、相手側があきらめて接 続を切ってしまい、"NO CARRIER" メッセージが出るかもしれません。

minicom を使っている場合にうまく動作しているかどうか調べるための一般的 なテスト方法は、一番簡単なコマンドである "AT" を入力し、これにモデムが 反応するかどうかを調べることです。単に at<enter> を入力すると、 普通は(割り込みが OK ならば)即座にモデムから "OK" という返事があるはずです。 割り込みの設定がおかしければ、at<enter> を入力しても何も返ってこ ないかもしれません。しかし 10 秒くらい経ってからカーソルが 1 行下がる かもしれません。何が起こっているかというと、FIFO が 1 バイトしか保持で きないように動作しているのです。入力した "at" は FIFO をオーバーランさ せ、どちらの文字も消えてしまいます。しかし、しばらく待っていたために最 後の <enter> だけは通り、カーソルが 1 行下がることによって、この 見えない文字を「見る」ことになります。1 文字を入力してから 10 秒待てば、 その文字が画面にエコーバックされるはずです。あなたが文字を打てる速度が 1 分間当り 1 単語より少なければ、これでも大丈夫でしょう :-)

14.3 割り込みの設定ミス

割り込みの役割が分からなければ、先に 割り込みの節を見てください。 シリアルポートのハードウェアには IRQ が 1 つ設定されているけれど、 デバイスドライバ にこれと異なる IRQ が設定されている場合、デバイスドライバはシリアル ポートから送られる割り込みを全く捕捉しません。シリアルポートは割り込み を使ってデバイスを呼び出してサービス(16 バイトの受信バッファからのバイ トデータの受け取りや、16 バイトの送信バッファへのバイトデータの書き込み) を要求するので、シリアルポートは全く動作しないと思われます。

しかしそれでも動く--あるいは動いているように見えることもあります。これ はどうしてでしょうか? つまり、シリアルポートにサービスを提供する方法に は、割り込み以外にも遅いポーリングを使う方法があるのです。この方法は割り込 みを必要としません。ポーリングとは、デバイスドライバが時々シリアルポー トを調べて、何か必要としているかどうか(例えば、受信バッファから取り込 む必要があるバイトデータが存在するかどうか)を見る方法です。割り込みが 使えなければ、シリアルドライバはこのポーリング法を最終的に使います。 しかし、このポーリングは割り込みの代わりに使うための方法ではありません。 ポーリングは遅いので実用的ではありませんし、バッファオーバーランを起 こすこともあるからです。ポーリングの目的は、割り込みが 1 つだけ無くな るか、動作が正しくなかったときに、繰り返し正しい動作を行わせることだっ たと思います。割り込みが失敗したことを示す際にも便利です。

16 バイトの送信バッファは、16 バイトを転送すると待ちに入り、次の ポーリングが(数秒後に)起こってからさらに 16 バイトを送りだします。 したがって、転送は非常に遅く、また細切れになります。 受信も遅くなります。なぜなら、受信バッファが受け取ったバイトデータは、 ポーリングが行われるまでの数秒間はバッファに留まるからです。

入力した文字が表示されるまでに非常に時間がかかるのは、これが理由です。 例えば「AT」という文字列をモデムに送ると、「AT」はシリアルポートを出て モデムに送られます。モデムはシリアルポートを通じて「AT」をスクリーンに エコーバックします。このように、「AT」という文字列はシリアルポートを 2 回通らなければなりません。普通はこの動作が非常に高速なので、キーボード で入力したのと同時に「AT」という文字列が表示されるように見えます。ポー リングのためにシリアルポートが遅い場合には、入力した文字は何秒も待たな いと表示されません。

16 バイトの受信バッファのオーバーランについてはどうでしょうか? これは 外付けモデムを使っている場合に起こります。というのも、モデムはシリアル ポートに高速にデータを送るだけなので、16 バイトのバッファがオーバーラ ンしてしまいます。しかし内蔵モデムの場合にはシリアルポートはモデムと同 じカード上にあるので、受信したバイトデータをこの受信バッファに入れる前 にバッファに空きがあるかどうかが多分チェックされます。この場合には、受 信バッファがオーバーランすることはありませんが、テキストは 16 バイトの まとまりごとに数秒の間隔を置いて表示されます。

外付けモデムであってもオーバーランが起こらないことがあります。数文字 (16 文字以下)しか送られていない場合にはオーバーランは起こりません。バッ ファには大抵、これだけの空きがあるからです。しかしこれより多いバイト数 をモデムから送ろうとすると、画面ではオーバーランが起こります。ただし、 タイミングさえ良ければオーバーランなしに 16 バイト(隙間無し)以上が通る こともあります。例えば 32 バイトが外付けケーブルからポートに一気に送ら れた場合を考えてみましょう。 前半の 16 バイトが来た後に、この 16 バイトをうまく受け取れるよう、 ポーリングが起こることもあります。 すると 次の 16 バイトまでには空き時間があるでしょうから、32 ビット全体がうま く通ります。このシナリオ通りになることはあまりありませんが、同様の条件 により 17 バイトから 31 バイトが通ることはもっと高い可能性で起こります。 しかし、データを落としながら 16 バイトのデータのかたまりだけが断続的に 届くということはさらによくあります。

1 バイトのバッファしか持たない古いシリアルポートの場合(あるいは設定を 誤って 1 バイトのバッファのような動作になっている場合)には、前に書いた よりもずっと悪い状況になります。 つまり、1 つの文字だけが時々シリアルポートを通る といった状態になります。最後に受け取った文字を除くと、受け取った文字は 全てオーバーランを起こします(そして失われます)。この最後の文字は単なる 改行文字であることがよくあります。というのも、改行文字は画面に一気に送 られる文字の中で最後の文字となることが多いからです。したがって、 AT<return> とモデムに入力しても、画面には AT と表示されないこと があります。そして数秒後に起こるのは、カーソルが一行下に移動する(改行 文字)ことだけです。筆者には、16 バイトの FIFO バッファが 1 バイトのバッ ファのように動作した経験があります。

通信プログラムは起動の時に、割り込みが動作していることを期待します。 ポーリング的なモードの遅い動作を使うようにはなっていません。 したがって、シリアルポートやモデムの設定ミスなど、どんな誤りを引き起こ してもおかしくありません。 接続が確立した瞬間を見逃してしまうこともありえます。 ログインするためにスクリプトを使っている場合には、ポーリングの遅延のた めにログインが(タイムアウトにより)失敗するかもしれません。

14.4 割り込みの衝突

2 つのデバイスが同じ IRQ 番号を使っていると、割り込みを共有している と言われます。条件によっては、この共有はうまく動作します。 バージョン 2.2 以降のカーネルは、場合によっては、シリアルポートと別の シリアルポートで割り込みを共有できます。 PCI バス上のデバイスは、PCI バス上の他のデバイスと IRQ を共有できます。 これ以外で衝突の可能性がある場 合でも、同じ IRQ のデバイス 2 つを同時に「使う」ことがなければ、問題は 起きないはずです。 正確に書くと、「使う」とは(プログラマ言葉で)「オープンする」と いう意味です。以上の例外を除くと、(割り込み共有を可能にする特殊なソフ トウェアとハードウェアを使わない限り)共有は許されておらず、共有を行お うとすると衝突が起こります。

IRQ が衝突している 2 つのプロセスが同時に実行された場合であっても、片 方のデバイスの割り込みがデバイスドライバに捕捉され、そちらだけはうまく 動作することもよくあります。他方のデバイスの割り込みは正しいドライバに 捕捉されないので、割り込みの設定ミスがある時のプロセスとちょうど同じよ うに動作するでしょう。詳しくは 割り込みの設定ミス の章をご覧ください。

14.5 割り込みの問題の解決

上記のように応答が非常に遅い場合のテスト方法の一つは、IRQ を 0 に変 更して(割り込みの代わりに高速なポーリングを用いる)、これで問題が解決す るかどうかを調べてください。IRQ=0 によるポーリングは、不正な割り込みに よる「ポーリング」と比べて桁違いに高速です。IRQ=0 で問題が解決するよう であれば、割り込みに何か問題があると考えられます。IRQ=0 はリソースを 大量に消費するので、一時的な修正のためだけに使ってください。割り込みの 問題の原因を見つけるべきであり、いつまでも IRQ=0 を使っていてはいけま せん。

/proc/interrupts を調べて、他のプロセスが現在その IRQ を使っていないか どうかを見てください。他のシリアルポートがその割り込みを使っているなら ば、"top" (f を入力して TTY 表示を有効にしてください)か "ps -e" を使って どのシリアルポートが使われているかを調べてください。setserial に間違っ た IRQ が設定されている疑いがある場合には、 シリアルポートの現在の I/O アドレスと IRQ の設定は? の節を見てください。


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