Home日記コラム書評HintsLinks自己紹介
 

フィンローダのあっぱれご意見番 第145回「限界を超えてしまう前にチェックしよう」

← 前のをみる | 「フィンローダのあっぱれご意見番」一覧 | 次のをみる →

自宅に置いてあるサーバーには RedHat Linux 7.3 がインストールされている。 7.3 というのはかなりの古いバージョンで、 サポートも打ち切られているし、 何か別のディストリビューションに置き換えようとか考えていたのだが、 そこで試しに使ってみようと思ったのが Fedora である。 Fedora というのは RedHat の無料版を後継したような位置づけでもあるので、 結局 RedHat から逃げられないというか、 似たものなら割と移行しやすいのではないかと思ったわけだ。

  

いきなり使用中のサーバーを置き換えるわけにいかないし、 試しにインストールしてみるにしても、 今更クロック200MHz の pc に戻るというのも何だから、 pcを新規購入することにした。 7.3 が動いているのは DELL のpcで、 これはプリインストールモデルを購入したのだから、 私としては、久しぶりの LINUX の新規インストール体験ということになる。

 

※ 以前使っていたサーバーがクロック 200MHz の PC で、 Solaris が入っていた。

pcは、格安pcで有名な某ショップブランドのものを使った。 OSをインストールしていないモデルで、メモリを256MBに増設、 HDDを80GBにグレードアップした状態で、36,120円で新品を買えた。 もちろん、LINUX の動作保証は一切ない。 ただ、 某店でこのpcがLindowsインストールモデルとして売られていたので、 Lindows が動く位なら、 Fedora を動かすのも問題ないだろ、 と勝手に思い込んだのである。 実際、Fedora 自体はきっちり動いた。 特にカスタマイズしなくても、 殆どのハードウェアは期待通りに認識してくれたのだが、 一つだけ問題が発生した。 インストール時だけ使わせてもらった液晶モニタに、何も表示されないのだ。

 

※ Lindows: CD-ROM bootable な LINUX ディストリビューションで、市販されている。 Windows が入っているpc に CD-ROM を入れて起動すれば LINUX が走る、 ということだったと思う。

実際はモニタには out of range と表示されている。 おそらく、水平・垂直周波数あたりの設定がうまくいってないのだろう。 Fedora の新規インストールは、GUI による画面がデフォルトになっている。 これでは先に進めないのだが、 もちろん、GUIを使わずに、テキストベースでインストールすることもできるから、 そのように指定すればインストールも問題はない。 実は発生した問題というのは、 インストールが成功した後の話なのである。

インストールが全て終わると、 reboot しませう(意訳)というメッセージが表示される。 そこでpcを再起動する。 インストールが成功していれば、 ログイン画面まで、普通に進むはずなのだが、 そのログイン画面がGUIで表示されているらしいのだ。 「らしい」というのは、またもや液晶モニタには out of range と 表示されているだけなのである。

  

もしかするとこれはGUI画面の解像度を指定してやれば済むだけの話で、 単にこの液晶モニタと相性が合わなかったのかもしれない。 そこで画面解像度を指定しようと思ったわけだが、 しかし、画面解像度を変更するには、 GUI の画面でログインして、メニューから画面の設定を選び、 解像度を選択するという操作が必要になる。 画面が表示できない状態でそんな操作は不可能である。 つまり、GUI の画面を表示するためには画面解像度を変更しなければならないが、 画面解像度を変更するためにはGUIの画面を表示しなければならないのだ。 これではデッドロックである。

 

※ 俗にバケツの穴というソレである。

結局これをどう回避したかというと、 Fedora をシングルユーザーモードで立ち上げ、 まず、iptables の設定を変更して他からアクセスできるようにした。 iptables というのは firewall である。 インストール時にはよく考えずに 「ファイアウォールを有効」にしてしまったため、 telnetもssh も拒絶されるという素晴らしい状態になっていたのだ。 どうせ LAN の中からしかアクセスできないのだから、 最初は firewall 無効にしておいて、 後で有効にすればよかったのである。 もっとも、リモートから iptables の設定を変更すると、 うっかりミスが原因で外から接続できなくなるという罠もあるわけで、 実際やってしまったのだが、まあそれは余談である。 次に、リモートログインのためのユーザーを登録し、 そのユーザーの権限で、vncserver を起動する。 これで、他の pc で vnc クライアントを起動すれば、 そこから各種の設定処理が可能になる、というシナリオになった。

これで画面解像度を指定できるのでは、 とか思ったのだが、 考えてみると、この pcはサーバーにしか使わないので、、 一旦インストールしてしまったら、モニタは外して使うのである。 しかも、vnc で他からログインして GUI 画面を使うことができる、 となると、今更画面解像度を指定する意味はあるのか?

§

