BSDレイヤーシリーズ第2回は「KEXT」について。OS Xでは主にデバイスドライバに利用されているが、その本質は「カーネルの拡張機能」であり、カーネルを改変することなく部品のように機能を着脱できるカーネルモジュールだ。今回は、その働きと基本的な管理方法について解説してみよう。

「KEXT」を知る

かつてUNIX系OSでは、ドライバの機能をカーネルに含める形で提供することが一般的で、ドライバを追加/削除するときには「カーネルの再構築」を行っていた。カーネルの再構築とは、カーネルのソースコードをコンパイルしてオブジェクト化し直す作業であり、スキルと手間が要求される。Macのような周辺機器を追加する機会が多い環境において、そのような作業は非効率的であり、ユーザ層を考慮しても無理がある。

OS Xは2000年の初リリース当初から、デバイスドライバなどカーネルに近いレイヤー(カーネル空間)で動作するプログラムをモジュール化し、必要に応じて呼び出したり無効化したりする機能を備えている。このモジュールが「KEXT」(Kernel EXTension)で、その機構によって周辺機器を追加するたびにカーネルを再コンパイルする必要がなくなり、ハードウェアを直接叩くプログラムをカーネルから分離することでシステムの安定性を保つことが可能になった。

KEXTはOS Xのブートプロセスにおいて読み込まれるか、周辺機器がMac本体に接続されるなどその機能を必要とされたとき自動的に読み込まれるため、ユーザ自身が有効/無効を意識する必要がない。GUIベースの管理ツールもなく、インストーラなどを使い導入してしまえばメンテナンスフリーだ。おもにKEXTが保存されるフォルダは「/System/Library/Extensions」と「/Library/Extensions」の2カ所で、Finderを使えば表示できるもののユーザが直接操作することは希だ。

唯一GUIでその存在を確認できるのが「システム情報」だ。ソフトウェア欄にある「機能拡張」を選択すると、現在システムに認識されているKEXTを一覧表示できる。KEXTのロード/アンロードなど管理作業には使えないが、どのようなKEXTがインストールされているか、いちど確認してみよう。

KEXTは/System/Library/Extensionsのほか、特定のディレクトリ以下に保存されている

システムが使用するKEXTは「システム情報」の機能拡張項目で確認できる

KEXTと付き合う

前述したとおり、基本的にKEXTはいちどインストールするとメンテナンスフリーだ。しかし、ある時期からシステムが不安定になった、あるデバイスを接続するとカーネルパニック(カーネルおよびカーネル空間で起きた致命的エラーにより正常動作不能となった状態のこと)が発生する、インストールしたアプリケーションともどもきれいに削除したい、といった場合にはKEXTと向き合わねばならない。

OS XにはKEXT管理用コマンドがいくつか収録されており、それを利用すればある程度絞り込むことは可能だ。ここでは、仮想化ソフト「VirtualBox」に含まれるKEXTを例に、アンロードまでの手順を追ってみよう。

その第一歩となるコマンドが「kextfind」。名前のとおりKEXTを対象に検索を行うためのコマンドで、次のとおり「-print」オプションを指定すると、システム上に存在するすべてのKEXTをフルパスで表示できる(例1)。ただし、このコマンドは再帰的(リカーシブ)に検索する機能を持たないため、デフォルトでは範囲外の「/Library/Application Support」といったディレクトリを検索する場合、通常のfindコマンドを利用したほうが確実だ(例2)。

(例1)

$ kextfind -print

(例2)

$ find /Library -name '*.kext'

kextfindコマンドを使えば、システムが使用するKEXTを一覧できる

VirtualBoxのKEXTが保存されている場所(/Library/Application Support/VirtualBox)がわかれば、kextstatコマンドを使いKEXTが持つ一意のID(バンドルID)を調べよう。左端に表示されるインデックス番号の次の数値は、他のKEXTから依存されている数(Refs)を意味するので、あとで実行するkextunloadコマンドのためにチェックしておこう。

$ kextstat | less

バンドルIDから、ID119から122がVirtualBox関連のKEXTとわかる。Refsの値を見てアンロードの順序を決定する

バンドルIDが判明したら、そのKEXTを無効化(アンロード)してみよう。利用するコマンドは「kextunload」、「-b」オプションに続けてバンドルIDを指定すればOKだ。なお、管理者権限が必要になるためsudoコマンドを併用する。これでアンロードは完了だ。

ただし、他のKEXTに利用されている(依存されている)場合にはアンロードに失敗するため、あらかじめ依存しているKEXTすべてを終了してから実行すること。仮想化ソフト「VirtualBox」を例にすると、他のKEXTが依存している「org.virtualbox.kext.VBoxDrv」を最後に回さなければ、VirtualBoxの動作に使われるすべてのKEXTをアンロードできないはずだ。

$ sudo kextunload -b org.virtualbox.kext.VBoxUSB
$ sudo kextunload -b org.virtualbox.kext.VBoxNetAdp
$ sudo kextunload -b org.virtualbox.kext.VBoxNetFlt
$ sudo kextunload -b org.virtualbox.kext.VBoxDrv

他から依存されているKEXTを先に処理しようとすると失敗するので、Refs値がゼロのものからアンロードする