Linux Kernel Modülü Geliştirme

Serbay Özkan
11 min readApr 9, 2021

--

Bu yazıda çok basit bir linux kernel modülünü (helloworld.ko) hem host PC’de hem de embedded linux bir cihazda (BeagleBoneBlack) çalıştırmak için gerekli adımlardan ve teknik altyapıdan bahsetmeye çalışacağım.

İhtiyaca göre hem çalışma sırasında hem de en başta kernel derleme işlemlerinde Linux kernel’ine ekleyip çıkarabildiğimiz kod parçacıklarına Linux Kernel Module denilmektedir.

Kernel modülü bir kere sisteme eklendikten sonra artık bu modüller ile sağladığımız fonksiyonellikleri sistemin yeniden başlatılmasına ihtiyaç duymadan kullanabilmekteyiz.

Kernel modülü kernel’in fonksiyonelliğini genişleterek ona cihaz ve dosya sistemi sürücüleri, sistem çağrıları gibi önemli özellikler eklememize imkan vermektedir.

Kernel modül desteği embedded linux cihazların minimal bir kernel imajı ile var olup daha sonrasında ihtiyaca göre opsiyonel cihaz sürücüsü ve diğer özelliklerin eklenmesine imkan vermektedir. Örneğin hot-pluggable bir cihaz (USB) takıldığında kernel modülü linux kernel tarafından otomatik olarak yüklenerek yeni bir cihazın insert olmasına imkan vermektedir. Cihaz sürücüsü (Device Driver) bir kernel modülüdür.

Statik ve Dinamik Linux Kernel Modülleri

Statik Linux Kernel Modülü

Linux kernel derlerken menuconfig aracını kullanarak hangi modüllerin statik hangi modüllerin dinamik olarak derlenmesini istediğimizi belirtebiliyoruz. Statik kernel modülleri nihai linux kernel imajının bir parçası olmaktadır. Bu metod doğal olarak linux kernel imajının boyutunu büyütmektedir. Statik kernel modülleri linux kernel imajına linklenmiş olduğu için modülü daha sonradan kernel’dan çıkarabilmemiz mümkün değildir. Her zaman bellekte bu statik modüller yer kaplar.

Dinamik Linux Kernel Modülü

Dinamik linux kernel modülleri nihai kernel imajın içerisinde yer almaz. Bu modüller .ko (kernel object) yaratılması için ayrı olarak derlenir ve ayrı olarak link edilir. Dinamik linux kernel modüllerini user space’den insmod, modprobe, rmmod gibi programları kullanarak dinamik olarak kernel’e ekleyip çıkarmamız mümkündür.

User Space ve Kernel Space Kavramları

User Space

User Space bütün user process’lerinin çalıştığı ve doğrudan donanıma ve cihaz sürücülerine erişimin olmadığı alandır. Kernel programlarına erişim sistem çağrıları (system call) ile yapılabilmektedir. User space’de CPU restricted modda çalışmaktadır.

Kernel Space

Kernel space içerisinde kernel seviyesi kodlar yer almaktadır ve bu alanda işlemci komutlarına, belleğe ve çevresel birimlere tam erişimimiz bulunmaktadır. Kernel space’de CPU privileged modda çalışmaktadır.

User Space / Kernel Space

Linux Kernel Modül Kaynak Kodu Yapısı

Genel sentaksı anlatmak için aşağıda bir hello world kernel modülü yazılmıştır ve bu yazı boyunca bu örnek üzerinden gidilecektir.

Header Bölümü

Her linux kernel modülü <linux/module.h> başlık dosyasını içermek zorundadır. Bu başlık dosyasında kernel modüle yazarken kullandığımız makroların tanımlamaları bulunmaktadır.

Linux kernel header’ları /include/linux/ altında yer almaktadır.

Kernel modülümüz kernel space’de yer alacağı için bu modül içerisinde user space header kullanabilmemiz mümkün değildir. User space header’lara örnek olarak standart C kütüphane (stdio.h, stdlib.h…) header’larını söyleyebiliriz. Hiç bir user space header’i kernel modülüne link edilmez.

Initilization ve Cleanup Bölümü

Kernel modülü yazarken tipik olarak iki entry point kullanılmaktadır. Bunlardan biri modüle init entry point diğeri ise module exit veya module clean-up entry pointtir.

Örneğimizde de görüldüğü gibi helloworld modül kodumuzda herhangi bir main fonksiyonu bulunmamaktadır. Kernel modüllerinde biz sadece entryleri yazıyoruz.

