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.
- aygıt sürücüsü
- dosya sistemi sürücüsü ve
- Sistem çağrıları.
/** * @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 world n ' ); 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.koModü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 modversionsTo 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.