logo

Linux Çekirdek Modülü Programlama: Merhaba Dünya Programı

Çekirdek modülleri, isteğe bağlı olarak çekirdeğe yüklenip kaldırılabilen kod parçalarıdır. Sistemi yeniden başlatmaya gerek kalmadan çekirdeğin işlevselliğini genişletirler. Linux çekirdeklerine özel kodlar iki yöntemle eklenebilir.
  • Temel yol, kodu çekirdek kaynak ağacına eklemek ve çekirdeği yeniden derlemektir.
  • Bunu yapmanın daha etkili bir yolu, çekirdek çalışırken kod eklemektir. Bu işleme modülün yüklenmesi denir; burada modül, çekirdeğe eklemek istediğimiz kodu ifade eder.
Bu kodları çalışma zamanında yüklediğimiz ve resmi Linux çekirdeğinin parçası olmadıkları için bunlara temel çekirdekten farklı olarak yüklenebilir çekirdek modülü (LKM) adı verilir. Temel çekirdek /boot dizininde bulunur ve makinemizi başlattığımızda her zaman yüklenir, LKM'ler ise temel çekirdek zaten yüklendikten sonra yüklenir. Bununla birlikte bu LKM, çekirdeğimizin bir parçasıdır ve işlevlerini tamamlamak için temel çekirdekle iletişim kurarlar. LKM'ler çeşitli görevleri yerine getirebilir ancak temel olarak üç ana kategoriye girerler.
  • aygıt sürücüsü
  • dosya sistemi sürücüsü ve
  • Sistem çağrıları.