Module initilization fonksiyonu int bir değer döndürmektedir. 0 döndürmesi init sürecinin başarılı olduğunu belirtirken sıfır olmayan bir değer ise hata olduğunu belirterek module init sürecinin başarısız olduğunu belirtmektedir ve bu da ilgili modülün kernel tarafından yüklenememesi ile sonuçlanmaktadır.

Module initilization fonksiyonu kernel modülümüz için bir main fonksiyonudur aslında. Statik kernel modül olarak düşünürsek bu fonksiyon boot zamanında kernel tarafından çağrılacaktır. Dinamik kernel modül olarak düşündüğümüzde de ilgili kernel modülümüz insert edildiği zaman çağrılacaktır.

Module initilization fonksiyonu içerisinde genel olarak yapılanları aşağıdaki gibi özetleyebiliriz.

  • Cihaz ilklendirmeleri yapılabilir.
  • Özel veri yapıları ilklendirilebilir.
  • Kernel veri yapıları ve servisleri için dinamik bellek istemi yapılabilir.
  • Cihaz dosyası yaratılabilir.

Module Initilization ve Module Cleanup fonksiyonları modüle özel fonksiyonlardır ve başka modüllerden çağrılmamaları gerekir. Bu yüzden bu fonksiyonlar static anahtar’ı ile ilgili kaynak koduna özel tanımlanmıştır.

Module Cleanup Fonksiyonu

Bu fonksiyon kernel modülü kaldırıldığında çağrılan fonksiyondur. Statik kernel modüllerimizi daha sonradan kaldıramadığımız için bu fonksiyon sadece dinamik kernel modülleri için işlevseldir. Örneğin biz bir dinamik kernel modülünü sonradan rmmod ile kaldırdığımızda doğrudan bu fonksiyon çağrılacaktır.

Eğer yazdığımız kernel modülü her zaman statik bir modül olarak çalışacaksa bu fonksiyonun implemente edilme zorunluluğu bulunmamaktadır. Hatta statik kernel modülümüz cleanup fonksiyonuna sahip olsa bile kernel build sürecinde __exit etiketine sahip fonksiyonlar işleme alınmaz.

Module cleanup fonksiyonu içerisinde genel olarak yapılanları aşağıdaki gibi özetleyebiliriz.

  • Tipik olarak module init fonksiyonu içerisinde yapılan işlemlerin tersi yapılır.
  • Init fonksiyonu içerisinde alınmış dinamik bellek varsa bu fonksiyon içerisinde önceden alınan bellek serbest bırakılır.

__init and __exit makroları

Bu makroların tanımlamaları /include/linux/init.h içerisinde yer almaktadır.

#define __init __section(“.init.text”)#define __exit __section(“.exit.text”)

Görüldüğü üzere aslında bu makrolar birer compiler directive’idir.

__section compiler directive’i bir veriyi ya da kod parçasını .init veya .exit output section’ununda tutması için compiler’i yönlendirmektedir. Bu directive’lere compiler directive’in yanı sıra compiler attributes de denilmektedir.

  • __init ve __exit makroları sadece static modüller için anlamlıdır.
  • __init makrosu bir compiler directive’ine dönüşerek işaret edilen fonksiyon kodunun compiler tarafından nihai linux kernel image elf içerisinde .init section’ununa yerleştirmesini sağlamaktadır. En sonda da linker işaretlenmiş bu fonksiyonları alarak nihai binary dosyanın sonuna veya başına bunları yerleştirmektedir. Bu özelliğin kullanılması için linker’a bu işaretlenmiş fonksiyonların nereye yerleştirilmesi gerektiğini belirten özel bir linker script dosyası kullanılmaktadır.
  • Bütün initilization fonksiyonları çağrıldıktan sonra .init section’u boot zamanında kernel tarafından free edilmektedir.
  • Static (built-in) modüller daha sonradan tekrar yüklenip kaldırılamadığı için bir sonraki boot süreci başlayana kadar bir daha çağrılamazlar bu yüzden de init fonksiyon referanslarının tutulmasına gerek kalmamaktadır.
  • __init makrosunu bir fonksiyon ile kullanmak kernel’ın bu fonksiyonu boot sürecinde bir defa çağırdıktan sonra free etmesini sağlamak için kullanılan bir tekniktir.
  • Fonksiyonlarda __init kullanarak uygulanan bu tekniği değişkenlerde de __initdata makrosu kullanarak uygulanabilmektedir. Yani bu durumda da ilgili değişkenler boot sürecinden sonra free edilir.

