SSブログ

PowerBook G4の故障とその原因その3 [PowerBook G4故障のこと]

具合の悪かったPowerBook G4 12"の問題が、ヒートシンクが外れたことによる熱暴走ではなく、メモリモジールが原因であるところまでつきとめた。このふたつが偶然同時に起こったとは考えにくいけど、どちらかがもう一方の原因になっているという証拠は見つかっていない。そのPowerBook G4はオンボードの256MBメモリだけにすると10.4.11で機嫌良く動いている。ちょっと大きなソフトを立ち上げるとスラッシングが起こるけど。

使っていたメモリモジュールはアップル純正(ADTEC製)のDDR333/PC2700のSO-DIMM1GBのモジュール。ネットショップなんかを見るとDDR2の場合、1GBモジュールで安いノーブランドものだと二千円台からあるのに、DDRは古いせいか1GBは六千円ぐらいしている。DDRとDDR2って、たしか互換性は無い。しかしたった2ビットの不良だし、仮想記憶のページひとつぶん(MacOSXは4KB)使わなければいいだけなんだから、なんとかならんか。

いろいろなアプリが次々おかしくなると言う症状からして、不良ビットはページングの領域に含まれていると思われる。でも、ほっとくとHDDのブートブロックまで壊してるのはどういうことかな。ブートブロックをアクセスするカーネルプロセスでもページングの対象になってる、ということなのかなあ。HDDを読み書きするようなOSの基本的なコードをページアウトしてどうすんの。そんなはず無いと思うけど、よくわからん。

とりあえずちょっとおいといて、メモリモジールを買い替えなくてもすむ方法を考えたい。

そのためにはまず、この不良ビットを含むページを使わないようにできればいい。ようするに

  1. ブートプロセスでハードウェアが初期化されてから
  2. 問題のある物理メモリのページを自分の仮想メモリにアロケートするプロセスを立ち上げる
  3. そのプロセスは問題ページをページアウトされないようにロックする
  4. 自分自身はinitの子プロセスとなってスリープする
  5. シャットダウンのときにはinitから発行されるSIGTERMシグナルを受けて仮想空間を整理して終了する(もちろん何もしなくてもいいけど気持ちの問題)
ということができればいい。

unixには

#include <sys/mman.h>

int mlock(const void *addr, size_t len);
int munlock(const void *addr, size_t len);
というシステムコールがあってMac OSXでも使える。mlockはaddrで指定されているアドレスの、長さlenの領域をメモリの上にロックしてページアウトされないようにするもの。munlockはその逆。これは頻繁にアクセスするデータがいつもメモリの上にようにしてパフォーマンスを上げるとか言うのに使う、かなりレガシーなシステムコール。もしこんなシステムコールをプロセス全部が我勝ちに発行していたら物理メモリを使い切ったところで動かなくなってしまうので基本的にはやってはいけない(本来そういう調整はOSがやるべき)。

そんな古くさいシステムコールを使わなくても、メモリをテストするのに使ったmemtestは何らかの方法で物理アドレスを特定している訳だから、そのソースを見れば何かわかるはず。と思ってmemtest86(ver.3.4)というWindowsかLinuxでコンパイルできるソースを落としてきたけど、ぜんぜんわからーん。いたるところにi86のインラインアセンブラが埋まっててわけわからん。少なくともunixのmlock()やioctl()やmmap()なんかのシステムコールは見つからなかった。まあWindowsで動かすのだから無いのが当たり前だけど。

最初、main()関数が見つからずに、どうなってんの?と思ったらアセンブラで_mainのエントリポイントが書いてあった。よく見ると自分の実行コードで踏んづけているメモリ領域までテストできるように自分自身のメモリ上の位置を移動させてテストを続けることまでやってるように読める(main.cのstatic void __run_at(unsigned long addr)がmemmove()で動かしてる)。ぐえ。こりゃ太刀打ちできんわい。

というわけで、memtest86の解析は諦めてやっぱりunixのmlock()に戻ることにした。しかしそもそもmlock()に指定できるのは当然仮想アドレス。unixでは、というか普通のOSでは、物理アドレスを直接指定できるシステムコールは存在しない。そんなことができたらページングのシステムがぐちゃぐちゃになってしまう。でも、「普通ではできない、でも絶対できないのはいけない」というもunixの思想である。

昔のHP-UX(ヒューレットパッカードの独自実装のsystemV系unix)ではI/Oデバイスをユーザプロセスから簡単にアクセスできるようにするために特定の物理アドレス領域を読み書きできるシステムコールを持っていた(HP-UXはメモリマップドI/O)。それと同じ時期のVAX(うわ!)のunixにはそんな便利なコールは無かったけど、やはり同じような目的のために/dev/memがある程度解放されていた。/dev/memと/dev/kmemは物理メモリを表すデバイスファイルで、それぞれユーザ用とカーネル用のメモリ領域をキャラクタデバイスとしてアクセスするためのファイル。もちろんそう簡単にはオープンできないけどこれを経由すれば物理メモリは指定できる。たとえば/dev/memをオープンしてmmap()なんかで仮想アドレスを割り当てられれば、さっきのmlock()が使える。

でも、Mac OS Xに/dev/memってあるの?/devを眺めてみると、PowerPCの10.4.11には見つかった。CoreSolo Mac miniの10.4.11はというと、探してもあらへんがな。Core 2 Duo iMac10.5.3にも無かった。まあ、こういう安直なデバイスファイルは無くなる方向だわな。もちろんレガシーなシステムコールを発行する古いソフトを動かすためだけにデバイスファイルが存在して、あったとしても実際に使えるとは限らない。とりあえず10.4.11をインストールしたPowerBook G4には/dev/memはあるのでちょっと中身を覗いてみよう、と思ったけどジジイのおねむの時間は過ぎてしまっている。

二十年前から変わらないunixのシステムコール。懐かしいが、普通の人にはなんのこっちゃ、やろなあ。ということで、続きはまたこんど。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立06/05献立06/06 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。