Androidカーネルを最新のLinux安定版に更新する方法

「カスタムカーネルの構築方法」や「Androidに最適なカスタムカーネル」など、Androidカーネルに関するガイドを取り上げましたが、今日は最新のLinux安定版に対してカーネルをアップストリームする方法を紹介します。

これは高度なものであることに注意してください。以前にカーネルをコンパイルしたことがない場合は、上記のリンク「カスタムカーネルの構築方法」に従ってください。このガイドには、最新のLinuxからのコミットとコンパイルする前に、Androidカーネルで安定したカーネルを使用します。

Androidカーネルを最新のLinux安定版にアップストリーム化すると、最新のセキュリティコミットやバグ修正などの最新の利点など、多くのプラスのメリットがあります。長所と短所については、このガイドの後半で説明します。

Linux安定カーネルとは何ですか?

名前が示すとおり、Linux-stableはLinuxカーネルの安定したアームです。 もう1つのアームは「メインライン」として知られ、 マスターブランチです。 Linuxカーネルの開発はすべてメインラインで行われ、通常は次のプロセスに従います。

  1. Linus Torvaldsは、メンテナから2週間パッチを受け取ります。
  2. この2週間後、彼はrc1(たとえば4.14-rc1)カーネルをリリースします。
  3. 次の6〜8週間の各週に、彼は別のRC(たとえば4.14-rc2、4.14-rc3など)カーネルをリリースします。これにはバグと回帰修正のみが含まれます。
  4. 安定していると判断されると、org(たとえば4.14)でダウンロードするためのtarballとしてリリースされます。

LTSカーネルとは何ですか?

Gregは毎年1つのカーネルを選択し、2年間(LTS)または6年間(拡張LTS)維持します。 これらは、安定性が必要な製品(Androidスマートフォンや他のIOTデバイスなど)を持つように設計されています。 このプロセスは上記とまったく同じです。それは単に長時間発生します。 現在、6つのLTSカーネルがあります(kernel.orgリリースページで常に表示できます)。

  • 4.14(LTS)、Greg Kroah-Hartmanにより管理
  • 4.9(LTS)、Greg Kroah-Hartmanにより管理
  • 4.4(eLTS)、Greg Kroah-Hartmanにより管理
  • 4.1(LTS)、Sasha Levinにより管理
  • 3.16(LTS)、Ben Hutchingsにより維持
  • 3.2(LTS)、Ben Hutchingsにより維持

AndroidカーネルをLinux Stableにアップストリーム化する利点は何ですか?

重要な脆弱性が公開/修正された場合、安定したカーネルが最初にそれらを取得します。 したがって、Androidカーネルは、攻撃、セキュリティ上の欠陥、および一般的なバグに対してはるかに安全です。

Linuxの安定版には、私のAndroidデバイスが使用しない多くのドライバーの修正が含まれていますが、これはほとんど不要なのではないでしょうか?

はい、いいえ。「大部分」の定義方法によって異なります。 Linuxカーネルには、Androidシステムで使用されない多くのコードが含まれている可能性がありますが、新しいバージョンをマージするときにこれらのファイルとの競合がないことを保証しません! UbuntuやMintなどの最も一般的なLinuxディストリビューションでさえ、カーネルのすべての部分をビルドする人はほとんどいないことを理解してください。 これは、実行するドライバーに修正があるため、これらの修正を行うべきではないという意味ではありません。 たとえば、最も一般的なAndroidアーキテクチャとファイルシステムであるarm / arm64とext4を例にとります。 4.4では、4.4.78(最新のOreo CAFタグのバージョン)から4.4.121(最新のアップストリームタグ)まで、これらのシステムのコミットに関する次の数字です。

 〜/ kernels / linux-stable(master)$ git log --format =%h v4.4.78..v4.4.121 | wc -l2285 〜/ kernels / linux-stable(master)$ git log --format =%h v4.4.78..v4.4.121 arch / arm | wc -l58 〜/ kernels / linux-stable(master)$ git log --format =%h v4.4.78..v4.4.121 arch / arm64 | wc -l22 〜/ kernels / linux-stable(master)$ git log --format =%h v4.4.78..v4.4.121 fs / ext4 | wc -l18 

最も時間のかかる部分は最初の立ち上げです。 最新の状態になったら、通常100を超えるコミットを含まない新しいリリースにマージするのにまったく時間はかかりません。 ただし、これがもたらす利点(ユーザーの安定性とセキュリティの向上)により、このプロセスが必要になります。

Linux安定カーネルをAndroidカーネルにマージする方法

まず、Androidデバイスが実行しているカーネルバージョンを把握する必要があります。

これは些細なことですが、どこから始める必要があるかを知る必要があります。 カーネルツリーで次のコマンドを実行します。

 kernelversionを作成します 