Sistemimizde yüzlerce kernel modülü olduğunu ve bu modüllerin init fonksiyonlarının sadece bir defa çağrılacağını düşünürsek bunları boot sürecinden sonra bellekte tutmanın hiçbir anlamı olmayacağı için bu şekilde bir teknik uygulanabilmektedir.

Daha önceden de söylediğimiz gibi statik (built-in) kernel modüllerinde cleanup fonksiyonu çağrılmıyor çünkü böyle bir ihtiyaç bulunmamaktadır. Bu yüzden __exit ile işaretlediğimiz cleanup fonksiyonları kernel build sürecinde exclude edilmektedir.

Linux Kernel Modül Entry Point Kaydı ve Diğer Makrolar

module_init ve module_exit makroları init ve cleanup fonksiyonlarımızı kernel’a kaydetmek için kullanılır. Bu ikisi birer fonksiyon değil makrodur ve tanımlamaları /include/linux/module.h içerisinde yer almaktadır.

module_init() makrosu parametre olarak verilen fonksiyonu kernel’in init entry point veri tabanına module_exit() makrosu da parametre olarak verilen fonksiyonu exit entry point veri tabanına eklemektedir.

pr_info fonksiyonu da kernel print (printk) fonksiyonun sadece sarmalanmış (wrapper) halidir.

#define pr_info(fmt,arg…) \printk(KERN_INFO fmt,##arg)

Linux Kernel Modülü Derleme

Bir linux kernel modülü iki farklı şekilde derlenebilir.

  • Statik olarak derlenip kernel imajına dahil edilebilir.
  • Dinamik olarak derlenerek çalışma sırasında yüklenebilir.

Dinamik olarak yüklenebilen kernel modülleri de kendi içerisinde ikiye ayrılmaktadır.

  • In-tree module
  • Out-of-tree module

Linux kernel’in zaten içinde var olan ve günümüzde de bakımına devam edilen modüllerine in-tree modüller denilmektedir.

Bizim yazdığımız hello world kernel modülü aslında bir out-of-tree modülü olmaktadır. Out-of-tree kernel modülleri için kernel “out-of-tree module has been loaded” adında bir warning üretmektedir ancak bu bilgi amaçlı bir warning olduğu için güvenli bir şekilde bu uyarıyı önemsemeyebiliriz.

Out-of-tree Kernel Modülü Derleme

Linux kernel modülleri Linux Kernel’in build sistemi olan “kbuild” kullanılarak derlenmektedir. Build işlemi için build içinde yer alan konfigürasyon ve başlık dosyalarını içeren bir prebuilt kernel kaynağına sahip olmak zorundayız.

Eğer kernel konfigürasyonununda bir değişiklik yapılmışsa bu sayede yazdığımız kernel modülünün otomatik olarak yeni ve doğru kernel config ile derlenmesi sağlanacaktır. kbuild kullanırken arka planda bütün compiler switch’leri otomatik olarak alınmaktadır.

Bir linux versiyonunda derlediğimiz bir modülü başka bir linux versiyonunda yüklediğimizde yüklemede sorun yaşayabiliriz ya da yükleme işlemi başarılı olsa bile çalışma sırasında beklenmedik sorunlarla karşılaşabilmemiz mümkündür.

Bu yüzden kural olarak hangi kernel versiyonu için modül geliştireceksek o kernel versiyonunun precompile edilmiş bir kernel kaynağı bulunmalıdır ve kernel modülü derleme işlemimizi bu kernel kaynağına karşı yapmalıyız.

make -C <kernel_source_tree_path> M=<local_module_path> [target]

Yukarıda komut içerisinde belirtilen -C argümanı ile make build sistemi ilk olarak Linux Kernel Source Tree içerisine girmektedir ve top level make dosyası çalıştırılmaktadır. Kernel build sistem bu şekilde tetiklenmektedir. Top level make file çalıştığında bütün compiler argümanları, dependency listesi gibi gerekli bütün parametreler kernel modülünü derlemek için faydalanılmaktadır.

Daha sonra make’i lokal make dosyamıza yönlendirmemiz gerekmektedir. Bunun için de komut içinde gördüğümüz M argümanı ile birlikte lokal make dosyamızın bulunduğu dosya yolunu belirtiyoruz. Yani burada M argümanı aslında module kaynağımızın ve make dosyamızın lokasyonunu belirtmektedir.

