Kernel Modülü Programlama


Kernel Programlama ile Kullanıcı Programları Arasındaki Fark?

Kullanıcı programları ya da uygulamalar "user space" diye adlandırdığımız bellek alanında çalışırlar. Kernel programları ise "kernel space" diye adlandırdığımız başka bir bellek alanında çalışırlar. İki bellek alanı birbirinden bağımsızdır. Direkt olarak haberleşemez ve birbiriyle iletişim kuramazlar. Aradaki bağlantı sistem çağrı katmanı aracılığıyla gerçekleşir. Kernel programları her zaman süper erişim modunda çalışır. Yani bir bakıma kernel programlama, sistemdeki her şeye ama her şeye erişim gücü demek oluyor.

Aynı zamanda performans gerektiren işlemler de kernel düzeyinde gerçekleştirilir. Mesela kullanıcı katmanında kullanılabilecek en iyi algoritma ile hacklenecek bir Wi-Fi ağı en az 10-15 dk zaman alırken aynı işlem kernel katmanında saniyelere kadar indirgenebilir. Çünkü kernel katmanında bellek gerektirmeden çok hızlı işlemler gerçekleştirilebilir. Uzay mekiklerinde de programlar kernel katmanında yazılır ve çalıştırılırlar. Çünkü bu daha yüksek performans ve daha az enerji demek oluyor. 

Kernel Modülü Nedir?

Loadable Kernel Module (LKM) yani türkçesiyle yüklenebilir çekirdek modülü Linux kernel' ına kod ekleme ve kod çıkarmaya yarayan mekanizmaya verilen isimdir. Genellikle kernel' ın donanımını nasıl kullanması gerektiğini bilmediği aygıtların sürücü yazılımları için kullanılır. 

Neden Modül Programlama?


Kernel, sistemi açılışından kapanışına kadar ayakta tutan ve çalıştıran büyük bir kod bloğundan oluşmakta. Her defasında koca kernelda değişiklikler yaptıktan sonra onu derlemek işkence haline gelebilir. Kernel' a, log' a "Hello World" yazdıracak bir kod parçacığı eklense bile onu derlemek saatlerimizi alabilir. Modüler programlamada ise istediğimiz kod parçacıklarını modüller içerisine yazabilir, yazdığımız modülleri kernel' a sonradan ekleyebilir ve çıkarabiliriz. Hem de bütün bunları sistemi durdurmadan, reboot atmadan, çalışır vaziyetteyken yapabiliriz.

LKM Oluşturmak İçin Sistemi Hazırlama

Sistemimizi kernel kodlarını oluşturabilmemiz için hazır hale getirmeliyiz. Bunun için de Linux Header' larını bilgisayarımıza yüklemeliyiz. Bunun için sistemimizin kendi paket yöneticisini kullanabiliriz. 

sudo apt-get update

komutuyla sistemimizi güncelliyoruz.

apt-cache search linux-headers-$(uname -r)

komutuyla sistemimizde çalışan kernel' a ait headerları arıyoruz.


Son güncel kernel' a ait header bulamadık. Mecbur olarak

sudo apt-get install linux-headers-

yazdıktan sonra çift tab basarak en son kernel' a ait header' ları kuruyoruz.


Zaten son sürüm ile header' larımız da yüklü gelmiş.

Modül Kodu

Kernel modülü programlama dilleriyle yazdığımız uygulamalardan bir takım farklılıklar gösterir. Başlatmak için bir main() metodu yoktur. 
  • Sıralı olarak çalıştıralamaz. 
  • Otomatik olarak temizlenmez.
  • printf() fonksiyonları yoktur. (buna benzeyen, loga çıktı verebilen printk() fonksiyonu vardır. )
Yazacağımız kodun birkaç özelliğinden bahsettikten sonra terminale dönebiliriz. Yazacağımız kodda C programlama dilini kullansak da kendine has bir formata uygun şekilde kod yazmamız gerekiyor. Kullanacağımız metin editörünün olabildiğince basit olmasına dikkat etmeliyiz. Çünkü gelişmiş editörler dosyayı kapatırken dosyanın sonuna gizli end of file gibi kod parçacıkları ekleyebiliyor. Bu da modülü derlerken hata almamıza sebep olabilir.

mkdir Linux-Kernel-Modules

komutuyla yeni bir klasör açtıktan sonra içerisine girip

vi Sum.c