現在のバージョンが返されます。 最初の2つの数値は、必要なブランチ(4.4カーネルの場合はlinux-4.4.yなど)を判別するために使用され、最後の数値は、マージを開始する必要があるバージョンを判別するために使用されます(例えば4.4 .21、次に4.4.22をマージします)。

kernel.orgから最新のカーネルソースを入手します。

kernel.orgは、linux-stableリポジトリに最新のカーネルソースを格納しています。 そのページの下部に、3つのフェッチリンクがあります。 私の経験では、Googleのミラーは最も速い傾向がありますが、結果は異なる場合があります。 次のコマンドを実行します。

 git remote add linux-stable //kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.gitgit fetch linux-stable 

カーネル全体をマージするか、コミットをチェリーピックするかを決定します

次に、コミットをマージするかチェリーピックをマージするかを選択する必要があります。 ここに、それぞれの長所と短所、およびそれらを実行するタイミングを示します。

注:カーネルソースがtarballの形式である場合、チェリーピックが必要になる可能性が高くなります。さもなければ、gitはOEMまたはCAFが持っているものではなく、純粋に上流に基づいて履歴を生成するため、数千のファイル競合が発生しますかわった。 手順4に進んでください。

さくらんぼ狩り:

長所:

  • 問題の原因となっている競合を正確に把握しているため、競合を簡単に解決できます。
  • 各コミットが独立しているため、リベースが簡単になります。
  • 問題が発生した場合は二分しやすい

短所:

  • 各コミットを個別に選択する必要があるため、時間がかかります。
  • 一見してコミットがアップストリームからのものかどうかを見分けるのはもう少し難しい

マージ

長所

  • すべてのクリーンなパッチがマージされるのを待つ必要がないため、高速です。
  • あなたがコミッターではなく、アップストリームのメンテナーであるので、コミットがアップストリームからのものであるときを見るのは簡単です。

短所:

  • git log / git blameを使用して、どのコミットが競合を引き起こしているのかを調べる必要があるため、競合の解決はもう少し難しくなります。
  • マージをリベースできないため、リベースは困難です。すべてのコミットを個別に選択することができます。 ただし、可能な限りgit revertおよびgit mergeを使用して、頻繁にリベースするべきではありません。

問題の競合を最初に見つけてマージし、問題のコミットを元に戻して更新を簡単にするためにチェリーピックを行うことをお勧めします(最新になった後、マージが速くなるため)。

コミットをソースに1つずつ追加します

このプロセスの最も重要な部分は、一度に1つのバージョンです。 アップストリームシリーズに問題のあるパッチが存在する可能性があります。これにより、起動に問題が発生したり、サウンドや充電などが壊れたりする可能性があります(ヒントとコツのセクションで説明)。 このため、バージョンの増分変更を行うことが重要です。一部のバージョンでは、2000件以上のコミットよりも50件のコミットで問題を見つける方が簡単です。 すべての問題のコミットと競合の解決を知ってから、完全マージを実行することをお勧めします。

さくらんぼ狩り

フォーマット:

 git cherry-pick .. 

例:

git cherry-pick v3.10.73..v3.10.74

マージ

フォーマット:

 git merge 

例:

git merge v3.10.74

#マーカーを削除して、マージコミットの競合を追跡することをお勧めします。

競合を解決する方法

C言語の十分な知識が含まれているため、すべての競合を解決するための段階的なガイドを提供することはできませんが、いくつかのヒントがあります。

マージする場合は、どのコミットが競合の原因であるかを把握してください。 次の2つの方法のいずれかを実行できます。

  1. git log -pv $(make kernelversion)..現在のバージョンとアップストリームの最新バージョンとの間の変更を取得します。 -pフラグを使用すると、各コミットによって行われた変更が表示されるため、確認できます。
  2. ファイルでgit blameを実行して、その領域の各コミットのハッシュを取得します。 その後、git show –format = fullerを実行して、コミッターがメインライン/ステーブル、Google、またはCodeAuroraからのものかどうかを確認できます。
  • すでにコミットがあるかどうかを確認します。 GoogleやCAFなどの一部のベンダーは、Dirty COWの修正などの重要なバグをアップストリームで検索しようとしますが、そのバックポートはアップストリームと競合する可能性があります。 git log –grep =””を実行して、何かを返すかどうかを確認できます。 その場合、コミットをスキップするか(git reset –hard && git cherry-pick –continueを使用してチェリーピッキングする場合)、競合を無視できます(<<<<< >>>>>を削除します)。
  • 解像度を台無しにしているバックポートがあったかどうかを把握します。 GoogleとCAFは、安定版ではできない特定のパッチをバックポートしたいと考えています。 安定版は、多くの場合、メインラインコミットの解決を、Googleがバックポートすることを選択した特定のパッチの不在に適応させる必要があります。 メインラインコミットを確認するには、git showを実行します(メインラインハッシュは、安定したコミットのコミットメッセージで利用できます)。 それを台無しにするバックポートがある場合は、変更を破棄するか、メインラインバージョンを使用することができます(通常はこれが必要です)。
  • コミットが何をしようとしているかを読み、問題がすでに修正されているかどうかを確認してください。 CAFはアップストリームとは無関係にバグを修正する場合があります。つまり、アップストリームの修正を上書きするか、上記のように破棄することができます。