Özetle biz ilk başta Linux Kernel’in top level make dosyasının tetiklenmesini sağladık daha sonra da kernel build sistem akışının lokal modül kaynak dosyamızın ve make dosyamızın olduğu yere gelmesini sağladık.

Burada [target] olarak kullanabileceğimiz seçenekler aşağıdaki gibidir.

  • modules (Varsayılan target seçeneğidir. Herhangi bir target belirtilmez ise bu çağrılır. Sadece derleme işlemi yapılmaktadır)
  • modules_install (Derleme işleminin yanında derlenen modüllerin kernel’in modules klasörüne yüklenmesini sağlamaktadır. Varsayılan dosya yolu /lib/modules/<kernel_release>/extra/ idir ancak bu dosya yolu INSTALL_MOD_PATH ile değiştirilebilmektedir)
  • clean (Üretilmiş bütün dosyaların kaldırılmasını sağlar)
  • help (Modül derlemesi için sunulan target’ları listelemektedir)

Peki top level make dosyasından sonra lokal make dosyamız çağrılacak demiştik. Lokal make dosyası içinde neler var?

obj-<X> := <module_name>.o

Yukarıda make içerisinde nasıl kbuild değişkeni tanımlaması yapılacağı belirtilmiştir. Burada X olarak belirtilen parametre aşağıdaki seçenekleri alabilmektedir.

  • obj-n (Modül derlenmeyecek)
  • obj-y (Modül statik olarak derlenecek ve kernel imajına link edilecek)
  • obj-m (Modül dinamik olarak derlenecek ve kernel imajına yüklenebilecek)
obj-m := helloworld.o

Lokal modül klasörümüzde bir Makefile dosyası yaratıp yukarıdaki gibi tanımlanmış bir kbuild değişkenini bu dosya içerisine yazıyoruz. Bu Makefile ile dinamik olarak derlenen, daha sonradan kernel imajına yüklenip/çıkarılabilen ve helloworld.o output kodunun link edilmesiyle oluşan helloworld.ko adında bir kernel modülü oluşacaktır.

Yukarıda da görüldüğü gibi helloworld.c kaynak dosyası değil helloworld .o dosyası kbuild objesine karşılık olarak tanımlanmaktadır ve link sürecinden sonra da helloworld.ko olarak kernel module dünyaya gelmektedir.

Host PC üzerinde out-of kernel modülü derleme ve test

helloworld.c kernel modülünü PC üzerinde yer alan linux kernel versiyonunu içeren build klasörünü referans göstererek derleyeceğiz. Linux makinemizin kernel versiyonunu aşağıdaki komutla öğrenebilmemiz mümkündür.

uname -r5.4.0–70-generic

Daha sonra kernel modül kaynak kodumuzun (helloworld.c) ve lokal make dosyamızın (Makefile) yer aldığı dosya yolu bilgisi ile daha önceden formatını anlattığım make komutunu aşağıdaki gibi çağırıyoruz.

sudo make -C /lib/modules/5.4.0-70-generic/build/ M=$PWD modulesmake: Entering directory '/usr/src/linux-headers-5.4.0-70-generic'Building modules, stage 2.MODPOST 1 modulesmake: Leaving directory '/usr/src/linux-headers-5.4.0-70-generic'lshelloworld.c    helloworld.mod.c  Makefile
helloworld.ko helloworld.mod.o modules.order
helloworld.mod helloworld.o Module.symvers

Bu işlem sonunda yukarıda görüldüğü gibi helloworld.ko dosyası oluşacaktır.

Bu kernel modülümüzü artık insmod ve rmmod kullanarak dinamik olarak kernel’a ekleyip çıkarabiliriz. Kernel loglarını da dmesg ile console’a yazdırabilmemiz mümkündür. Eğer kernel loglarımızın dmesg ile kernel ring buffer’ından çekmek için ayrı bir komut çağırmak istemiyorsanız ve logların direk console’da görünmesini istiyorsanız kernel message log level önceliğinin console log level önceliğinden daha büyük olarak ayarlanması gerekmektedir. Bu ayarlamaları linux kernel derlerken menuconfig üzerinden ya da /proc/sys/kernel/printk dosyasına yazarak değiştirebilmek mümkündür.

Menuconfig -> Kernel hacking -> printk and dmesg options
sudo insmod helloworld.kosudo rmmod helloworld.kodmesg. . .. . .[ 4066.529127] Hello World LKM Initilization...[ 4076.791138] Hello World LKM Cleanup…

