Panduan Pemrograman Modul Kernel Linux
(sysprog21.github.io)- Linux Kernel Module Programming Guide adalah panduan gratis untuk membuat modul kernel yang dapat dimuat pada Linux v5.10 ke atas, mencakup alur lengkap dari lingkungan pengembangan hingga build, load, debugging, dan antarmuka kernel utama
- Contoh awal menggunakan
hello-*.cuntuk mempelajarimodule_init(),module_exit(),kbuild,insmod,rmmod, dandmesg, serta memakai devtools berbasis QEMU untuk mengurangi risiko merusak sistem host - Karena modul kernel berjalan di ruang alamat kernel, pointer yang salah, urutan unload, concurrency, dan kesalahan penyalinan memori pengguna dapat menyebabkan korupsi memori kernel atau ketidakstabilan sistem
- Cakupan diperluas ke perangkat karakter,
/proc,seq_file, threaded IRQ, input, PCI, USB, block, network, Device Model, Device Tree, hingga static key, sambil berulang kali membahas urutan registrasi dan pelepasan serta pengelolaan lifetime - Karena API internal kernel berubah menurut versi, perlu memeriksa kondisi seperti
LINUX_VERSION_CODE,KERNEL_VERSION,CONFIG_MODVERSIONS, penandatanganan SecureBoot, dan version magic, dan contoh-contohnya juga mencakup kompilasi kondisional
Struktur panduan dan alur dasar
- Panduan ini adalah materi pembelajaran modul kernel yang menyediakan repositori GitHub dan dokumen PDF, serta dapat disalin, dimodifikasi, dan didistribusikan di bawah ketentuan Open Software License 3.0
- Saat ini panduan menetapkan Linux v5.10 sebagai batas minimum yang didukung, dan bertujuan menjaga kompatibilitas contoh serta petunjuk di berbagai kernel dukungan jangka panjang
- Pembelajar perlu menguasai bahasa C dan memiliki pengalaman menulis program untuk proses umum, sementara modul kernel dimuat dan dilepas secara dinamis untuk memperluas fungsi kernel tanpa reboot
- Alur pengembangan dasar berlanjut dari pemasangan header kernel, build
.kodenganmake, pemeriksaan denganmodinfo, load denganinsmod, pengecekan log dengandmesgataujournalctl -k, lalu unload denganrmmod devtools/membangun source kernel dan root filesystem BusyBox lalu melakukan boot di QEMU, membagikanexamples/melalui 9p virtfs, dan memungkinkan pengujian modul di guest- Untuk inisialisasi dan pembersihan modul, penggunaan
module_init()danmodule_exit()lebih disarankan, sedangkan pendekatan lamainit_module()dancleanup_module()dapat menyebabkan kegagalan build dalam kondisi tertentu pada kernel 6.15 ke atas saat x86 IBT aktif - Modul kernel tidak menggunakan
printf()atau libc dan hanya dapat memakai simbol yang diekspor kernel, sementara output dikirim bukan ke terminal melainkan ke ring buffer log kernel - Pemindahan data antara ruang pengguna dan ruang kernel memerlukan fungsi khusus seperti
put_user,get_user,copy_to_user, dancopy_from_user - Contoh perangkat karakter menunjukkan
register_chrdev,file_operations, dynamic major number, pembuatan node/dev, exclusive open, read berbasisput_user, dan penanganan write yang tidak didukung - Contoh
/procmembahasproc_create,proc_ops, callback read/write, dan APIseq_file, serta mencerminkan perubahan setelah Linux v5.6 ketikaproc_opsdiperkenalkan untuk handler/procmenggantikanfile_operations - Threaded IRQ memisahkan top-half dan bottom-half dengan
request_threaded_irq(), di mana top-half hanya melakukan pekerjaan minimal dalam interrupt context lalu membangunkan bottom-half berbasis thread denganIRQ_WAKE_THREAD - Bab-bab berikutnya meluas ke area driver nyata seperti input, PCI, USB, block, network, Device Model, dan Device Tree, berfokus pada cara registrasi setiap subsystem dan pemilihan ABI userspace
- Bagian optimasi dan keamanan membahas
likelydanunlikely, static key, stack kernel yang kecil, larangan penggunaan FPU, kebocoran padding yang belum diinisialisasi, dan kehati-hatian saat memakai API internal dengan double underscore
Kendala awal saat build dan load
- Modul yang dikompilasi untuk satu kernel mungkin tidak dapat dimuat pada kernel lain, dan jika version magic serta
CONFIG_MODVERSIONStidak cocok, dapat munculInvalid module formatatau ketidakcocokan versi simbol - Sebagian besar kernel distribusi Linux umum mungkin mengaktifkan modversioning, sehingga jika contoh tidak langsung berjalan, perlu mempertimbangkan kernel dengan modversioning dimatikan atau lingkungan QEMU
- Pada sistem dengan SecureBoot aktif, pemuatan modul tanpa tanda tangan bisa dibatasi, dan jika muncul
Lockdown: insmod: unsigned module loading is restricted, perlu menonaktifkan SecureBoot atau menjalankan prosedur penandatanganan modul
Lingkungan praktik berbasis QEMU
devtools/setup.shmengunduh dan membangun tarball kernel serta BusyBox, lalu memaketkan initramfsdevtools/build-modules.shmembangun modul untuk kernel target QEMU,devtools/boot.shmenyediakan shell guest, dandevtools/test-modules.shmenjalankan pengujian otomatisinsmoddanrmmodper modul- Debugging GDB dilakukan dengan membangun
vmlinuxmelaluiLKMPG_NO_PREBUILT=1 devtools/setup.sh, lalu menggunakandevtools/boot.sh --gdbdan koneksi GDB jarak jauh
Aturan penulisan kode kernel
- Dalam fungsi init, registrasi dan alokasi bisa gagal, sehingga resource yang sudah diperoleh harus dilepas dalam urutan terbalik melalui jalur error berbasis
goto - Jika struktur callback didaftarkan ke kernel, userspace dapat memanggil callback bahkan sebelum init selesai mengembalikan nilai, sehingga aturan register last, unregister first penting: selesaikan inisialisasi internal lebih dulu, daftarkan paling akhir, dan saat teardown lepaskan lebih dahulu
- Process context, softirq/tasklet context, dan hardirq context berbeda dalam hal boleh tidaknya sleep, akses memori pengguna,
GFP_KERNEL, dan penggunaan mutex, dan salah memahami perbedaan ini dapat menimbulkan bug kernel yang umum
Hal yang perlu diperhatikan per perangkat dan subsystem
- Perangkat karakter memakai major number untuk mengidentifikasi driver dan minor number untuk membedakan beberapa perangkat di dalam driver, dan pada pendekatan modern, antarmuka
cdevlebih disarankan daripadaregister_chrdev() - Driver PCI tidak mengasumsikan alamat tetap, melainkan memetakan BAR resource yang dienumerasi oleh PCI core, dan pada kode Linux 5.10 ke atas,
pcim_enable_device()serta device-managed resource API berguna untuk mengurangi bug teardown - Driver USB harus memperlakukan hotplug dan disconnect sebagai kejadian normal, dan dirancang dengan asumsi bahwa URB completion dapat berpacu dengan disconnect, timeout, suspend, dan shutdown dari userspace
- Driver block bekerja dengan
blk-mq,request,gendisk, queue limit, dan semantik flush/FUA, dan berpartisipasi dalam model penyelesaian request asinkron, bukan callback read/write sederhana - Driver jaringan terikat dengan
struct net_device,net_device_ops,sk_buff, NAPI, offload feature flag, dan pelaporan link-state, dan deklarasi offload yang salah dapat menyebabkan kerusakan lalu lintas
Menangani perubahan versi kernel
- Contoh menangani perubahan signature
class_create()di Linux 6.4,proc_opsdi Linux v5.6, perubahan tipe nilai balikremove()di Linux 6.11, serta perubahan helperblk-mqantara Linux 5.15 hingga 6.9 melalui kompilasi kondisional - Karena antarmuka internal kernel berubah lebih sering daripada system call, modul yang mendukung banyak kernel sulit menghindari perbandingan
LINUX_VERSION_CODEdanKERNEL_VERSION
Checkpoint keamanan
- Stack kernel jauh lebih kecil daripada stack ruang pengguna, dan pada banyak sistem hanya sekitar 8 KiB atau 16 KiB, sehingga array besar sebaiknya menggunakan
kmalloc()ataukzalloc() - Saat mengirim data ke ruang pengguna dengan
copy_to_user(), semua byte termasuk padding harus sudah diinisialisasi; jika tidak, dapat terjadi kebocoran informasi memori kernel - API yang diawali double underscore seperti
__kmalloc()dan__list_add()dapat mengasumsikan prasyarat internal, sehingga jika dokumentasi tidak memintanya, sebaiknya utamakan wrapper publik
Cakupan yang dihilangkan
- Disebutkan bahwa beberapa chunk asli dihilangkan selama pemrosesan input karena batas panjang dan biaya, sehingga ringkasan ini tidak membahas setiap bab, contoh, dan jalur kode dalam panduan secara lengkap
1 komentar
Komentar Hacker News
QEMU adalah cara yang bagus untuk mencoba pengalaman meretas kernel
Akan menyenangkan jika ada yang memperbarui LDD(Linux Device Drivers) dan buku-buku kernel Linux; karena buku teknis seperti ini sulit menghasilkan keuntungan, sepertinya Linux Foundation juga bisa mensponsorinya
Minggu ini juga, saya mereproduksi dengan QEMU + GDB masalah di v6.8 ketika parameter command line kernel arm64 sepanjang 146 karakter atau lebih membuat kernel langsung berhenti diam-diam, lalu mengemulasikan build kernel arm64 di host Debian 12 Bookworm amd64 dan menelusuri kode bermasalah baris demi baris untuk menemukan penyebabnya
Alurnya adalah, di lingkungan yang sudah memiliki dependensi build dan tool cross-compile, build image kernel arm64 dan skrip untuk GDB, lalu pasang
gdb, jika perlugdb-multiarch, sertaqemu-system-armdi host, kemudian jalankanqemu-system-aarch64dalam keadaan berhenti dengan-S -gdb tcp::1234, dan dari terminal lain attach dengangdb-multiarch ./vmlinuxSetelah itu, di GDB jalankan
target remote :1234,break __parse_cmdline,continue, maka fitur GDB umum seperti memeriksa memori·variabel·stack dan eksekusi satu langkah bisa digunakanUntuk debugging kernel dengan GDB dan skrip
lx-*, lihat https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-...Agar GDB dapat memakai skrip Python
lx-*, biasanya perlu juga mengizinkan path, misalnyaecho "add-auto-load-safe-path ${SRC_DIR}/scripts/gdb/vmlinux-gdb.py" > ~/.gdbinitThread HN terkait: https://news.ycombinator.com/item?id=35782630, https://news.ycombinator.com/item?id=28283030
The Linux Memory Manager juga layak dijadikan referensi: https://linuxmemory.org/chapters
Menurut pembaruan terakhir yang dikirim penulis pada awal Juli, draf pertama sudah selesai, dan sekarang sudah masuk tahap penyuntingan bersama penerbit
Beberapa contoh tampaknya sulit dijalankan langsung
Misalnya “Detecting button presses” mengasumsikan kita bisa membangun modul untuk RPi, tetapi itu sendiri bisa menuntut pekerjaan seperti cross-compiling sehingga mungkin tidak sederhana
Sangat bagus karena rinci, berorientasi praktik, dan berupa tutorial yang langsung mencoba membangun modul kernel
Materi lain yang layak dibaca bersama: https://0xax.gitbooks.io/linux-insides/content/index.html
Saya penasaran di mana tempat yang bagus untuk mempelajari pemrograman kernel Linux secara umum, seperti filesystem atau manajemen memori
Dulu ada “Linux Kernel Development” karya Robert Love, tetapi sepertinya sekarang tidak lagi diperbarui
Pertama kali saya membaca ini sekitar 22 tahun lalu :)