Peki LKM'ler ne gibi avantajlar sunuyor? Sahip oldukları en büyük avantajlardan biri, her yeni cihaz eklediğimizde veya eski bir cihazı yükselttiğimizde çekirdeği yeniden oluşturmaya devam etmemize gerek olmamasıdır. Bu, zamandan tasarruf sağlar ve aynı zamanda temel çekirdeğimizi hatasız tutmamıza yardımcı olur. Yararlı bir temel kural, çalışan bir temel çekirdeğimiz olduğunda temel çekirdeğimizi değiştirmememiz gerektiğidir. Ayrıca sistem sorunlarının teşhis edilmesine yardımcı olur. Örneğin, temel çekirdeğe bir modül eklediğimizi (yani temel çekirdeğimizi yeniden derleyerek değiştirdiğimizi) ve modülün içinde bir hata olduğunu varsayalım. Bu, sistem önyüklemesinde hataya neden olur ve çekirdeğin hangi bölümünün sorunlara neden olduğunu asla bilemeyeceğiz. Oysa modülü çalışma zamanında yüklersek ve bu sorunlara neden olursa, sorunu hemen anlarız ve sorunu çözene kadar modülü kaldırabiliriz. LKM'ler tek bir komut satırıyla yüklenip boşaltılabilmeleri açısından oldukça esnektir. Bu, LKM'yi yalnızca ihtiyacımız olduğunda yüklediğimiz için hafızadan tasarruf etmemize yardımcı olur. Üstelik temel çekirdekten daha yavaş değiller çünkü ikisinden birini çağırmak sadece belleğin farklı bir kısmından kod yüklemek anlamına geliyor. **Uyarı: LKM'ler kullanıcı alanı programları değildir. Bunlar çekirdeğin bir parçasıdır. Sistemi serbestçe çalıştırabilirler ve kolayca çökertebilirler. So now that we have established the use loadable kernel modules we are going to write a hello world kernel module. That will print a message when we load the module and an exit message when we unload the module. Code: CPP
/**  * @file hello.c  * @author Akshat Sinha  * @date 10 Sept 2016  * @version 0.1  * @brief An introductory 'Hello World!' loadable kernel  * module (LKM) that can display a message in the /var/log/kern.log  * file when the module is loaded and removed. The module can accept  * an argument when it is loaded -- the name which appears in the  * kernel log files. */ #include  /* Needed by all modules */ #include  /* Needed for KERN_INFO */ #include  /* Needed for the macros */ ///< The license type -- this affects runtime behavior MODULE_LICENSE('GPL'); ///< The author -- visible when you use modinfo MODULE_AUTHOR('Akshat Sinha'); ///< The description -- see modinfo MODULE_DESCRIPTION('A simple Hello world LKM!'); ///< The version of the module MODULE_VERSION('0.1'); static int __init hello_start(void) {  printk(KERN_INFO 'Loading hello module...n');  printk(KERN_INFO 'Hello worldn');  return 0; } static void __exit hello_end(void) {  printk(KERN_INFO 'Goodbye Mr.n'); } module_init(hello_start); module_exit(hello_end); 
Yukarıdaki kodun açıklaması: Çekirdek modülleri en az iki işleve sahip olmalıdır: modül çekirdeğe yerleştirildiğinde çağrılan init_module() adı verilen bir 'başlatma' (başlatma) işlevi ve rmmodlanmadan hemen önce çağrılan cleanup_module() adı verilen bir 'son' (temizleme) işlevi. Aslında çekirdek 2.3.13'ten itibaren işler değişti. Artık bir modülün başlangıç ​​ve bitiş fonksiyonları için istediğiniz adı kullanabilirsiniz. Aslında yeni yöntem tercih edilen yöntemdir. Ancak birçok kişi hala başlangıç ​​ve bitiş işlevleri için init_module() ve cleanup_module() yöntemlerini kullanıyor. Bu kodda, başlangıç ​​işlevi olarak hello_start() işlevini ve temizleme işlevi olarak hello_end() işlevini kullandık. Fark etmiş olabileceğiniz başka bir şey de printf() işlevi yerine printk() işlevini kullanmış olmamızdır. Bunun nedeni, modülün konsolda herhangi bir şey yazdırmaması ancak mesajı /var/log/kern.log dosyasına kaydetmesidir. Bu nedenle çekirdek modüllerinde hata ayıklamak için kullanılır. Ayrıca, başlıkta tanımlanmış ve printk() kullanılırken gerekli olan sekiz olası günlük düzeyi dizisi vardır. Bunları azalan ciddiyet sırasına göre listeledik:
  • KERN_EMERG: Genellikle bir kazadan önce gelen acil durum mesajları için kullanılır.
  • KERN_ALERT: Acil eylem gerektiren bir durum.
  • KERN_CRIT: Genellikle ciddi donanım veya yazılım arızalarıyla ilgili kritik koşullar.
  • KERN_ERR: Hata durumlarını bildirmek için kullanılır; aygıt sürücüleri donanım sorunlarını bildirmek için sıklıkla KERN_ERR'yi kullanır.
  • KERN_WARNING: Kendi başına sistemde ciddi sorunlar yaratmayan sorunlu durumlara ilişkin uyarılar.
  • KERN_NOTICE: Normal ama yine de dikkate değer durumlar. Bu düzeyde güvenlikle ilgili bir takım koşullar rapor edilir.
  • KERN_INFO: Bilgilendirici mesajlar. Birçok sürücü, başlatma sırasında buldukları donanım hakkındaki bilgileri bu düzeyde yazdırır.
  • KERN_DEBUG: Mesajlarda hata ayıklamak için kullanılır.
  • Mesajı yazdırmak için KERN_INFO'yu kullandık. Sistemi kodu çalıştırmaya hazırlama: The system must be prepared to build kernel code and to do this you must have the Linux headers installed on your device. On a typical Linux desktop machine you can use your package manager to locate the correct package to install. For example under 64-bit Debian you can use:
    akshat@gfg:~$ sudo apt-get install build-essential linux-headers-$(uname -r) 
    Kaynak kodunu derlemek için 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 
    **Not: Makefile'daki sekme boşluklarını unutmayın Modülün derlenmesi ve yüklenmesi: Run the make command to compile the source code. Then use insmod to load the module.
    akshat@gfg:~$ make make -C /lib/modules/4.2.0-42-generic/build/ M=/home/akshat/Documents/hello-module modules make[1]: Entering directory `/usr/src/linux-headers-4.2.0-42-generic' CC [M] /home/akshat/Documents/hello-module/hello.o Building modules stage 2. MODPOST 1 modules CC /home/akshat/Documents/hello-module/hello.mod.o LD [M] /home/akshat/Documents/hello-module/hello.ko make[1]: Leaving directory `/usr/src/linux-headers-4.2.0-42-generic' 
    Now we will use insmod to load the hello.ko object.
    akshat@gfg:~$ sudo insmod hello.ko 
    Modülün test edilmesi: You can get information about the module using the modinfo command which will identify the description author and any module parameters that are defined:
    akshat@gfg:~$ modinfo hello.ko filename: /home/akshat/Documents/hello-module/hello.ko version: 0.1 description: A simple Hello world LKM author: Akshat Sinha license: GPL srcversion: 2F2B1B95DA1F08AC18B09BC depends: vermagic: 4.2.0-42-generic SMP mod_unload modversions 
    To see the message we need to read the kern.log in /var/log directory.
    akshat@gfg:~$ tail /var/log/kern.log ... ... Sep 10 17:43:39 akshat-gfg kernel: [26380.327886] Hello world To unload the module we run rmmod: akshat@gfg:~$ sudo rmmod hello Now run the tail command to get the exit message. akshat@gfg:~$ tail /var/log/kern.log ... Sep 10 17:43:39 akshat-gfg kernel: [26380.327886] Hello world Sep 10 17:45:42 akshat-gfg kernel: [26503.773982] Goodbye Mr.