試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

ディストリのカーネルとそのモジュールを用いつつ、特定のカーネルモジュールのみを置き換える(後半)

ディストリのカーネルとそのモジュールを用いつつ、特定のカーネルモジュールのみを置き換える(前半)」の続き。

ビルド(続き)

カーネルの開発パッケージについては、VMware製品やVirtualBoxなどの外部カーネルモジュールを作る必要のあるアプリケーションのカーネルモジュールをビルドするために用いるものと同じで、「kernel-(*-)devel(-*)」のような形の名前(Mandrivaでは「kernel-desktop-devel-latest」)もしくはDebian/Ubuntuでは「linux-headers-*」のパッケージの内、動作カーネルに合ったものを入れることになる。
下はビルドの作業例。作業ディレクトリはどこでもよいが、シンボリックリンク/usr/src/linuxの指し示すディレクトリがカーネルソースツリーの最上位ディレクトリとなっていることが前提。カーネルの開発パッケージが入っていればこのリンクは自動で設定されていることも多い。

$ sudo make -C /usr/src/linux-$(uname -r) M=/usr/src/linux drivers/hid/hid{,-pl}.ko
make: ディレクトリ `/usr/src/linux-2.6.33.5-desktop-2mnb' に入ります
  CC [M]  /usr/src/linux/drivers/hid/hid-lg.o
  CC [M]  /usr/src/linux/drivers/hid/hid-lgff.o
  CC [M]  /usr/src/linux/drivers/hid/hid-lg2ff.o
  CC [M]  /usr/src/linux/drivers/hid/hid-core.o
  CC [M]  /usr/src/linux/drivers/hid/hid-input.o
  CC [M]  /usr/src/linux/drivers/hid/hid-debug.o
  CC [M]  /usr/src/linux/drivers/hid/hidraw.o
  LD [M]  /usr/src/linux/drivers/hid/hid.o
  MODPOST 1 modules
  CC      /usr/src/linux/drivers/hid/hid.mod.o
  LD [M]  /usr/src/linux/drivers/hid/hid.ko
  CC [M]  /usr/src/linux/drivers/hid/hid-pl.o
  MODPOST 1 modules
  CC      /usr/src/linux/drivers/hid/hid-pl.mod.o
  LD [M]  /usr/src/linux/drivers/hid/hid-pl.ko
make: ディレクトリ `/usr/src/linux-2.6.33.5-desktop-2mnb' から出ます

上の例ではディレクト/usr/src/linux-2.6.33.5-desktop-2mnb/カーネルの開発パッケージのディレクトリ(ソースツリーではない)となる。
ビルド後にモジュールや中間ファイルを消してやり直したい場合はソースツリーの最上位ディレクトリで「distclean」ターゲットを指定する。この場合に限っては「mrproper」でも同じ結果となる。

$ sudo make -C /usr/src/linux distclean
make: ディレクトリ `/usr/src/linux-2.6.33.5-2mnb' に入ります
  CLEAN   .tmp_versions
  CLEAN   Module.symvers
make: ディレクトリ `/usr/src/linux-2.6.33.5-2mnb' から出ます

上の例ではディレクト/usr/src/linux-2.6.33.5-2mnb/カーネルのソースツリーの最上位ディレクトリ(シンボリックリンク/usr/src/linuxのリンク先)となる。
ターゲット「clean」ではソースツリーの最上位ディレクトリにあるModule.symversが残る。

$ sudo make -C /usr/src/linux clean
make: ディレクトリ `/usr/src/linux-2.6.33.5-2mnb' に入ります
  CLEAN   .tmp_versions
make: ディレクトリ `/usr/src/linux-2.6.33.5-2mnb' から出ます
関連:Module.symversとModule versioning

このModule.symversについてはドキュメントDocumentation/kbuild/modules.txtの「Module versioning & Module.symvers」に説明が書かれているが、カーネルのビルド設定CONFIG_MODVERSIONSが有効のときにモジュールが組み込み先カーネルのバージョンに合ったものかを、「シンボルのC言語のプロトタイプをCRCハッシュ計算したものをカーネルとモジュールのそれぞれに保存しておき、読み込み時に両方が一致しないとモジュールの読み込みを拒否(disagrees about version of symbol [名前])する」という形でチェックする仕組み(Module versioning)があるようで、Module.symversはそのCRC,シンボル,モジュールを1行にまとめた