BeagleBoneBlack üzerinde out-of tree kernel modülü derleme ve test

Host PC üzerinde yazdığımız helloworld.c kernel kaynak kodumuzu cross-compiler aracılığı ile BeagleBoneBlack üzerinde çalışacak bir kernel modülü haline getirebilmemiz mümkündür.

Beaglebone black üzerinde çalışacak kernel modülümüzü derlemek için öncelikle BBB üstünde yüklü kernel versiyonuna bakıyoruz. Benim elimdeki board üzerindeki kernel versiyonuna baktığımda aşağıdaki gibi gözükmektedir.

uname -r4.14.108-ti-r113

Beaglebone linux kernel kodlarının olduğu github hesabında ilgi sürümün kaynak kodlarını buradan indiriyoruz.

Daha sonra indirdiğimiz kaynak kodlarının bulunduğu dosya yolunda aşağıdaki komutları sırayla çalıştırıyoruz. Son komutta Kernel kodlarının olduğu dosya yolu benim bilgisayarımdaki hali ile gözükmektedir bunu değiştirmeniz gerekmektedir.

make ARCH=arm CROSS-COMPILE=arm-linux-gnueabihf- distcleanmake ARCH=arm CROSS-COMPILE=arm-linux-gnueabihf- bb.org_defconfigmake ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j8sudo make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C /home/serbay/Desktop/BeagleBone_Linux_Kernel_4.14/linux M=$PWD modules

Yukarıdaki komutlardan sonra lokal modülümüzün olduğu klasörümüzde Host PC’de LKM build işlemi sonrasında elde ettiğimiz aynı dosyalar Target için de oluşacaktır.

lshelloworld.c    helloworld.mod.c  Makefile
helloworld.ko helloworld.mod.o modules.order
helloworld.mod helloworld.o Module.symvers

Artık helloworld.ko modülümüz BBB üzerinde de çalışacak hale dönüşmüştür. PC’den BeagleBoneBlack’e bu dosyayı Secure Copy (scp) aracını kullanarak kopyalayabilmemiz mümkündür. Bunun için aşağıdaki komutu kullanabiliriz.

scp <module_name.ko> <username>@<ipaddress>:/<path>scp helloworld.ko debian@192.168.1.33:/home/debian/

Bu komut sonrasında helloworld.ko dosyamız artık BBB içerisinde belirttiğimiz klasöre kopyalanacaktır ve daha sonra kernel modülümüzü Host PC’de yaptığımız gibi aşağıdaki komutlarla test edebiliriz.

sudo insmod main.kosudo rmmod main.kodmesg. . .. . .[ 4066.529127] Hello World LKM Initilization...[ 4076.791138] Hello World LKM Cleanup…

Derlediğimiz kernel modülünün bilgilerine modinfo komutu ile erişebilmekteyiz. Görüldüğü üzere kernel modülümün Linux 4.14.108 versiyonu ve ARMv7 işlemci mimarisi için derlendiğini bu şekilde doğrulamamız mümkündür.

modinfo helloworld.ko
filename: /home/serbay/Desktop/HelloWorldLKM/helloworld.ko
board: BeagleBoneBlack LKM
description: Hello World Kernel Module
author: Serbay Ozkan
license: GPL
depends:
name: helloworld
vermagic: 4.14.108+ SMP preempt mod_unload modversions ARMv7 p2v8

BeagleBoneBlack üzerinde in-tree kernel modülü derleme ve test

Linux kernel menuconfig içinde yazdığımız kernel modülümüzün listelenmesini istiyorsak bunun için Kconfig dosyası yaratmak ve kullanmak zorundayız. Bu sayede menuconfig aracını kullandığımızda modül konfigürasyonumuz bir menü halinde karşımıza gelecektir.

  • Daha önceki adımlarda github üzerinden BBB için indirdiğimiz linux kernel kaynak klasörü içerisinde /drivers altında istediğimiz bir subdriver’in altına yeni bir klasör açılır. Test amaçlı olarak drivers altında char (character device) altında helloworld adında bir klasörü oluşturulabilir. ( /drivers/char/helloworld/)
  • Modül kaynak kodu (helloworld.c) yeni yarattığımız helloworld klasörüne kopyalanır.
  • Kconfig adında bir dosya oluşturulur ve içerisine aşağıda belirtilen entry girilir. Kconfig yazım sentaksının detaylarına buradan ulaşmanız mümkündür. menu ile başlayan ve endmenu ile biten bir blok oluşturulur. İçerisine de menuconfig üzerinde modülün hangi string ile gözükeceği, seçimlerinin ve default değerinin ne olacağı belirtilir.