このコラムを書いている時点で書店でgetできるCD-ROM付きの書籍には、 Fedora の Core 1 というバージョンが入っている。 インターネットから本家サイトをアクセスすると、 Core 2 Test 3 というリリースがgetできる状況になっていた。 ということで、その後、Fedora をバージョンアップした。 CD-R を4枚用意しろ、というボリュームである。 ちょっと前なら冗談はやめてくれ、というサイズだが、 自宅にBフレッツが入っているという時代である。 たかが700MB弱のファイルの3つや4つ、 別に構わんだろ、と思ってダウンロードを始めた。 やゃり世の中そんなに甘くなかった。 ダウンロードの残り時間が9時間とか表示されているのだ。

つまり、途中の経路がどうなっているのかは分からないが、 サーバーのパフォーマンスとしては数十KB/秒がせいぜいで、 Bフレッツだと100Mbps出るのかというと、そんな話は理論値であって、 現実にはないものと知るべきである。 もっとも、9時間かかるというのなら、 9時間かけてダウンロードすればいいのだから、 そういう意味では別に問題ないわけで、 結局、Core 2 を全部ダウンロードして、 例のpcにインストールし直してみた。 すると、何ということでしょう! 今度はGUIのインストール画面がきっちり表示されたのである。

  

Core 1 と Core 2 で何が変わったのかまだ比較していないのでよく分からないが、 モニターディスプレイの判定方法が何か変わったのか? ということで、現在そのpcには Core 2 が入っているのである。

 

※ 2005年4月現在、Core 3 が入っている。

§

C言語Q&A というページがあって、 かなり前から更新停止状態だが、 廃止したわけではなく、単に更新していないだけである。 ここに稀にメールで質問してくる方もいらっしゃるので、 それに対してはメールで回答したり、しなかったり、という状態だ。

最近あった質問で、 10桁以上の数値文字列を指定したら結果がおかしくなる、というものがあった。 これはつまり、コードの中に、List のような感じの処理があったのだ。

---- List 1 (数値文字列を int に変換する) ----

    int value = 0;

    while (isdigit(*s)) {
        value = value * 10 + (*s - '0');
        s++;
    }

C言語の場合、int のサイズは最低でも16ビットのデータ、 つまり -32767~32767 が扱えるということになっている。 もっとも、実際は -32768 も扱える場合も多いのだが、 これは最上位ビットが符号だと考えると、 0x0001~0x7FFF が正の数の1~32767に対応し、 0x8000~0xFFFF が負の数の-32768~-1に対応するという仕組みである。

最近の pc だと、 あえて int を16ビットで表現してもあまり意味がないということか、 int は long と同じで 32ビット、 つまり -2147483648~2147483647 が扱えるようになっている処理系も多い。 これが大雑把にいって10桁の数である。 だから「10桁で何かがおかしくなった」という状況が発生したら、 ある程度の経験を積めば、一瞬で原因は想像できる。 long、あるいは 32ビットの int の変数で数値が表現できなくなってしまったのである。

というように、想像するのは簡単なのだが、 この問題の難しいところは、どうすれば解決するかという点にある。 32ビットで表現できないような整数は、どのようにして扱うべきか? double を使うという人もいるのだが、 浮動小数点の変数で整数を扱うのはどうも気味が悪いというか、 一般には禁じ手だと思う。 Java だと int は32ビット、 long は 64ビットのサイズを持っているので、 long にしておけば10桁程度は楽勝で処理できる。 C言語とかC++でも、long long という型が使える処理系もある。 ただ、それにしても、本質的な問題は解決していない。 表現できないような値が入ってきたらどうするか。 信頼性が要求されるプログラムなら、 数値化する所で検証する処理を入れるべきである。 例えば List 2 のようにすればいい。

---- List 2 (限界チェック版) ----

    int value = 0;

    while (isdigit(*s)) {
        if (value >= (INT_MAX / 10)) {
            /* 厳密には処理できる数も多少はじいてしまう */
            /* ここに数値が大きすぎるときの特別な処理を書く */
            break;
        }
        value = value * 10 + (*s - '0');
        s++;
    }
  

何もこんなことしなくても atoi を使えばよさそうなものだが、 前後の処理の都合でこうなったのだと思われる。 そういえば atoi を使ったら文字列の表現が処理できる値を超えていた場合には結果が未定義になってしまうので要注意なのだが、 そういうコードは実際あまり見た記憶がない。

 

※ 負の数は考えていない。

無制限の桁数を扱いたいなら、 最初に文字列で数値を表現しているのだから、 そのまま文字列で最後までやってしまえ、という発想も現実的である。。 その場合は、文字列で表現した数値計算のための処理を自分で書く必要があるが、 加減算程度ならそれほどたいした処理でもない。 いずれにしても、処理できる範囲が限られているなら、 多分、事前にチェックした方がいい。

  

(C MAGAZINE 2004年7月号掲載)
内容は雑誌に掲載されたものと異なることがあります。

修正情報:
2005-04-04 注釈追加版を公開。
2006-03-01 裏ページに転載。

(C) Phinloda 2004-2006, All rights reserved.