Difference between revisions of "OS: Membuat Kernel Modul"

From OnnoWiki
Jump to navigation Jump to search
 
(21 intermediate revisions by the same user not shown)
Line 2: Line 2:
 
* http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
 
* http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
 
* http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html
 
* http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html
 +
* http://www.tldp.org/LDP/lkmpg/2.6/html/x181.html
 +
* http://www.tldp.org/LDP/lkmpg/2.6/html/
  
 +
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.
  
In this lesson, we'll write and load a simple kernel module. Writing your own module lets you write some standalone kernel code, learn how to use modules, and discover a few rules about how the kernel links together. Note: These instructions were written for the 2.6.x kernels and may not work with different kernel versions.
+
Catatan: instruksi disini ditulis untuk kernel 3.8.x yang mungkin tidak cocok untuk versi kernel yang berbeda.
Does your kernel support modules?
 
  
For this lesson, your kernel must have been compiled with these options:
+
==Apakah kernel mendukung modul?==
  
Loadable module support  --->
+
Kernel yang kita gunakan, harus di compile dengan option:
  [*] Enable loadable module support
 
  [*]  Module unloading
 
  [ ]  Module versioning support (EXPERIMENTAL)
 
  [*]  Automatic kernel module loading   
 
  
If you compiled your kernel according to the instructions in the first few kernel lessons, you should already have these options properly set. Otherwise, change these options, recompile the kernel, and boot into your new kernel.
+
[*] Enable loadable module support  --->
A simple module skeleton
+
  [ ]  Forced module loading 
 +
  [*]  Module unloading
 +
  [ ]    Forced module unloading
 +
  [*]  Module versioning support
 +
  [*]  Source checksum for all modules
 +
  [*]  Module signature verification
 +
  [ ]    Require modules to be validly signed
  
First, find the source that your current Linux kernel was compiled from. Change directory to drivers/misc/ in your Linux source code directory. Now, copy and paste the following code into a file named mymodule.c:
+
Pastikan pada saat kita mengcompile kernel opsi di atas di aktifkan. Jika tidak, kita perlu mengcompile ulang kernel.
  
#include <linux/module.h>
+
Sebaiknya, sebelum berexperimen dengan kernel modul, kita mengcompile ulang kernel yang kita gunakan.
#include <linux/config.h>
+
Tentunya lengkap dengan update-grub dan kemudian boot ke kernel baru tersebut untuk berexperimen dengan kernel modul yang kita buat.
#include <linux/init.h>
 
  
static int __init mymodule_init(void)
+
==Rangka Kernel Modul Sederhana==
{
 
printk ("My module worked!\n");
 
        return 0;
 
}
 
  
static void __exit mymodule_exit(void)
+
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. Lakukan di shell
{
 
printk ("Unloading my module.\n");
 
        return;
 
}
 
  
module_init(mymodule_init);
+
cd /usr/src/linux/drivers/misc
module_exit(mymodule_exit);
 
  
MODULE_LICENSE("GPL");
+
Edit file, misalnya, mymodule.c
  
Save the file and edit the Makefile in the same directory. Add this line:
+
vi mymodule.c
  
obj-m += mymodule.o
+
Sekarang, copy paste code berikut ke file mymodule.c
  
Compile your module:
+
#include <linux/module.h>
 +
#include <linux/configfs.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");
  
  # make -C [top directory of your kernel source] SUBDIRS=$PWD modules
+
Simpan file .c tersebut. Edit Makefile di directory tersebut.
  
Load the module. Depending on your kernel version, do that with either:
+
cd /usr/src/linux/drivers/misc
 +
vi Makefile
  
  # insmod ./mymodule.o
+
Tambahkan kalimat:
  
Or:
+
obj-m += mymodule.o
  
  # insmod ./mymodule.ko
+
Compile module yang kita tulis:
  
And check to see if your message printed out:
+
# make -C [top directory dari source kernel] SUBDIRS=$PWD modules
  
  # dmesg | tail
+
Atau yang lebih jelas
  
You should see this at the end of the output:
+
# make -C /usr/src/linux SUBDIRS=$PWD modules
  
  My module worked!
+
===Jalankan Module===
  
Now remove the kernel module:
+
Load module. Tergantung versi kernel yang kita gunakan, ketik:
  
  # rmmod mymodule
+
cd /usr/src/linux/drivers/misc
 +
insmod ./mymodule.ko
  
Check the output of dmesg again, you should see:
+
Atau:
  
  Unloading my module.
