Loadable Kernel Module Development

14 Oct 2019 » linux

Kernel Module Nedir ?

Çekirdek modülleri (Kernel modules), talep üzerine çekirdeğe yüklenebilen ve boşaltılabilen kod parçalarıdır. Sistemi yeniden başlatmaya gerek kalmadan çekirdeğin işlevselliğini artırırlar.

Linux çekirdeğine özel kod eklemenin temel yolu, kodu çekirdek kaynak ağacına eklemek ve çekirdeği yeniden derlemektir. Bunu yapmanın daha etkili bir yolu ise çalışırken çekirdeğe kod eklemektir. Bu işleme modül yükleme işlemi denir ve burada ki modül ifadesi çekirdeğe eklemek istediğimiz kodu ifade eder.

Bu kodları çalışma zamanında yüklediğimiz için ve bu kodların resmi Linux çekirdeğinin bir parçası olmadığı için, bunlara temel çekirdekten farklı olan Yüklenebilir Çekirdek Modülü (LKM) denir. Temel çekirdek, boot dizininde bulunur ve makinemizi başlattığımızda her zaman yüklenirken, LKM’ler ise temel çekirdek yüklendikten sonra yüklenir. Bununla birlikte, bu LKM’ler çekirdeğimizin çok büyük bir kısmıdır ve işlevlerini tamamlamak için temel çekirdekle iletişim kurarlar.

LKM’ler çeşitli görevleri yerine getirebilirler, ancak temel olarak aygıt sürücüsü, dosya sistemi sürücüsü ve sistem çağrıları olmak üzere üç ana kategoriye girerler.

Nasıl Yapılır ?

Ufak bir tanımın ardından artık kolları sıvayabiliriz. Yüklendiği zaman “Merhaba Dünya !” , çıkardığımızda ise “Güle güle” diyen basit bir modül yazalım. Bunun için öncelikli olarak boş bir klasör açıp, içerisinde de hello.c adında bir dosya oluşturalım. Dosyamızın içerisine de aşağıda bulunan C kodunu yazıp kaydedelim.

hello.c

Peki bu C kodumuz ne yapıyor ? Hemen açıklayayım.

Öncelikli olarak tabiki de gerekli olan kütüphanelerimizi ekledik :).

#include <linux/module.h>     // Needed by all modules
#include <linux/kernel.h>     // Needed for KERN_INFO
#include <linux/init.h>       // Needed for the macros

Şimdi de geliştireceğimiz modül hakkında bazı bilgiler girelim.

///< The license type
MODULE_LICENSE("GPL");

///< The author  
MODULE_AUTHOR("Alp Eren");

///< The description  
MODULE_DESCRIPTION("A simple Hello world LKM!");

///< The version of the module
MODULE_VERSION("0.1");

Artık modülümüz yüklendikten sonra çalışma aşamasında ne yapacak onu belirleyelim. ( Burada fonksiyon tipimizi ve return tipimizi belirledik. )

static int __init hello_start(void) {   
  printk(KERN_INFO "Loading hello module...\n");
  printk(KERN_INFO "Hello world\n");
  return 0;
}

printk fonksiyonu kernel içerisinde yazdırma işlemi yapan bir fonksiyondur.

Peki ya ilerde yüklenmiş olan modülümüzü kernel içerisinden çıkarmak istersek.

static void __exit hello_end(void) {
  printk(KERN_INFO "Goodbye Mr.\n");
}

Son olarak tüm bu __init ve __exit fonksiyonlarını modül içine yükleyebiliriz.

module_init(hello_start);
module_exit(hello_end);

Modülümüzün içeriği bu kadar. Şimdi de sıra bir adet Makefile dosyası oluşturup make komutu ile tüm bu kodu derlemekte.

makefile

obj-m = hello.o

all:
        make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Artık make komutu ile derleyebiliriz.

make

Ve gördüğünüz gibi bizim modülümüz olan hello.ko dosyası artık hazır.

Modülümüzü kernel içerisine yüklemek için ise insmod komutunu kullanacağız. Modül bilgilerini görmek için ise modinfo komutunu kullanabilirsiniz.

insmod

dmesg komutu ile de kernel da bize gelen mesajı görebiliriz.

dmesg

Modülümüzü başarılı bir şekilde yükledik ve sorunsuz çalıştığını gördük. Son olarak da modülümüzü sistemden nasıl sileceğiz ona bakalım.

rmmod komutu ile modülümüzü başarılı bir şekilde kernel içerisinden çıkarabiliriz.

rmmod

dmesg komutu ile baktığımızda modülümüz içerisinde bulunan __exit fonksiyonunun çalıştığını görebiliriz.

Son olarak yüklü modülleri görmek isterseniz lsmod komutunu kullanabilirsiniz.