Come aggiornare il kernel Android all'ultima versione stabile di Linux

Abbiamo trattato delle guide sui kernel Android, come "Come costruire un kernel personalizzato" e "I migliori kernel personalizzati per Android", ma oggi ti mostreremo come eseguire l'upstream del tuo kernel con l'ultima versione stabile di Linux.

Tieni presente che si tratta di cose avanzate : se non hai mai compilato un kernel prima, dovresti seguire la guida "Come costruire un kernel personalizzato" collegata sopra, e questa guida comporterà la raccolta delle ciliegie e l'unione dei commit dagli ultimi Linux- kernel stabile con il kernel Android prima di compilarlo.

L'upgrade del kernel Android all'ultima versione stabile di Linux ha molti vantaggi positivi, come essere aggiornati con gli ultimi impegni di sicurezza e correzioni di bug: spiegheremo alcuni dei pro e dei contro più avanti in questa guida.

Cos'è il kernel Linux-Stable?

Linux-stable come suggerisce il nome è il braccio stabile del kernel Linux. L'altro braccio è noto come "mainline", che è il ramo principale . Tutto lo sviluppo del kernel Linux avviene nella linea principale e generalmente segue questo processo:

  1. Linus Torvalds prenderà un mucchio di cerotti dai suoi manutentori per due settimane.
  2. Dopo queste due settimane, rilascia un kernel rc1 (es. 4.14-rc1).
  3. Per ogni settimana per le successive 6-8 settimane, rilascerà un altro kernel RC (ad es. 4.14-rc2, 4.14-rc3, ecc.), Che contiene SOLO correzioni di bug e regressione.
  4. Una volta ritenuto stabile, verrà rilasciato come tarball per il download su org (ad es. 4.14).

Cosa sono i kernel LTS?

Ogni anno Greg sceglierà un kernel e lo manterrà per due anni (LTS) o sei anni (LTS esteso). Questi sono progettati per avere prodotti che richiedono stabilità (come telefoni Android o altri dispositivi IOT). Il processo è esattamente lo stesso di sopra, succede solo per un tempo più lungo. Attualmente ci sono sei kernel LTS (che possono sempre essere visualizzati nella pagina delle versioni di kernel.org):

  • 4.14 (LTS), gestito da Greg Kroah-Hartman
  • 4.9 (LTS), gestito da Greg Kroah-Hartman
  • 4.4 (eLTS), gestito da Greg Kroah-Hartman
  • 4.1 (LTS), gestito da Sasha Levin
  • 3.16 (LTS), gestito da Ben Hutchings
  • 3.2 (LTS), gestito da Ben Hutchings

Quali sono i vantaggi dell'upstream del mio kernel Android su Linux Stable?

Quando vengono rivelate / risolte importanti vulnerabilità, i kernel stabili sono i primi a ottenerle. Pertanto, il tuo kernel Android sarà molto più sicuro contro attacchi, difetti di sicurezza e solo bug in generale.

La scuderia Linux include correzioni per molti driver che il mio dispositivo Android non utilizza, non è per lo più inutile?

Sì e no, a seconda di come definisci "principalmente". Il kernel Linux può includere un sacco di codice che non viene utilizzato nel sistema Android, ma ciò non garantisce che non ci saranno conflitti da quei file quando si uniscono nuove versioni! Comprendi che praticamente nessuno costruisce ogni singola parte del kernel, nemmeno le distribuzioni Linux più comuni come Ubuntu o Mint. Questo non significa che non dovresti prendere queste correzioni perché ci sono correzioni per i driver che esegui. Prendiamo ad esempio arm / arm64 ed ext4, che sono rispettivamente l'architettura e il file system Android più comuni. In 4.4, dal 4.4.78 (versione dell'ultimo tag Oreo CAF) al 4.4.121 (ultimo tag upstream), questi sono i seguenti numeri per i commit di tali sistemi:

 ~ / 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 

La parte che richiede più tempo è il richiamo iniziale; una volta che sei completamente aggiornato, non ci vuole tempo per unire una nuova versione, che di solito contiene non più di 100 commit. I vantaggi che ciò comporta (maggiore stabilità e migliore sicurezza per gli utenti) dovrebbero tuttavia rendere necessario questo processo.

Come unire il kernel stabile Linux in un kernel Android

Per prima cosa devi capire quale versione del kernel è in esecuzione sul tuo dispositivo Android.

Per quanto banale possa sembrare, è necessario sapere da dove iniziare. Esegui il seguente comando nel tuo albero del kernel:

 fare kernelversion 

Restituirà la versione su cui ti trovi. I primi due numeri saranno usati per capire il ramo di cui hai bisogno (es. Linux-4.4.y per qualsiasi kernel 4.4) e l'ultimo numero sarà usato per determinare quale versione devi iniziare con l'unione (es. Se sei su 4.4 .21, unirai il prossimo 4.4.22).