+
cd /usr/src/linux/drivers/misc
 +
insmod ./mymodule.o
  
You just wrote and ran a new kernel module! Congratulations!
+
Tampaknya untuk kernel versi 3.8 ke atas lebih aman menggunakan .ko.
The module/kernel interface
 
  
Now, let's do some more interesting things with your module. One of the key things to realize is that modules can only "see" functions and variables that the kernel deliberately makes visible to the modules. First, let's try to do things the wrong way.
+
Cek apakah modul yang kita masukan jalan dengan baik, ketik:
  
Edit the file kernel/printk.c and add this line after all the included files and near the other global variable declarations (but outside all functions):
+
# dmesg | tail
  
  int my_variable = 0;
+
Kita harusnya melihat di akhir printout sebagai berikut:
  
Now recompile your kernel and reboot into your new kernel. Next, add this to the beginning of your module's mymodule_init function, before the other code:
+
My module worked!
  
   extern int my_variable;
+
Cek menggunakan
   printk ("my_variable is %d\n", my_variable);
+
 
 +
# lsmod | more
 +
 
 +
Harusnya keluar kira-kira
 +
 
 +
Module                  Size  Used by
 +
mymodule              12428  0
 +
 
 +
Selanjutnya, coba kita buang kernel module tersebut menggunakan perintah:
 +
 
 +
# rmmod mymodule
 +
 
 +
Cek output di dmesg,
 +
 
 +
# dmesg | tail
 +
 
 +
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
 +
 
 +
vi /usr/src/linux/kernel/printk.c
 +
 
 +
Dan tambahkan kalimat berikut sesudah semua include file dan dekat deklarasi variable global (tapi di luar semua function):
 +
 
 +
int my_variable = 0;
 +
 
 +
 
 +
Atau yang lebih lengkap kira-kira sebagai berikut,
 +
 
 +
#define CREATE_TRACE_POINTS
 +
#include <trace/events/printk.h>
 +
 +
int my_variable = 0;
 +
 +
/*
 +
  * Architectures can override it:
 +
  */
 +
void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
 +
{
 +
}
 +
 
 +
Sekarang compile ulang kernel, update-grub dan reboot ke kernel yang baru.
 +
 
 +
Selanjutnya, tambahkan kalimat berikut di awal dari module kita dalam function mymodule_init, sebelum code lainnya:
 +
 
 +
extern int my_variable;
 +
printk ("my_variable is %d\n", my_variable);
 +
my_variable++;
 +
I
 +
Lebih jelasnya lakukan modifikasi pada function mymodule_init agar menjadi,
 +
 
 +
static int __init mymodule_init(void)
 +
{
 +
   extern int my_variable;  
 +
   printk ("my_variable is %d\n", my_variable);  
 
   my_variable++;
 
   my_variable++;
 +
  printk ("My module worked!\n");
 +
        return 0;
 +
}
  
Save your changes and recompile your module:
+
Simpan file yang kita ubah, dan di recompile module menggunakan perintah:
  
  # make -C path/to/kernel/src SUBDIRS=$PWD modules
+
cd /usr/src/linux/drivers/misc
 +
make -C /usr/src/linux SUBDIRS=$PWD modules
  
And load the module (this will fail):
+
Dan load module (ini harusnya akan gagal):
  
  # insmod ./mymodule.ko
+
cd /usr/src/linux/drivers/misc
 +
insmod ./mymodule.ko
  
Loading your module should fail with the message:
+
Saat loading module yang kita buat harusnya fail dengan message berikut:
  
  insmod: error inserting './mymodule.ko': -1 Unknown symbol in module
+
insmod: error inserting './mymodule.ko': -1 Unknown symbol in module
  
What this is saying is that the kernel is not allowing modules to see that variable. When the module loads, it has to resolve all it's external references, like function names or variable names. If it can't find all of it's unresolved names in the list of symbols that the kernel exports, then the module can't write to that variable or call that function. The variable my_variable has space allocated for it somewhere in the kernel, but the module can't figure out where.
+
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.
  
To fix this, we're going to add my_variable to the list of symbols that the kernel exports. Many kernel directories have a file specifically for exporting symbols defined in that directory. Bring up the file kernel/printk.c again and add this line after the declaration of your variable:
+
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 definisikan dalam directory tersebut. Buka lagi file kernel/printk.c
  
  EXPORT_SYMBOL_NOVERS(my_variable);
+
vi /usr/src/linux/kernel/printk.c
  
