OS: Membuat Kernel Modul

From OnnoWiki
Jump to navigation Jump to search

Sumber:


Pada bagian ini, kita akan menulis dan load sebuah kernel modul sederhana. Dengan menuliskan sendiri modul kita menjadi belajar bagaimana menulis code kernel yang berdiri sendiri, belajar bagaimana menggunakan modul, dan menemukan beberapa aturan bagaimana kernel terkait menjadi satu kesatuan.

Catatan: instruksi disini ditulis untuk kernel 2.6.x yang mungkin tidak cocok untuk versi kernel yang berbeda.

Apakah kernel mendukung modul?

Kernel yang kita gunakan, harus di compile dengan option:

Loadable module support  --->
  [*] Enable loadable module support
  [*]   Module unloading
  [ ]   Module versioning support (EXPERIMENTAL)
  [*]   Automatic kernel module loading    

Pastikan pada saat kita mengcompile kernel opsi di atas di aktifkan. Jika tidak, kita perlu mengcompile ulang kernel.

Rangka Kernel Modul Sederhana

Pertama kali, kita perlu mencari lokasi directory tempat kernel di compile, biasanya di /usr/src/linux. Kemudian ubah directory ke drivers/misc dari directory source code Linux.

Sekarang, copy paste code berikut ke file dengan nama, misalnya, mymodule.c

#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>

static int __init mymodule_init(void)
{
 printk ("My module worked!\n");
        return 0;
}

static void __exit mymodule_exit(void)
{
 printk ("Unloading my module.\n");
        return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

Simpan file .c tersebut. Edit Makefile di directory tersebut. Tambahkan kalimat:

obj-m += mymodule.o

Compile module yang kita tulis:

# make -C [top directory dari source kernel] SUBDIRS=$PWD modules

Jalankan Module

Load module. Tergantung versi kernel yang kita gunakan, ketik:

# insmod ./mymodule.o

Atau:

# insmod ./mymodule.ko

Cek apakah message yang kita ketik keluar:

# dmesg | tail

Kita harusnya melihat di akhir printout sebagai berikut:

My module worked!

Selanjutnya, coba kita buang kernel module tersebut menggunakan perintah:

# rmmod mymodule

Cek output di dmesg, kita harusnya akan melihat:

Unloading my module.

Selamat! Kita baru saja menulis & menjalankan kernel module yang baru.

Interface module/kernel

Selanjutnya, mari kita bermain dengan module yang kita buat. Satu hal yang harus kita sadari bahwa module hanya dapat "melihat" function dan variable yang secara sengaja oleh kernel dibuat terlihat ke module.

Pertama-tama, mari kita coba cara yang SALAH! :) ..

Edit file kernel/printk.c dan tambhakan kalimat berikut sesudah semua include file dan dekat deklarasi variable global (tapi di luar semua function):

int my_variable = 0;

Sekarang compile ulang kernel dan reboot ke kernel yang baru. Selanjutnya, tambahkan kalimat ini di awal dari module kita berupa function mymodule_init, sebelum code lainnya:

extern int my_variable;
printk ("my_variable is %d\n", my_variable);
my_variable++;

Simpan file yang kita ubah, dan di recompile module menggunakan perintah:

# make -C path/to/kernel/src SUBDIRS=$PWD modules

Dan load module (ini harusnya akan gagal):

# insmod ./mymodule.ko

Saat loading module yang kita buat harusnya fail dengan message berikut:

insmod: error inserting './mymodule.ko': -1 Unknown symbol in module

ini artinya kernel tidak mengijinkan module untuk "melihat" variable tersebut. Saat module di load, kernel akan me-resolve semua referensi external, seperti nama function atau nama variable. Jika dia tidak berhasil me-resolve semua nama yang ada dalam daftar simbol yang di export kernel, maka module tidak bisa menulis / menggunakan variable atau call ke function tersebut. Kernel mengalokasi tempat bagi variable my_variable entah mana, sayangnya module tidak bisa menemukannya.

Untuk memperbaiki ini, kita akan memasukan my_varible ke daftar symbol yang di export oleh kernel. Banyak directory di kernel mempunyai file yang di khususkan untuk meng-export symbol yang di definikan dalam directory tersebut. Buka lagi file kernel/printk.c dan tambahkan kalimat berikut sesudah deklarasi varible kita:

EXPORT_SYMBOL_NOVERS(my_variable);

Recompile dan reboot ke kernel yang baru. Sekarang coba untuk load module lagi:

# insmod ./mymodule.ko

Sekarang, saat kita cek dmesg, kita harusnya melihat:

my_variable is 0
My module worked!

Reload module:

# rmmod mymodule && insmod ./mymodule.ko

Sekarang kita akan melihat:

Unloading my module.
my_variable is 1    
My module worked!

Setiap kali kita me-reload module, my_variable harus bertambah satu. Module yang kita buat dapat mengakses variable atau function yang ada di main kernel, selama secara explisit di export melalui deklarasi EXPORT_SYMBOL(). Contoh, function printk() di definisikan di kernel dan di export di file kernel/printk.c.

Membuat loadable kernel module sederhana adalah cara menyenangkan untuk mengeksplorasi kernel. Contoh, kita dapat menggunakan sebuah module untuk menyalakan dan mematikan printk, dengan mendefinisikan variable do_print di kernel yang awalnya di set 0. Maka semua printk menjadi tergantung pada "do_print":

if (do_print)
  printk ("Big long obnoxious message\n");

dan menyalakan do_print jika kernel module yang kita buat di load. Kita dapat mendefinisikan di modul yang kita buat ke daftar function yang di panggil ketika kernel menerima interupsi tertentu (gunakan cat /proc/interrupts untuk mencaritahu interupsi yang digunakan).

The function request_irq() adds your function to the list of handlers for a selected irq line, which you can use to print out a message each time you receive an interrupt on that line. You can investigate the current value of any exported variable by loading a module that reads that value and immediately exits (returns a non-zero value from the module_init() function). The variable jiffies, which increments every 1/100th of a second (on most platforms), is a good candidate for this kind of module.

Play with your new kernel module - modules are fun!

Referensi

Pranala Menarik