menu “helloworldmodule”config CUSTOM_HELLOWORLD    tristate “helloworld module support”    default mendmenu
  • Lokal olarak oluşturulan Kconfig dosyamızın entry’si upper level Kconfig dosyasına girilir. Upper level Kconfig dosyası bir üst klasör olan /drivers/char/ altındadır. Bu dosyayı açarak son satırına aşağıdaki entry’i ekliyoruz.
source "drivers/char/helloworld/Kconfig"
  • Lokal Makefile yaratılır.
touch Makefile
  • obj-<config-item> += <module_name>.o formatında oluşturulan komut Makefile dosyasına yazılır. config_item menuconfig üzerinden geleceği için onu komuta CONFIG_ prefixi ekleyerek parametre olarak geçiyoruz.
obj-$(CONFIG_CUSTOM_HELLOWORLD) += helloworld.o
  • Son olarak da lokal make dosyamızın entry’si upper level make dosyasına tanıtılması lazım. Kconfig dosyasında yaptığımız gibi Makefile için de upper level Makefile içerisinde kendi make dosyamızı belirtmemiz gerekmektedir. Bunun için yine bir üst klasöre (/drivers/char/) çıkılır. Burada direk makefile entry’isini dosya yolu olarak eklediğimiz için varsayılan olarak obj-y kullanılır ve aşağıdaki komut upper level Makefile dosyasının sonuna eklenir.
obj-y += helloworld/

Artık bu aşamadan sonra menuconfig’imizi çağırmak için Linux Source Tree içerisinde top level klasörüne gidilir ve aşağıdaki komutla çağrılır.

make ARCH=arm menuconfig

menuconfig içerisine Character devices altında helloworld modülümüzün tanımlandığı görülür.

Bu sayfadan çıktığımızda ayarlar aşağıdaki gibi .config dosyasını yazılmaktadır.

scripts/kconfig/mconf  Kconfigconfiguration written to .config

Dilersek .config dosyasını açarak helloworld modül entry’sini aşağıdaki gibi görebiliriz.

cat .config
...
...
...
#
# helloworldmodule#CONFIG_CUSTOM_HELLOWORLD=m

Kconfig ve Makefile dosyalarımızı hazır hale geldiği için artık Linux’un in-tree modüllerini aşağıdaki komutla derleyebiliriz.

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules -j4

Bu komuttan sonra /drivers/char/helloworld/ klasörümüz altında out-of-tree kernel modül derlemede elde ettiğimiz tüm dosyalar aynı şekilde bu klasör altında da oluşacaktır ancak bu sefer farkı out-of-tree değil menuconfig üzerinden kernel derleme sırasında konfigürasyonunu yapabileceğimiz ve kernel source tree içinde yer alan bir in-tree kernel modülü olmasıdır. in-tree kernel modül doğrulamasını yine daha önceden belirttiğim modinfo komutu ile kontrol edilebilmektedir. Loglardan da görüldüğü gibi intree parametresi “Yes” olarak gözükmektedir.

modinfo helloworld.ko
filename: /home/serbay/Desktop/BeagleBone_Linux_Kernel_4.14/linux/drivers/char/helloworld/helloworld.ko
board: BeagleBoneBlack LKM
description: Hello World Kernel Module
author: Serbay Ozkan
license: GPL
depends:
intree: Y
name: helloworld
vermagic: 4.14.108+ SMP preempt mod_unload modversions ARMv7 p2v8

Testini de yine out-of-tree kernel modüllerinde yaptığımız şekilde yapabilmemiz mümkündür. Bunun için helloworld.ko dosyasını scp ile BBB’ye atıyoruz ve daha sonrasında insmod/rmmod kullanarak kernel loglarını kontrol ediyoruz.

sudo insmod main.kosudo rmmod main.kodmesg. . .. . .[ 2356.285830] Hello World LKM Initilization...
[ 2362.467186] Hello World LKM Cleanup...

Böylelikle yazı boyunca helloworld.c kernel modülü kaynak dosyasını hem host için hem de target için başarılı bir şekilde derleyerek out-of-tree ve in-tree kernel modülü yarattık ve bunu host ve target linux kernel’ine sırayla ekleyerek ve çıkararak bir test gerçekleştirmiş olduk.

Diğer yazılarımda görüşmek üzere…

Referanslar ve Faydalı Kaynaklar

--

--