Recompile and reboot into your new kernel. Now try to load your module again:
+
dan tambahkan kalimat berikut sesudah deklarasi varible my_variable:
  
  # insmod ./mymodule.ko
+
EXPORT_SYMBOL(my_variable);
  
This time, when you check dmesg, you should see:
+
Atau yang lebih lengkap kira-kira sebagai berikut,
  
  my_variable is 0
+
#define CREATE_TRACE_POINTS
  My module worked!
+
#include <trace/events/printk.h>
  
Reload your module:
+
int my_variable = 0;
 +
EXPORT_SYMBOL(my_variable);
 +
 +
/*
 +
  * Architectures can override it:  
 +
  */
 +
void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
 +
{
 +
}
  
  # rmmod mymodule && insmod ./mymodule.ko
+
Recompile kernel, update-grub dan reboot ke kernel yang baru.  
  
Now you should see:
+
Sekarang coba untuk load module lagi:
  
  Unloading my module.
+
# insmod ./mymodule.ko
  my_variable is 1   
 
  My module worked!
 
  
Each time you reload the module, my_variable should increase by one. You are reading and writing to a variable which is defined in the main kernel. Your module can access any variable or function in the main kernel, as long as it is explicitly exported via the EXPORT_SYMBOL() declaration. For example, the function printk() is defined in the kernel and exported in the file kernel/printk.c.
+
Sekarang, saat kita cek dmesg, kita harusnya melihat:
  
A simple loadable kernel module is a fun way to explore the kernel. For example, you can use a module to turn a printk on or off, by defining a variable do_print in the kernel which is initially set to 0. Then make all your printk's dependent on "do_print":
+
my_variable is 0
 +
My module worked!
  
  if (do_print)
+
Reload module:
    printk ("Big long obnoxious message\n");
 
  
And turn on do_print only when your module is loaded. You can add a function defined in your module to the list of functions that are called when the kernel receives a certain interrupt (use cat /proc/interrupts to find out what interrupts are in use). 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.
+
# rmmod mymodule && insmod ./mymodule.ko
  
Play with your new kernel module - modules are fun!
+
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 mencari tahu interupsi yang digunakan).
 +
 +
function request_irq() menambahkan function yang kita buat ke daftar handler untuk line IRQ (Interrupt ReQuest) tertentu, yang mana kita dapat gunakan untuk mem-print out sebuah message setiap kita menerima interupsi di line tersebut. Kita dapat melakukan investigasi nilai dari variable yang di export dengan cara me-load module yang dapat membaca nilai tersebut dan langsung keluar (return nilai non-zero dari function module_init()). Variabel jiffies, yang naik setiap 1/100 detik (di kebanyakan platform), adalah kandidat yang baik untuk module seperti ini.
 +
 +
Semoga anda cukup bersemangat untuk bermain dengan kernel module!
  
 
==Referensi==
 
==Referensi==
Line 144: Line 247:
 
* http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
 
* http://www.linuxchix.org/content/courses/kernel_hacking/lesson8
 
* http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html
 
* http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html
 +
* http://www.tldp.org/LDP/lkmpg/2.6/html/x181.html
 +
* http://www.linuxvoice.com/be-a-kernel-hacker/
  
 
==Pranala Menarik==
 
==Pranala Menarik==
Line 149: Line 254:
 
* [[Linux]]
 
* [[Linux]]
 
* [[Ubuntu]]
 
* [[Ubuntu]]
 +
* [[Buku Sistem Operasi]]
 +
 +
===Secara Umum===
 +
 
* [[Sistem Operasi]]
 
* [[Sistem Operasi]]
 +
 +
===Instalasi Linux===
 +
 +
* [[Linux: CLI untuk Survival]]
 +
* [[Linux: Skema Partisi di Linux]]
 
* [[Linux: Instalasi Sistem Operasi]]
 
* [[Linux: Instalasi Sistem Operasi]]
* [[Linux: Skema Partisi di Linux]]
+
 
 +
===Compile Kernel===
 +
 
 
* [[Kernel]]
 
* [[Kernel]]
 +
* [[OS: Linux Kernel]]
 +
* [[Kernel: Anatomi Kernel Source]]
 
* [[Compile Kernel]]
 
* [[Compile Kernel]]
 
* [[Compile Kernel: Konfigurasi Kernel]]
 
* [[Compile Kernel: Konfigurasi Kernel]]
* [[Kernel: Anatomi Kernel Source]]
+
 
* [[OS: Linux Kernel]]
+
===Remaster Linux===
 +
 
 +