Prendi l'ultima fonte del kernel da kernel.org

kernel.org ospita l'ultimo sorgente del kernel nel repository stabile per Linux. Nella parte inferiore di quella pagina, ci saranno tre collegamenti di recupero. Nella mia esperienza, il mirror di Google tende ad essere il più veloce ma i risultati possono variare. Esegui i seguenti comandi:

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

Decidi se vuoi unire l'intero kernel o selezionare i commit

Successivamente, dovrai scegliere se vuoi unire i commit o il cherry-pick. Ecco i pro e i contro di ciascuno e quando potresti volerli fare.

NOTA: Se il tuo sorgente del kernel ha la forma di un tarball, molto probabilmente dovrai scegliere ciliegia, altrimenti otterrai migliaia di conflitti di file perché git sta popolando la cronologia basandosi esclusivamente su upstream, non su ciò che OEM o CAF hanno cambiato. Vai al passaggio 4.

Raccogliere le ciliegie:

Professionisti:

  • È più facile risolvere i conflitti poiché sai esattamente quale conflitto sta causando un problema.
  • Più facile da modificare poiché ogni commit è autonomo.
  • Più facile da dividere in due se si verificano problemi

Contro:

  • Ci vuole più tempo perché ogni commit deve essere scelto individualmente.
  • Un po 'più difficile da dire se il commit proviene da monte a prima vista

fondersi

Pro :

  • È più veloce in quanto non è necessario attendere l'unione di tutte le patch pulite.
  • È più facile vedere quando un commit proviene da monte poiché non sarai il committer, lo sarà il manutentore a monte.

Contro:

  • Risolvere i conflitti può essere un po 'più difficile in quanto sarà necessario cercare quale commit sta causando il conflitto usando git log / git biasimo, non lo dirà direttamente.
  • Il rifacimento è difficile in quanto non è possibile rifare la fusione di un'unione, offrirà di scegliere individualmente tutto il commit singolarmente. Tuttavia, non dovresti ripetere il rebasing, invece usa git revert e git merge dove possibile.

Consiglierei di scegliere una ciliegia per capire inizialmente eventuali conflitti di problemi, fare una fusione, quindi ripristinare il problema in seguito, in modo che l'aggiornamento sia più semplice (poiché la fusione è più veloce dopo essere stata aggiornata).

Aggiungi i commit alla tua fonte, una versione alla volta

La parte più importante di questo processo è la versione una alla volta. Potrebbe esserci una patch di problema nella tua serie upstream, che potrebbe causare un problema con l'avvio o interrompere qualcosa come il suono o la ricarica (spiegato nella sezione suggerimenti e trucchi). È importante apportare modifiche incrementali alla versione per questo motivo, è più facile trovare un problema in 50 commit rispetto a oltre 2000 commit per alcune versioni. Consiglierei di fare una fusione completa solo dopo aver appreso tutti i commit e le risoluzioni dei conflitti.

Raccogliere le ciliegie

Formato:

 git cherry-pick .. 

Esempio:

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

fondersi

Formato:

 git merge 

Esempio:

git merge v3.10.74

Consiglio di tenere traccia dei conflitti negli commit di unione rimuovendo i marcatori #.

Come risolvere i conflitti

Non possiamo fornire una guida dettagliata per la risoluzione di ogni singolo conflitto, poiché comporta una buona conoscenza del linguaggio C, ma ecco alcuni suggerimenti.