0xce5674c1	hidinput_connect	drivers/hid/hid	EXPORT_SYMBOL_GPL

のような形を並べて記述したもののようだ。詳しくは前述のドキュメントやソースkernel/module.c(check_version())を参照。また、このチェックの仕組みに関連した分析も
http://d.hatena.ne.jp/elatior/20100413/1271182522
にある。
話を戻すが、この段階でカーネルのソースツリーにあるModule.symversを消しても、その中身つまりビルドしたモジュールのシンボルに関する内容は既にカーネルの開発パッケージにあるModule.symversに書かれており、CRCも一致しているため、問題はない。

余分な情報の削除とモジュールの圧縮

これで必要なモジュールだけが正しくビルドされたが、この状態では不必要な情報をモジュールに含んでいるため、これを削除し、更に、Mandriva Linux 2010.1の時点ではモジュールのファイルはgzip圧縮して配置されることになっているので、圧縮もかけておく。
モジュールはカーネルのソースツリー内にあるので、そこから取り出す。
下は作業例。

$ mkdir work; cd work/
[work]$ cp /usr/src/linux/drivers/hid/*.ko .
[work]$ strip -g *.ko
[work]$ gzip *.ko
[work]$ sudo install -m 644 *.ko.gz /lib/modules/$(uname -r)/kernel/drivers/hid/
[work]$ cd ..
$ rm work -fr

初期RAMディスクイメージ(initrd/initramfs)の更新(モジュールによっては不要)

今回は起動の初期段階から用いられる「hid」と「hid-pl」のモジュールを更新したので初期RAMディスクイメージ(initrd/initramfs・以下initrdとする)の中のモジュールを更新する必要がある。起動時に必要のないものや初期段階で読み込まずに動作するものであればinitrdには含まれないため、更新の必要はない。
Mandriva Linuxではmkinitrdというツールを用いて

$ sudo mv /boot/initrd-$(uname -r).img{,.orig} && sudo mkinitrd /boot/initrd-$(uname -r).img $(uname -r)

のようにすればよいのだが、Mandriva Linux 2010.1上では何故かmkinitrdがうまく動かずに途中で止まってしまい、イメージ(.cpio.gz形式)を手動で更新することになった。
(2010/7/24)「Mandriva Linux 2010.1上の幾つかのメモ(ページ3/3)」で扱った代替ツールdracutを用いることでinitrdの作成が正しく行えた。ただし、2010.1の時点では実験的なものとなっている。
initrdの更新方法はディストリによって異なり、Debian/Ubuntuではupdate-initramfsを用いる。

Mandriva Linux 2010.1上のinitrd手動更新

下の作業例は管理者権限で行うものとする。

(注意:通常は手動ではなく、ディストリごとの方法でinitrdを更新する)
# mkdir initrd; cd initrd/
[initrd]# zcat /boot/initrd-$(uname -r).img | cpio -idm
[initrd]# cp -a /lib/modules/$(uname -r)/kernel/drivers/hid/hid{,-pl}.ko.gz lib/modules/$(uname -r)/
[initrd]# mv /boot/initrd-$(uname -r).img{,.orig}
[initrd]# find | cpio -o -H newc | gzip > /boot/initrd-$(uname -r).img
[initrd]# cd ..
# rm initrd -fr

最後に、initrdのファイルの属性を必要に応じて変更する。

# chmod 600 /boot/initrd-$(uname -r).img

これで再起動後に新しい「hid」と「hid-pl」のモジュールが利用され、PLANEX USBゲームパッドコンバータ(PS/PS2対応・2ポート) PSX-CV02上のPlayStation 2コントローラの振動機能がディストリのカーネル上で動作するようになり、ディストリのパッケージとして提供される他のビルド済みカーネルモジュールもそのまま利用できる。

関連記事:

使用したバージョン:

  • Linux 2.6.33.5-desktop-2mnb