* [[Cara Cepat Melakukan Remastering Ubuntu]]
 +
 
 +
===Sistem Operasi untuk Embedded===
 +
 
 +
* [[OpenWRT]]
 +
* [[OpenWRT: Download Firmware yang sudah jadi]]
 +
* [[OpenWRT: Source Repository Download]]
 +
* [[OpenWRT: Melihat Daftar Package]]
 +
 
 +
====Membuat Firmware Sendiri====
 +
 
 +
* [[OpenWRT: Build Firmware]]
 +
* [[OpenWRT: Build Firmware Buffalo WZRHPG450H]]
 +
* [[OpenWRT: Build Firmware Buffalo WZRHPG300N]]
 +
* [[OpenWRT: Build Firmware Ubiquiti NanoStation2]]
 +
* [[OpenWRT: Build Firmware Mikrotik RB433]]
 +
* [[OpenWRT: Build Firmware Linksys WRT160NL]]
 +
* [[OpenWRT: Build Firmware Linksys WRT54GL]]
 +
 
 +
====Flash ke Device====
 +
 
 +
* [[OpenWRT: Flash Linksys WRT54GL]]
 +
* [[OpenWRT: Flash Buffalo WZRHP450H]]
 +
* [[OpenWRT: Flash Buffalo WZRHP300N]]
 +
* [[OpenWRT: Flash UBNT NanoStation2]]
 +
 
 +
====Beberapa Tip====
 +
 
 +
* [[OpenWRT: Mikrotik RB433]]
 +
* [[OpenWRT: 3G modem]]
 +
* [[OpenWRT: Build Firmware dengan 3G Modem Support]]
 +
* [[OpenWRT: Setup Firewall]]
 +
* [[OpenWRT: Konfigurasi UBNT NanoStation2 tanpa WebGUI]]
 +
 
 +
===Tuning Kernel===
 +
 
 
* [[OS: Parameter Kernel Default]]
 
* [[OS: Parameter Kernel Default]]
 +
 +
====Tuning Kernel Scheduler====
 +
 
* [[OS: Kernel Scheduler]]
 
* [[OS: Kernel Scheduler]]
 +
* [[OS: Tuning Kernel Scheduler]]
 +
* [[OS: Tuning Completely Fair scheduler CFS]]
 
* [[OS: Complete Teori Tuning Kernel Scheduler]]
 
* [[OS: Complete Teori Tuning Kernel Scheduler]]
 +
 +
====Tuning I/O Scheduler====
 +
 +
* [[OS: Tuning Completely Fair Queueing CFQ I/O scheduler]]
 
* [[OS: Complete Teori Tuning I/O Performance]]
 
* [[OS: Complete Teori Tuning I/O Performance]]
* [[OS: Tuning Kernel Scheduler]]
+
 
* [[OS: Tuning Completely Fair Queueing CFQ I/O scheduler]]
+
====Tuning Manajemen Memory====
* [[OS: Tuning Completely Fair scheduler CFS]]
+
 
 +
* [[OS: Tuning Manajemen Memory]]
 +
 
 +
===Android===
 +
 
 +
* [[OS: Android - Download]]
 +
 
 +
===Membuat Kernel Module===
 +
 
 +
* [[OS: Mengerti System Call]]
 +
* [[OS: Membuat Kernel Modul]]
 +
 
 +
===Monitoring & Benchmark===
 +
 
 
* [[OS: Build in Monitoring Tool]]
 
* [[OS: Build in Monitoring Tool]]
 
* [[Linux Benchmarking]]
 
* [[Linux Benchmarking]]
 
* [[OS: Benchmarking menggunakan UnixBench]]
 
* [[OS: Benchmarking menggunakan UnixBench]]
 
* [[OS: Benchmarking menggunakan LLCBench]]
 
* [[OS: Benchmarking menggunakan LLCBench]]
* [[OS: Mengerti System Call]]
 
* [[OS: Membuat Kernel Modul]]
 

Latest revision as of 17:40, 1 March 2015

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 3.8.x yang mungkin tidak cocok untuk versi kernel yang berbeda.

Apakah kernel mendukung modul?

Kernel yang kita gunakan, harus di compile dengan option:

[*] Enable loadable module support  ---> 
  [ ]   Forced module loading  
  [*]   Module unloading 
  [ ]     Forced module unloading 
  [*]   Module versioning support 
  [*]   Source checksum for all modules 
  [*]   Module signature verification 
  [ ]     Require modules to be validly signed

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

