Android 10 menyertakan daemon live-lock Android
(llkd
), yang dirancang untuk menangkap dan mengurangi deadlock kernel. llkd
menyediakan implementasi mandiri {i>default<i}, tetapi Anda juga dapat
atau mengintegrasikan kode llkd
ke layanan lain, baik sebagai bagian dari
di loop utama atau sebagai thread terpisah.
Skenario deteksi
llkd
memiliki dua skenario deteksi: status D atau Z persisten, dan status
ciri khas{i> stack<i}.
Status D atau Z persisten
Jika thread berada dalam status D (tidur tanpa gangguan) atau Z (zombie) tanpa maju
progres yang lebih lama dari ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms
,
llkd
menghentikan proses (atau proses induk). Jika pemindaian berikutnya menunjukkan
proses yang sama tetap ada, llkd
mengonfirmasi kondisi {i>live-lock<i} dan
panik {i>kernel<i} dengan cara yang dapat
memberikan laporan {i>bug<i} paling rinci untuk
.
llkd
menyertakan watchdog mandiri yang melakukan alarm jika llkd
terkunci; watchdog adalah
menggandakan waktu yang diharapkan untuk mengalir melalui mainloop dan pengambilan sampel
ro.llk_sample_ms
.
Tanda tangan stack persisten
Untuk rilis debug pengguna, llkd
dapat mendeteksi live-lock kernel menggunakan metode
pemeriksaan tanda tangan tumpukan. Jika thread dalam status apa pun kecuali Z memiliki
terdaftar simbol kernel ro.llk.stack
yang dilaporkan lebih lama dari
ro.llk.timeout_ms
atau ro.llk.stack.timeout_ms
, llkd
akan menghentikan proses
(meskipun ada progres penjadwalan yang diteruskan). Jika pemindaian berikutnya menunjukkan
proses yang sama tetap ada, llkd
mengonfirmasi kondisi {i>live-lock<i} dan
panik {i>kernel<i} dengan cara yang dapat
memberikan laporan {i>bug<i} paling rinci untuk
.
Pemeriksaan lldk
terus berlanjut saat kondisi live lock terjadi dan
mencari string tersusun symbol+0x
atau symbol.cfi+0x
dalam
File /proc/pid/stack
di Linux. Daftar simbol ada di ro.llk.stack
dan
secara default adalah daftar
yang dipisahkan koma,
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
.
Simbol harus langka dan berumur pendek sehingga pada sistem biasa
hanya terlihat sekali dalam sampel selama periode waktu tunggu
ro.llk.stack.timeout_ms
(contoh terjadi setiap ro.llk.check_ms
). Karena kurangnya
perlindungan ABA, ini adalah satu-satunya cara untuk mencegah pemicu palsu. Simbol
harus muncul di bawah fungsi yang memanggil gembok yang dapat bersaing. Jika
gembok berada di bawah atau dalam fungsi simbol, simbol akan muncul di semua
proses, bukan hanya
yang menyebabkan {i>lockup<i}.
Cakupan
Implementasi default llkd
tidak memantau init
, [kthreadd]
, atau
[kthreadd]
muncul. Agar llkd
dapat mencakup thread yang dibuat [kthreadd]
:
- Pengemudi tidak boleh tetap dalam status D persisten,
ATAU
- Driver harus memiliki mekanisme untuk memulihkan thread jika thread tersebut dimatikan
secara eksternal. Misalnya, gunakan
wait_event_interruptible()
, bukanwait_event()
.
Jika salah satu kondisi di atas terpenuhi, daftar tolak llkd
dapat disesuaikan menjadi
membahas komponen {i>kernel<i}. Pemeriksaan simbol {i>stack <i}melibatkan proses tambahan
daftar tolak untuk mencegah pelanggaran sepolicy pada layanan yang memblokir ptrace
operasional bisnis.
Properti Android
llkd
merespons beberapa properti Android (tercantum di bawah).
- Properti dengan nama
prop_ms
dalam milidetik. - Properti yang menggunakan pemisah koma (,) untuk daftar menggunakan pemisah di awal untuk
mempertahankan entri {i>default<i}, lalu menambah atau mengurangi entri dengan tanda plus opsional
Setiap awalan (+) dan minus (-). Untuk daftar ini, string
false
identik dengan daftar kosong, dan entri kosong atau tidak ada dimasukkan ke nilai default yang ditentukan.
{i>ro.config.low_ram<i}
Perangkat dikonfigurasi dengan memori terbatas.
dapat di-debug
Perangkat dikonfigurasi untuk userdebug atau build ing.
{i>ro.llk.sysrq_t<i}
Jika properti adalah eng
, defaultnya bukan ro.config.low_ram
atau ro.debuggable
.
Jika true
, buang semua thread (sysrq t
).
{i>ro.llk.enable<i}
Izinkan pengaktifan daemon live-lock. Defaultnya adalah false
.
{i>llk.enable<i}
Dievaluasi untuk build teknis. Defaultnya adalah ro.llk.enable
.
{i>ro.khungtask.enable<i}
Izinkan daemon [khungtask]
diaktifkan. Defaultnya adalah false
.
{i>khungtask.enable<i}
Dievaluasi untuk build teknis. Defaultnya adalah ro.khungtask.enable
.
{i>ro.llk.mlockall<i}
Aktifkan panggilan ke mlockall()
. Defaultnya adalah false
.
{i>ro.khungtask.timeout<i}
Batas waktu maksimum [khungtask]
. Defaultnya adalah 12 menit.
{i>ro.llk.timeout_ms<i}
Batas waktu maksimum D atau Z. Defaultnya adalah 10 menit. Gandakan nilai ini untuk menyetel
watchdog alarm untuk llkd
.
{i>ro.llk.D.timeout_ms<i}
Batas waktu maksimum D. Defaultnya adalah ro.llk.timeout_ms
.
{i>ro.llk.Z.timeout_ms<i}
Batas waktu maksimum Z. Defaultnya adalah ro.llk.timeout_ms
.
{i>ro.llk.stack.timeout_ms<i}
Memeriksa batas waktu maksimum simbol stack persisten. Defaultnya adalah
ro.llk.timeout_ms
. Hanya aktif di userdebug atau build ENG.
{i>ro.llk.check_ms<i}
Contoh thread untuk D atau Z. Defaultnya adalah dua menit.
{i>ro.llk.stack<i}
Pemeriksaan simbol tumpukan kernel yang jika ada secara terus-menerus dapat menunjukkan
subsistem terkunci. Defaultnya adalah
cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
simbol {i>kernel<i} yang dipisahkan koma. Pemeriksaan ini tidak melakukan penjadwalan penerusan
ABA kecuali dengan polling setiap ro.llk_check_ms
selama periode yang dipilih
ro.llk.stack.timeout_ms
, jadi simbol stack akan sangat jarang dan
sekilas (sangat tidak mungkin simbol muncul terus-menerus di semua
contoh stack). Memeriksa kecocokan untuk symbol+0x
atau
symbol.cfi+0x
dalam perluasan tumpukan. Hanya tersedia di userdebug atau Inggris
build; masalah keamanan pada build pengguna mengakibatkan
keterbatasan hak istimewa yang
mencegah pemeriksaan ini.
{i>ro.llk.blacklist.process<i}
llkd
tidak mengamati proses yang ditentukan. Defaultnya adalah 0,1,2
(kernel
,
init
, dan [kthreadd]
) plus nama proses
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]
.
Proses dapat berupa referensi comm
, cmdline
, atau pid
. Default otomatis
bisa lebih besar dari ukuran properti maksimum saat ini, yaitu 92.
{i>ro.llk.blacklist.parent<i}
llkd
tidak mengamati proses yang memiliki induk yang ditentukan. Default
adalah 0,2,adbd&[setsid]
(kernel
, [kthreadd]
, dan adbd
hanya untuk zombie
setsid
). Pemisah dan (&) menentukan bahwa induk hanya diabaikan
dalam kombinasi dengan proses turunan target. Ampersand dipilih karena
bukan pernah menjadi bagian
dari nama proses; namun, setprop
dalam shell memerlukan
ampersand untuk di-escape atau diberi tanda kutip, meskipun dalam file init rc
tempatnya berada
biasanya tidak memiliki masalah ini. Proses induk atau target dapat berupa
Referensi comm
, cmdline
, atau pid
.
{i>ro.llk.blacklist.uid<i}
llkd
tidak mengamati proses yang cocok dengan UID yang ditentukan.
Daftar nomor atau nama UIS yang dipisahkan koma. Defaultnya adalah kosong atau false
.
{i>ro.llk.blacklist.process.stack<i}
llkd
tidak memantau subset proses yang ditentukan untuk stack live lock
tanda tangan. Defaultnya adalah nama proses
init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd
. Mencegah sepolicy
pelanggaran yang terkait dengan proses yang memblokir ptrace
(karena tidak dapat
dicentang). Hanya aktif di userdebug dan build ing. Untuk mengetahui detail tentang build
jenis, lihat Building Android.
Masalah arsitektur
- Properti dibatasi hingga 92 karakter (tetapi akan diabaikan untuk default
yang ditentukan dalam file
include/llkd.h
dalam sumber). - Daemon
[khungtask]
bawaan terlalu umum dan melakukan perjalanan pada kode pengemudi yang terlalu banyak berada di status D. Beralih ke S akan membuat tugas selesai (dan dapat dihidupkan kembali oleh pengemudi jika diperlukan).
Antarmuka library (opsional)
Secara opsional, Anda dapat menggabungkan llkd
ke daemon dengan hak istimewa lain menggunakan
antarmuka C berikut dari komponen libllkd
:
#include "llkd.h"
bool llkInit(const char* threadname) /* return true if enabled */
unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
Jika nama thread diberikan, thread akan otomatis muncul. Jika tidak, pemanggil akan muncul
harus memanggil llkCheckMilliseconds
di loop utamanya. Fungsi tersebut mengembalikan
periode waktu sebelum panggilan yang diharapkan berikutnya ke pengendali ini.