メモリが足りない?
最近、ときどきシステムが不安定になることがあります。ロードアベレージをモニターしたりしてわかってきたのですが、負荷が原因ではないようで、どうやらメモリ不足のようなのです。
あるときシステムが外部からまったく応答しなくなっていたので、調べてみたら、syslogに、
user.alert kernel: BUG: unable to handle kernel paging request at 7420646
というメッセージを吐いていたのを見つけました。メモリが足りない証拠です。
Tiny Core Linux/Microcore Linuxは省メモリで動作するシステムですが、逆に何でもメモリ上で動かそうとするので、メモリが足りなくなることがあります。 このときは、/tmpでソースコンパイルなど色々作業をしていて、そのままにしておいたのが悪かったのでした。Tiny Core Linuxでは /tmp(というかrootfs)はメモリ上にあり、アプリケーションが動くメモリ空間と共用しているのです。
私のシステムでは、VirtualBoxでシステムに1GBのメモリを割り当てています。 リブート直後のメモリ関連のファイルシステムを見ると、
$ df Filesystem Size Used Available Use% Mounted on rootfs 904.6M 19.9M 884.7M 2% / tmpfs 502.6M 0 502.6M 0% /dev/shm (以下省略)
という感じで、かなり空いています。 ただ、このrootfsはカーネルやアプリケーション実行用のメモリとも共用しているものなので、フルで使えるわけではありません。 メモリの状態をfreeで見てみると、こんな感じです。
$ free -m total used free shared buffers Mem: 1005 238 766 0 36 -/+ buffers: 202 802 Swap: 251 0 251
swap領域が250MBほどしかありません。 Tiny Core Linuxのswap領域はデフォルトで/dev/zram0上にあります。 そのため、メモリが圧迫されてくればメモリ内のswap領域に圧縮して使うという形になるわけですが、その領域も潤沢ではないため、無理をするとメモリ不足に陥ると言うわけです。
スワップ領域を拡張する3つの方法
そこで、スワップ領域を大きくすることにしました。Linux一般でも通じますが、スワップ領域を増やすには3つくらい方法があります。
- スワップ専用のファイルシステムを用意する
一番シンプルな方法です。/dev/sda2 (ディスクの一部分を使う)とか/dev/sdc (ディスク全体を使う)などのデバイスをスワップ専用にします。 - 既存ファイルシステム上に専用ファイルを用意してスワップ領域として使う
新しくディスクを用意できなければ、専用ファイルを必要なサイズ分ddコマンドで用意すればスワップとして使えます。 - 既存のスワップスペースを大きくする
PartedやGPartedでディスク領域のパーティション分割を変更したり、zramの大きさを変えたりしてスワップの大きさを変えることも可能です。
通常の物理マシンの環境では2.を選ばざるを得ないことも多いと思います。スワップが足りないからといって急にディスクを足したりできないためです。 GPartedなどを使って動的に領域を空けるという手もありますが、お手軽さという意味ではファイルを用意するだけなので2.はラクです。 WindowsもC:\pagefile.sysのようなファイル名で似たような方法を使ってますね。
ただ、この方法は若干パフォーマンスが心配です。ただでさえ私の環境は非力なマシンにVirtualBoxの仮想ディスク(つまりホストから見たら1ファイル)上に構築しています。さらにこの中にスワップファイルを作成するというのはなんだかマトリョーシカ状態。
3. の既存のswapを大きくする方法ですが、実はメモリが限られていても効果はあります。というのも、zram上のswapはメモリの一部を圧縮して持つよ うなイメージなので、その圧縮するメモリ部分を大きくすればその分総量として使えるスペースが広がるということです。ただ、もともと1GBしかないと いうこと、非力でswap入出力時の圧縮/伸張もそれなりのコストがかかる、swapが始まるメモリ上限が低くなるというトレードオフがあり、今回は見送 りました。TinyCore/Microcoreにデフォルトではzram-configがなかった(見つからなかった)というのも理由の一つです。
まぁ、簡単に仮想ディスクを作成できるのもVirtualBoxのような仮想環境のいいところ。ということで、今回は1.の方法で新しく仮想ディスクを作成することにしました。
スワップ用ディスクを作る
仮 想ディスクの作成はいったんゲストOSをシャットダウンしないとできません。上記2.のファイルの方法ならシャットダウンしなくてもできるのですが、そこ は仕方ありません。シャットダウンをしてVirtualBox上で仮想ディスクを作成しておきます。作るのは簡単です。
まず、VirtualBoxの設定の画面で「ストレージ」を選択し、ディスクの追加を選択します。上記の赤い部分です。
続いて、新規ディスクの作成を選択します。
ファイルタイプを聞いてきます。特に別のソフトウェアとの相互運用するなどの特殊な要件がなければvdiで問題ないです。
こちらの質問に関しては、可変サイズにしておくのが無難でしょう。
サイズは自由に設定してかまわないわけですが、今回は2GBにしてみました。
私のシステムには既に/dev/sda (システム)および/dev/sdb (ホーム)のディスクが存在するので、今回追加したものは/dev/sdcとなります。その前提で話をします。
$ sudo fdisk /dev/sdc Device contains neither a valid DOS partition table, nor Sun, SGI, OSF or GPT disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that the previous content
won't be recoverable.
Command (m for help): p Disk /dev/sdc: 2147 MB, 2147483648 bytes 255 heads, 63 sectors/track, 261 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First cylinder (1-261, default 1): (Enter)Using default value 1 Last cylinder or +size or +sizeM or +sizeK (1-261, default 261): Using default value 261: (Enter)Using default value 261 Command (m for help): t Selected partition 1 Hex code (type L to list codes): 82 Changed system type of partition 1 to 82 (Linux swap) Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table
上記で、fdiskコマンド内で入力が必要なところは赤字にしています。ご覧の通り、2GBの仮想ディスクを作りました。
これでディスク全体がswap領域として設定され、/dev/sdc1というデバイスも生成されます。
また、次のようなエントリが/etc/fstabに追加されます。
/dev/sdc none swap defaults 0 0
このスワップ領域を有効にするには、次のコマンドを入力します。
$ sudo swapon /dev/sdc
次のリブートからは/etc/fstabの設定で自動的にswaponになるため、このコマンドの入力は不要です。
これで以前のzram上のスワップスペースと合わせて、
$ free -m total used free shared buffers Mem: 1005 239 765 0 36 -/+ buffers: 203 801 Swap: 2299 0 2299
だいぶ大きくなりました。実際スワップしたら遅くなってしまいますが、応答しなくなるよりマシです。これでしばらく様子を見ようと思います。
匿名
画面が真っ暗、でもカーソルは出てる状況。
探して、ここにたどり着きました。
パスワード入力で、復活!
修理に出す寸前でした。ホントにありがとう!