Sebaiknya, sebelum berexperimen dengan kernel modul, kita mengcompile ulang kernel yang kita gunakan. Tentunya lengkap dengan update-grub dan kemudian boot ke kernel baru tersebut untuk berexperimen dengan kernel modul yang kita buat.

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. Lakukan di shell

cd /usr/src/linux/drivers/misc

Edit file, misalnya, mymodule.c

vi mymodule.c

Sekarang, copy paste code berikut ke file mymodule.c

#include <linux/module.h>
#include <linux/configfs.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.

cd /usr/src/linux/drivers/misc
vi Makefile

Tambahkan kalimat:

obj-m += mymodule.o

Compile module yang kita tulis:

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

Atau yang lebih jelas

# make -C /usr/src/linux SUBDIRS=$PWD modules

Jalankan Module

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

cd /usr/src/linux/drivers/misc
insmod ./mymodule.ko

Atau:

cd /usr/src/linux/drivers/misc
insmod ./mymodule.o

Tampaknya untuk kernel versi 3.8 ke atas lebih aman menggunakan .ko.

Cek apakah modul yang kita masukan jalan dengan baik, ketik:

# dmesg | tail

Kita harusnya melihat di akhir printout sebagai berikut:

My module worked!

Cek menggunakan

# lsmod | more

Harusnya keluar kira-kira

Module                  Size  Used by 
mymodule               12428  0 

Selanjutnya, coba kita buang kernel module tersebut menggunakan perintah:

# rmmod mymodule

Cek output di dmesg,

# dmesg | tail

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

vi /usr/src/linux/kernel/printk.c

Dan tambahkan kalimat berikut sesudah semua include file dan dekat deklarasi variable global (tapi di luar semua function):

int my_variable = 0;


Atau yang lebih lengkap kira-kira sebagai berikut,

#define CREATE_TRACE_POINTS 
#include <trace/events/printk.h> 

int my_variable = 0; 

/* 
 * Architectures can override it: 
 */ 
void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) 
{ 
} 

Sekarang compile ulang kernel, update-grub dan reboot ke kernel yang baru.

Selanjutnya, tambahkan kalimat berikut di awal dari module kita dalam function mymodule_init, sebelum code lainnya:

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

I Lebih jelasnya lakukan modifikasi pada function mymodule_init agar menjadi,

static int __init mymodule_init(void) 
{ 
 extern int my_variable; 
 printk ("my_variable is %d\n", my_variable); 
 my_variable++;
 printk ("My module worked!\n"); 
        return 0; 
} 

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

cd /usr/src/linux/drivers/misc
make -C /usr/src/linux SUBDIRS=$PWD modules

Dan load module (ini harusnya akan gagal):

cd /usr/src/linux/drivers/misc
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 definisikan dalam directory tersebut. Buka lagi file kernel/printk.c

vi /usr/src/linux/kernel/printk.c

dan tambahkan kalimat berikut sesudah deklarasi varible my_variable:

EXPORT_SYMBOL(my_variable);

Atau yang lebih lengkap kira-kira sebagai berikut,

#define CREATE_TRACE_POINTS 
#include <trace/events/printk.h> 
int my_variable = 0; 
EXPORT_SYMBOL(my_variable); 

/* 
 * Architectures can override it: 
 */ 
void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) 
{ 
} 

Recompile kernel, update-grub 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 mencari tahu interupsi yang digunakan).

function request_irq() menambahkan function yang kita buat ke daftar handler untuk line IRQ (Interrupt ReQuest) tertentu, yang mana kita dapat gunakan untuk mem-print out sebuah message setiap kita menerima interupsi di line tersebut. Kita dapat melakukan investigasi nilai dari variable yang di export dengan cara me-load module yang dapat membaca nilai tersebut dan langsung keluar (return nilai non-zero dari function module_init()). Variabel jiffies, yang naik setiap 1/100 detik (di kebanyakan platform), adalah kandidat yang baik untuk module seperti ini.

Semoga anda cukup bersemangat untuk bermain dengan kernel module!

Referensi

Pranala Menarik

Secara Umum

Instalasi Linux

Compile Kernel

Remaster Linux

Sistem Operasi untuk Embedded

Membuat Firmware Sendiri

Flash ke Device

Beberapa Tip

Tuning Kernel

Tuning Kernel Scheduler

Tuning I/O Scheduler

Tuning Manajemen Memory

Android

Membuat Kernel Module

Monitoring & Benchmark