それ以外の場合は、CAF / Google / OEMの追加の結果である可能性があります。その場合は、いくつかのことをシャッフルする必要があります。

GitHubのlinux-stable kernel.orgリポジトリのミラーを次に示します。これは、競合解決のためにコミットリストと差分を簡単に検索できます。 最初にコミットリストビューに移動し、問題のあるコミットを見つけて元のdiffを確認し、それを自分のものと比較することをお勧めします。

URLの例://github.com/nathanchance/linux-stable/commits/linux-3.10.y/arch/arm64/mm/mmu.c

コマンドラインからもできます:

 git log .. git show 

解決策の解決は、コンテキストに関するものです。 常にすべきことは、2つの別々のウィンドウで次のコマンドを実行して、最終的な差分がアップストリームのものと一致することを確認することです。

 git diff HEAD git diff v $(make kernelversion).. $(git tag --sort = -taggerdate -lv $(make kernelversion | cut -d。-f 1, 2)* | head -n1) 

rerereを有効にする

Gitにはrerere(Reuse Recorded Resolutionの略)と呼ばれる機能があります。つまり、競合を検出すると、解決方法を記録し、後で再利用できるようにします。 これは、git addを実行するだけでよいので、マージとチェリーピッキングの両方を行う慢性リベーサーの両方に特に役立ちます。 && git –アップストリームブリングアップを再実行するときに続行します。競合は以前に解決した方法で解決されるためです。

カーネルリポジトリで次のコマンドを実行することで有効にできます。

 git config rerere.enabled true 

コンパイラーまたはランタイムエラーが発生したときにbisectをgitする方法

かなりの数のコミットを追加することを考えると、コンパイラまたはランタイムエラーが発生する可能性が非常に高くなります。 あきらめる代わりに、gitのビルトインbisectツールを使用して、問題の根本原因を突き止めることができます! 理想的には、カーネルバージョンを追加するたびにビルドしてフラッシュするので、必要に応じて二分する時間が短くなりますが、5000のコミットを問題なく二分することができます。

git bisectが行うことは、問題が存在する場所から存在しない場所までの範囲のコミットを取得し、コミット範囲を半分にし始めて、ビルドしてテストし、それが良いかどうかを知らせることです。 問題の原因となるコミットを吐き出すまでこれを続けます。 その時点で、修正するか元に戻すことができます。

  1. 二分法を開始:git bisect start
  2. 現在のリビジョンを不良としてラベル付けします:git bisect bad
  3. リビジョンに良いラベルを付ける:git bisect good
  4. 新しいリビジョンでビルドする
  5. 結果に基づいて(問題が存在するかどうか)、gitに伝えます:git bisect goodまたはgit bisect bad
  6. 問題のあるコミットが見つかるまで、ステップ4〜5をすすぎます。
  7. 問題のコミットを元に戻すか、修正します。

注:マージでは、適切なバイセクトのためにすべてのパッチをブランチに適用するために、一時的にgit rebase -iを実行する必要があります。 リクエストに応じてこれについてさらに詳しく説明しますが、私を信頼してください。 問題のコミットを特定したら、それを元に戻すか、マージにリベースできます。

アップストリームの更新をつぶさないでください

多くの新しい開発者は、管理が「よりクリーン」で「簡単」であるため、これを実行したいと考えています。 これはいくつかの理由でひどいです:

  • 著者名が失われます。 他の開発者にとっては、自分の功績を称えられるのは不公平です。
  • 分割は不可能です。 一連のコミットをスカッシュし、そのシリーズの何かが問題である場合、どのコミットがスカッシュで問題を引き起こしたかを知ることは不可能です。
  • 将来のチェリーピックはより困難です。 押しつぶされたシリーズでリベースする必要がある場合、競合の原因を特定することは困難/不可能です。

タイムリーな更新のためにLinuxカーネルメーリングリストに登録する

アップストリームの更新があるたびに通知を受けるには、linux-kernel-announceリストに登録してください。 これにより、新しいカーネルがリリースされるたびにメールを受け取ることができるので、できるだけ早く更新してプッシュすることができます。

興味深い記事