komutuyla vi editöründe temiz bir sayfa açıyoruz.

vi editöründe yeteri kadar sinirimizi bozduktan sonra daha kullanışlı olan nano editörüne dönebiliriz. Ya da vi editörünün son kullanıcıya daha çok hitap eden vim versiyonunu yükleyip kullanabilirsiniz.

nano Sum.c 

komutu ile açtığımız dosyanın içerisine giriyoruz.

/**
* @file    Sum.c
* @author  Abdulkadir Azmanoglu
* @date    14 Ekim 2017
* @version 0.1
* @brief   Parametre olarak iki değişkeni kullanıcıdan
* alarak toplayan ve /var/log/kern.log dosyasına yazan 
* bir kernel modulu
* @see     http://abdulkadirazm.blogspot.com.tr adresinden
* tum detaylara ulasabilirsiniz.
*/ 

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

MODULE_AUTHOR("Abdulkadir Azmanoglu");
MODULE_DESCRIPTION("Kullanıcıdan alınan iki sayıyı toplayan bir modul.");
MODULE_VERSION("0.1");

static int numberOne = 0;
static int numberTwo = 0;

module_param(numberOne, int, 0);
module_param(numberTwo, int, 0);

/** @brief LKM modulunu kernela yukleyecek olan fonksiyon
*   basarili ise return degeri sifir donecek.
*/
static int __init Sum_init(void){
printk(KERN_INFO "Merhaba! Modul yuklendi.\n Sayilarin toplami: %d", numberOne+numberTwo);
return 0;
}

/** @brief LKM modulunu kerneldan kaldiran fonksiyon. Init fonksiyonunun
*   aksine geriye bir deger donmez.
*/
static void __exit Sum_exit(void){

printk(KERN_INFO "Hoscakal! Modul kerneldan kaldirildi.");
}


/** @brief Modulun sahip olmasi gereken module_init() ve module_exit() 
*   fonksiyonları olmasi gerekir ve bunlari linux/init.h kutuphanesine
*   tanitmamiz gerekir.
*/
module_init(Sum_init);
module_exit(Sum_exit);

kodlarını yazıyoruz ve kaydedip çıkıyoruz.


Şimdi de Makefile dosyası oluşturacağız.

nano Makefile

komutuyla yeni bir dosya oluşturup içerisine 

obj-m+=Sum.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

kodlarını yazıyoruz.


Her şey yolunda görünüyor. Dosyalarımızı ls -l komutuyla kontrol edip bir bakalım.


make komutuyla dosyalarımızı derliyoruz


Burada birkaç hata aldık. İlk hatamız Syntax hatası. module_param(numberOne,int,0) yazacağımız yerde mudole_param(numberOne,int,0) yazmışız.
İkinci hatamız da parametreler için yaptığımız description' ların eksik olmasından kaynaklı. Hata almamak adına description' ı koddan kaldırıyorum ve tekrar derliyorum.


ls komutuyla da görüldüğü gibi derleme işlemi başarıyla gerçekleşmiş ve Sum.ko dosyamız oluşturulmuş. Şimdi insmod komutuyla modülü kernela yükleyelim

sudo insmod Sum.ko numberOne=53 numberTwo=34


lsmod komutuyla görüldüğü gibi modülümüz kernela başarıyla yüklendi.

şimdi root olup log dosyası içerisinde aldığımız çıktıyı görüntüleyelim

cd /var/log/

dizinine gidip

tail -f kern.log

komutunu çalıştırıyoruz


başta hızlı davranmadığım için birden fazla deneme gerçekleştirdim ve mesajı yakaladım :)

yüklediğimiz modülü kaldırmak için de 

rmmod Sum.ko 

komutunu çalıştırıyoruz. Exit fonksiyonu içerisine yazdığımız mesajın da log' a düştüğünü görebiliriz.


Böylece basit bir modül yazarak kernel' a ekledik ve işimiz bittiğinde de kernel' dan kaldırdık.

Yorumlar

Yorum Gönder

Bu blogdaki popüler yayınlar

ITIL SÜREÇLERİ ve YAZILIM KALİTE METRİKLERİ

Linux Kernel Son Sürümünü Derleme

Klavye Ledlerini Yakıp Söndüren Character Device Driver Uygulaması

Raspberry Pi ile Konuşacak Sensörden Gelen Verileri Loga Yazdıran Character Device Driver Uygulaması

Linux Dört İşlem Yapan Proc Uygulaması