Linuxのカーネルのパッチ適用
カーネルに対して最新の機能を適用したい場合、カーネルの再構築を行う必要がある。
Linuxはオープンソースでありソースコードは公開されているため、このソースコードを編集し(パッチの作成と適用)、コンパイルを行い、これをカーネル側に反映することにより適用する。
ソースコードは公開されているため、個人利用目的の範囲内であれば、直接ソースコードを編集して目的を実現することが可能だ。
しかし、実際にこれは現実的でないことが多いため、リポジトリ等で公開されているパッチを当てるのが一般的である。
パッチの作成(diffコマンド)
かつて、ネットワーク回線は非常に低速であった。また、記憶装置も高価なものであった。したがって、カーネルプログラムのような大規模なソースコードを更新の都度全てダウンロードするのは、大きな負荷であった。
これを、パッチという仕組みによって解決した。
パッチとは、古いカーネルプログラムと新しいカーネルプログラムの差分データのことである。
patchコマンドによって、これをカーネルのソースコードへ反映する。
パッチに利用するパッチファイルは、diffコマンドによって得られる差分情報の出力結果を利用する。
diffコマンドは、テキストファイルの差分情報を出力するコマンドである。
以下はその例である。
# diff -aNru ./hoge ./fuga | nl 1 diff -aNru ./hoge/test1.txt ./fuga/test1.txt 2 --- ./hoge/test1.txt 2009-11-29 19:59:45.000000000 +0900 3 +++ ./fuga/test1.txt 2009-11-29 20:00:04.000000000 +0900 4 @@ -1,5 +1,5 @@ 5 a 6 b 7 -C 8 +c 9 d 10 e 11 diff -aNru ./hoge/test2 ./fuga/test2 12 --- ./hoge/test2.txt 2009-11-29 20:03:18.000000000 +0900 13 +++ ./fuga/test2.txt 1970-01-01 09:00:00.000000000 +0900 14 @@ -1 +0,0 @@ 15 -abcde
hogeは旧ディレクトリ、fugaは新ディレクトリであり、この差分情報を標準出力へ出力した。
なお、解説を行うため、nlコマンドにより行番号を与えている。また、C言語のファイルの場合煩雑になるため、簡単な文字列の情報ファイルをサンプルとしている。
diffコマンドへ与えたオプションは以下の通りである。
オプション | 内容 |
---|---|
a | 対象データがテキストファイルであることを明示する。diffはバイナリの認識も可能なので、誤認識を防ぐためである。 |
N | ファイルが存在しない場合、空ファイルとして認識する。ソースコードの追加・削除の可能性があるからである。 |
r | 比較対象がディレクトリであることを表す。パッチの適用対象がディレクトリであるからである。 |
u | ユニファイド形式(最小の情報)で出力する。patchコマンドで利用するフォーマットである。 |
1行目は、比較の対象となるファイルを表している。
2-3行目にて、タイムスタンプが異なるため、これを更新する情報を与えている。
4-10行目にて、テキストデータの差異を表現している。旧ファイルの3行目が「C」であるのに対し、新ファイルの3行目が「c」であることを表している。
11行目以降も別のファイルに対して同様のことを行っているが、サンプルでは新データにtest2.txtというファイルを作成していない。
しかし、オプションでNを与えたため、新データに空ファイル「test2.txt」が存在しているものとして扱っている。
15行目では、新データには当然情報が存在しないので、旧ファイル側には「abcde」という情報が存在していたことを明示している。
パッチの適用(patchコマンド)
パッチの適用は、patchコマンドを用いる。
下記の図では、現在パッチ対象のディレクトリへ移動しており、そこに3つのファイルが置かれていることを確認した状態である。
# ls test.diff test1.txt test2.txt
ファイル「test.diff」は、パッチファイルである。
これを利用して、patchコマンドを実行する。
まず、パッチファイルの内容を確認して、対象ディレクトリの深さを確認する。
# head -3 ./test.diff diff -aNru ./hoge/test1.txt ./fuga/test1.txt --- ./hoge/test1.txt 2009-11-29 20:33:04.000000000 +0900 +++ ./fuga/test1.txt 2009-11-29 20:33:04.000000000 +0900
headコマンドによりパッチファイルの上部を確認したところ、
パッチ対象となるドキュメントが「+++ ./fuga/test1.txt」からディレクトリ「fuga」以下に置かれている事が理解できる。
しかし、実際には更新対象のデータ「test1.txt」はカーレントディレクトリであるため、パッチファイルの内容は階層が1つ浅いということになる。
そこでオプション「-p」を利用して、以下のコマンドを入力する。
# patch -p1 < test.diff can't find file to patch at input line 4 Perhaps you used the wrong -p or --strip option? The text leading up to this was: -------------------------- |diff -aNru ./hoge/test1.txt ./fuga/test1.txt |--- ./hoge/test1.txt 2009-11-29 20:33:04.000000000 +0900 |+++ ./fuga/test1.txt 2009-11-29 20:33:04.000000000 +0900 -------------------------- File to patch: test1.txt ・・・(略)
「-p」に続く数字は、階層の深さを指定する。
旧データと新データのルートとなるディレクトリの名称は、大抵バージョン名が含まれているなどの理由で異なる事が多い。
したがって、patchコマンド実行の際には、パッチ対象データのディレクトリ内に入り、「-p」を指定してパッチを当てることは少なくない。
パッチの適用(patch-kenelスクリプト)
近年更新するソースコードのサイズは増大しており、patchの対象となるデータも比例して多くなっている。
この様な状況下において、上記のpatchコマンドの利用は負荷としてかなり大きいものである。これを解決するのが、patch-kernelスクリプトである。
patch-kernelスクリプトは、カーネルのソースコードが置かれたディレクトリへ一緒に置かれている。
これを、以下の通り実行する。
# (新データ)/scripts/patch-kernel (旧データ)
- 最終更新:2009-12-06 23:18:53