Se ti stai unendo, scopri quale commit sta causando il conflitto. Puoi farlo in due modi:

  1. git log -pv $ (make kernelversion) .. per ottenere le modifiche tra la versione corrente e l'ultima dall'upstream. Il flag -p ti darà le modifiche apportate da ogni commit in modo che tu possa vedere.
  2. Esegui git blame sul file per ottenere gli hash di ciascun commit nell'area. Puoi quindi eseguire git show –format = fuller per vedere se il committer proviene da mainline / stable, Google o CodeAurora.
  • Scopri se hai già il commit. Alcuni fornitori come Google o CAF tenteranno di cercare a monte bug critici, come la correzione Dirty COW, e i loro backport potrebbero entrare in conflitto con quelli a monte. Puoi eseguire git log –grep = ”” e vedere se restituisce qualcosa. In tal caso, puoi saltare il commit (se cherry-picking usando git reset –hard && git cherry-pick –continua) o ignorare i conflitti (rimuovi <<<<< >>>>>).
  • Scopri se c'è stato un backport che sta incasinando la risoluzione. A Google e CAF piace eseguire il backport di alcune patch che stabile non avrebbe. Stable dovrà spesso adattare la risoluzione del commit della mainline all'assenza di alcune patch che Google opta per il backport. Puoi guardare il commit della linea principale eseguendo git show (l'hash della linea principale sarà disponibile nel messaggio di commit del commit stabile). Se c'è un backport che lo confonde, puoi scartare le modifiche o puoi usare la versione mainline (che è ciò che di solito dovrai fare).
  • Leggi cosa sta tentando di eseguire il commit e vedi se il problema è già stato risolto. A volte CAF può correggere un bug indipendente da upstream, il che significa che puoi sovrascrivere la loro correzione per upstream o scartarla, come sopra.

Altrimenti, potrebbe essere solo il risultato di un'aggiunta CAF / Google / OEM, nel qual caso devi solo mescolare alcune cose in giro.

Ecco un mirror del repository kernel.org stabile per Linux su GitHub, che può essere più semplice per la ricerca di liste di commit e differenze per la risoluzione dei conflitti. Ti consiglio di andare prima alla visualizzazione dell'elenco di commit e di individuare il commit del problema per vedere il diff originale per confrontarlo con il tuo.

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

Puoi anche farlo tramite la riga di comando:

 git log .. git show 

La risoluzione delle risoluzioni riguarda il contesto. Quello che dovresti SEMPRE fare è assicurarti che il tuo differenziale finale corrisponda a quello di upstream eseguendo i seguenti comandi in due finestre separate:

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

Abilita rerere

Git ha una funzione chiamata rerere (sta per Reuse Recorded Resolution), il che significa che quando rileva un conflitto, registrerà come lo hai risolto in modo da poterlo riutilizzare in seguito. Questo è particolarmente utile per entrambi i rebaser cronici con fusione e raccolta delle ciliegie poiché dovrai solo eseguire git add. && git –continua quando esegui il ripristino upstream poiché il conflitto verrà risolto come lo hai precedentemente risolto.

Può essere abilitato eseguendo il comando seguente nel repository del kernel:

 git config rerere.enabled true 

Come eseguire il git bisect durante l'esecuzione in un compilatore o un errore di runtime

Dato che aggiungerai un numero considerevole di commit, è molto possibile introdurre un errore del compilatore o di runtime. Invece di rinunciare, puoi usare lo strumento bisec incorporato di git per capire la causa principale del problema! Idealmente, compilerai e eseguirai il flashing di ogni singola versione del kernel man mano che la aggiungi, in modo che bisecare impiegherà meno tempo se necessario, ma puoi sezionare due commit senza problemi.

Quello che farà git bisect è prendere una serie di commit, da dove il problema è presente a dove non era presente, e quindi iniziare a dimezzare l'intervallo di commit, permettendoti di costruire e testare e fargli sapere se è buono o no . Continuerà fino a quando non sputa il commit che causa il problema. A quel punto, puoi ripararlo o ripristinarlo.

  1. Inizia la bisettrice: git bisect start
  2. Contrassegna la revisione corrente come non valida: git bisect bad
  3. Etichetta una revisione come buona: git bisect buono
  4. Costruisci con la nuova revisione
  5. In base al risultato (se il problema è presente o meno), dire a git: git bisect buono O git bisect cattivo
  6. Risciacquare e ripetere i passaggi 4-5 fino a quando non viene rilevato il commit del problema!
  7. Ripristina o correggi il commit del problema.

NOTA: le fusioni dovranno eseguire temporaneamente git rebase -i per applicare tutte le patch al tuo ramo per una corretta bisecatura, poiché bisecare con le fusioni in atto spesso farà il checkout sui commit a monte, il che significa che non hai nessuno dei commit specifici di Android. Posso approfondire questo aspetto su richiesta, ma fidati di me, è necessario. Dopo aver identificato il commit del problema, è possibile ripristinarlo o rifondarlo nell'unione.

NON schiacciare gli aggiornamenti upstream

Molti nuovi sviluppatori sono tentati di farlo poiché è "più pulito" e "più facile" da gestire. Questo è terribile per alcuni motivi:

  • L'autore è perso. Non è giusto per gli altri sviluppatori avere il loro credito stappato per il loro lavoro.
  • Bisecare è impossibile. Se schiacci una serie di commit e qualcosa è un problema in quella serie, è impossibile dire quale commit abbia causato un problema in una zucca.
  • Le future selezioni di ciliegie sono più difficili. Se è necessario rifarsi con una serie schiacciata, è difficile / impossibile dire da dove provenga un conflitto.

Iscriviti alla mailing list del kernel Linux per aggiornamenti tempestivi

Per ricevere una notifica ogni volta che c'è un aggiornamento a monte, iscriviti alla lista di linux-kernel-annuncio. Ciò ti consentirà di ricevere un'email ogni volta che viene rilasciato un nuovo kernel in modo da poter aggiornare e spingere il più rapidamente possibile.

Articoli Interessanti