Linux Kernel Proc File System Üzerinde Dört İşlem
/ Proc dosya sistemi aslında bir sistemdeki işlemler(proccess) hakkında bilgi vermek için geliştirilmiş bir dosya sistemidir. Fakat dosya sisteminin kullanışlılığı göz önüne alındığında, kernel çekirdeğinin birçok elemanı hem bilgiyi rapor etmek hem de dinamik çalışma zamanı yapılandırmasını sağlamak için kullanılıyor.
/ Proc dosya sistemi alt klasörleri ve sanal dosyalar içerir. Sanal bir dosya kernel çekirdeğiden kullanıcıya bilgi sunabilir ve aynı zamanda kullanıcıdan kernel çekirdeğe bilgi gönderme aracı olarak da hizmet edebilir.
/Proc dosya sistemin üzerinde read,write,open,show,mkdir,symlink vb işlemlerin yapılması mümkündür. Bu yazımızda sadece read ve write methodlarını kullanarak dörtişlem yapabilen bir modül yazacağız.
Kernel modül aracığı ile kişisel işlemlerimiz için /proc alt dosyaları oluşturabiliriz. Bu yazımızda(Tıklayınız) Kernel Modül programlama hakkında detaylı bilgiye ulabilirsiniz.
Modülümüzde aşağıdaki metholar ile /proc alt dosyalama yapısı oluşturabiliriz.
//Proc oluşturma fonksiyonu
# proc_create("string proc name", permissions, id,&File_Operations)
//Proc silme fonksiyonu
# remove_proc_entry(ProcName, id);
1: Kernel Modülünün Oluşturulması# cd /home/omansak/Downloads/linux-4.13.4
# cd ExternalModules
# mkdir ProcCalculator
# cd ProcCalculator
# gedit proc.c
2: C Modulünün YazılmasıC modulünü yazarken Calculate adın method tanımlayarak bizim için dört işlemi yapacak olan kodları yazacaz. Bu methodu ister /proc alt dosyasının Read methodunu çalışırken aktif edebiliriz ister Write methodu çalışırken aktif edebiliriz.İki yöntem arasında pek fark yoktur. Sadece user space üzerinde çağrılma farklıkları vardır.
// Kütüpnalerin Tanımlanması #include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/init.h> //Modul Hakkında bilgilerin tanımlanması MODULE_LICENSE("GPL"); MODULE_AUTHOR("NativeCore"); //Proc Name ve Proc Size tanımlanmaso #define ProcName "NativeCore" #define MaxSize 1024 //Alınacak girdinin max uzunluğunun tanımlanması #define MaxLenght 10 //Kullanılan Fonksiyonların tanımlanması static ssize_t ProcRead(struct file *filp,char *buf,size_t count,loff_t *offp ); static ssize_t ProcWrite(struct file *filp,const char *buf,size_t count,loff_t *offp); static void Calculate(char* values); static int Check(char c); //Proc Struct yapısının tanımlanması ve izin verilen fonksiyonların atanması static struct proc_dir_entry *ProcEntry; static const struct file_operations FileOperations = { .owner = THIS_MODULE, .read = ProcRead, .write = ProcWrite }; //Dosya yazma yada okuma esnasında aracı olarak kullanılan buffer tanımlanması static char ProcBuffer[MaxSize]; static unsigned long BufferSize; //init(başlangıç) methodunun tanımlanması static int onStart(void) { //Proc dosyasının oluşturulması ProcEntry = proc_create(ProcName, 0, NULL,&FileOperations); if (ProcEntry == NULL) { //Memory yetersizliği yada diğer durumlar için oluşacak hata sonunda proc silinmesi remove_proc_entry(ProcName, NULL); printk(KERN_ALERT "/proc/%s oluşturulamadı.\n", ProcName); return ENOMEM; } //Proc izinlerinin tanımlanması proc_set_user(ProcEntry,KUIDT_INIT(0),KGIDT_INIT(0)); proc_set_size(ProcEntry,37); printk(KERN_ALERT "/proc/%s başarı ile oluşturuldu.\n", ProcName); return 0; } //exit(kapanış) methodunun tanımlanması void onExit(void) { remove_proc_entry(ProcName, NULL); printk(KERN_ALERT "/proc/%s kaldırıldı\n", ProcName); } //Read methodunun tanımlanması static ssize_t ProcRead(struct file *filp,char *buf,size_t count,loff_t *offp ) { printk(KERN_ALERT "ProcRead çalıştırıldı \n"); //Kernel space'den user space'e verilen aktarılması if (copy_to_user(buf, ProcBuffer, BufferSize)) { printk(KERN_ALERT "ProcRead : Proc dosyası kopyalanmadı\n"); return -EFAULT; } //Calculate(ProcBuffer); return BufferSize; } static void Calculate(char* values) { //Dört işlem için kullanılacak değişkenlerin tanımlanması static char stringOne[10]; static char stringTwo[10]; static long numberOne; static long numberTwo; static char proccess; static int i = 0; static int j = 0; //+-*/ işaretlerinden birini görene kadar olan tüm karakterleri birinci sayı dizisine aktarılması while (Check(values[i]) == 0) { stringOne[j] = values[i]; j++; i++; } //+-*/ kulllanılacak işlemin atanaması proccess = values[i]; j = 0; i++; //+-*/ den sonraki tüm karakterleri ikinci sayı dizisine atanması while (i < BufferSize) { stringTwo[j] = values[i]; j++; i++; } //Karakter dizilerinin integer dönüştürülmesi if (kstrtol(stringOne, 10, &numberOne) != 0) { printk(KERN_ALERT "1.Sayı : Geçersiz Karakter\n"); return; } if (kstrtol(stringTwo, 10, &numberTwo) != 0) { printk(KERN_ALERT "2.Sayı : Geçersiz Karakter\n"); return; } //Yapılacak işleme göre methodun yapılması ve ekrane basılması static int result; switch (proccess) { case '+': result = numberOne + numberTwo; break; case '-': result = numberOne - numberTwo; break; case '*': result = numberOne * numberTwo; break; case '/': result = numberOne / numberTwo; break; default: printk(KERN_ALERT "Geçersiz Karakter Girildi\n"); break; } printk(KERN_ALERT "%d %c %d = %d\n", numberOne, proccess, numberTwo, result); } //+-*/ yardımcı karakter ayırt etme methodu static int Check(char c) { if (c == '+' || c == '-' || c == '*' || c == '/') return 1; else return 0; } //Write methodunun tanımlanması static ssize_t ProcWrite(struct file *filp,const char *buf,size_t count,loff_t *offp) { // Girilen verinin boyutu izin verilen boyutun üstende ise izin verilen boyuta çekilmesi printk(KERN_ALERT "ProcWrite çalıştırıldı\n"); BufferSize = count; if (BufferSize > MaxSize) { BufferSize = MaxSize; } if (copy_from_user(ProcBuffer, buf, BufferSize)) { printk(KERN_ALERT "ProcWrite : Proc dosyası kopyalanmadı\n"); return -EFAULT; } Calculate(ProcBuffer); return BufferSize; } module_init(onStart); module_exit(onExit);
obj-m = proc.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
4: Modülün derlenmesi ve aktif olması
# make
# insmod proc.ko (aktif etme)
# rmmod proc (inaktif etme)
5: Proc dosya sisteminin çağrılması
Öncellikle proc alt dizinine girilmesi gerekmektedir.
# cd ../proc
Modülümüzü aktif olmasından sonra /proc klasörünün içerisine verdiğimiz isme göre dosya oluşacaktır (/proc/NativeCore)Görüldüğü üzere dosyamız oluştu ve artık bu dosyaya veri yazabilir yada okuyabiliriz.
5: Proc dosya veri yazılması ya da okunması
Modül üzerinde ki Write methodu ile proc dosyasına veri yazmak için "echo" komutu kullanılır
#### Proc Dosyasına veri yazmak için ####
# echo "string veri" > ProcName
# echo "15+65" > NativeCore
# dmesg
Echo komutu kullandıktan sonra veriler proc dosyamıza yazılmış olacaktır.
Örnek Toplama İşlemi
Örnek Çarpma İşlemi
Bu örnekte Write Methodundan sonra hesaplama işlemlerini yaptık. Read Methodundan sonra hesaplama işlemlerini yapmak için
#### Proc Dosyasından veri okumak için ####
# cat ProcName
# echo "15+65" > NativeCore
# cat NativeCore
6: Modulden Çıkılması
#rmmod proc
Olası Hatalar ve Çözümleri
1: "Makefile:3: *** missing separator. Stop".
Makefile dosyanızda boşluk(Space) karakterleri olabilir,bu karakterler yerine TAB karakteri koymalısınız.
2: "make not found"
Bu hata Kernel Kaynak kodlarının bozulması sonucunda meydana gelir, güncel Kerneli indirip tekrar derlenip kurulması gerekir.
3"Bad Adrress" or "Is not proccess"
Bu hata genellikle Write Read methodları içinde veri okurken copy_to_user yada copy_from_user fonksiyonlarının karıştırılması sonucu oluşur
4:"Could not save file"
Bu hata Kernel Dosyalarını değiştirmek için yönetici izninizin olmadığını belirtir.
Yönetici şifrenizi oluşturmadıysanız
# sudo passwd root
Yönetici olarak terminalde işlem yapmak için
# su
C dosyasının derlerken alınan hatalar için komut satırı incelenmeli ve hataların ayıklanması gerekmektedir. En çok karşılaşan hatalar /proc dosyası için tanımlanan write/read methodlarının geri dönüş tipi yada parametlerin hatalı olmasından kaynaklamakdatır.
Linux Terminal Komutları
1: "cd" istenilen klasöre girilmesi
2: "ls" klasör içeriğinin görülmesi
3: "mkdir" klasör oluşturulması
4: "gedit" dosya açılması yada düzenlenmesi
5: "su" yönetici olarak girilmesi
6: "dmesg" kernel/debug mesajlarının görülmesi
7: "make" kernele ait komut olup derlenme işlemini yapar
8: "insmod" kernel modülünün aktif olması
9: "rmmod" kernel modülünün inaktif olması
10: "echo" veri yazılması
11: "cat" veri okunması
12: "lsmod" modüllerin listelenmesi
Grup Üyeleri
OSMAN ŞAKİR KAPAR (Takım Lideri)
Yorumlar
Yorum Gönder