Linux Dört İşlem Yapan Proc Uygulaması

Proc Dosya Sistemi Nedir ?


     /proc bir sanal dosya sistemi olduğu için çok özeldir. İşlem bilgisi psüdo-dosya sistemi olarak da anılır. 'Gerçek' dosyalar bulundurmaz fakat sistem bilgisi (örn. sistem hafızası, bağlı cihazlar, donanım konfigürasyonu, vs.) bulundurur. Bu sebepten dolayı çekirdek için bir kontrol ve bilgi merkezi olarak düşünülebilir. Aslında, bir çok sistem bu dizindeki dosyalara çağrı yapar. Örneğin; 'lspci' komutu 'cat/proc/pci' komutunun eş anlamlısıyken, 'lsmod' komutu 'cat/proc/modules' ile aynıdır. Bu dizindeki dosyaları düzenleyerek sistem çalıştığı anda çekirdeğin parametereleri okunup düzenlenebilir.
     Bu dizindeki dosyaların en ayırt edici özelliği, hepsinin dosya boyutunun 0 olmasıdır(kcore, mtrr ve self hariç.)

Ilk once odev_grup adinda bir klasor olusturduk.Daha sonra icerisinde bir C dosyasi olusturarak asagidaki kod bloklarini yazdik.

/*
 * calculator.c - /proc dizini içerisine yalnızca dört işlem gerçekleştirebilen bir
 * proc dosyası yaratan program
 * */

#include <linux/kernel.h> /* kernel'da işlem yapacağız */
#include <linux/module.h> /* Özellikle, bir modül */
#include <linux/proc_fs.h> /* proc fs kullanacağımız için gerekli  */
#include <linux/uaccess.h> /* copy _*_user için */
#include <linux/string.h>

#define PROCFS_NAME "calculator"
#define PROCFS_MAX_SIZE 2048

static char procfs_buffer[PROCFS_MAX_SIZE]; /* bufferın karakterleri depoladığı yer */
static unsigned long procfs_buffer_size = 0; /* buffer'ın içinde tutalacak verinin boyutu */
static struct proc_dir_entry *Our_Proc_File; /* Bu struct /proc dosyası ile ilgili bilgi tutar */
static int n1;
static int n2;
static int result;

static ssize_t procfs_read(struct file *filp, /* include/linux/fs.h */
char *buffer, /* data ile doldurmak için */
size_t length, /* buffer'ın uzunluğu */
loff_t *offset) /* read fonksiyonumuz */
{
static int finished = 0;

/* Dosyanın sonuna daha fazla bilgi yazmayacağımızı belirtmek için
* return 0 yazıyoruz. Yoksa, proces'ler sonsuz bir dögü içerisinde
* bizden bilgi okumaya devam edecek.
*/

if( finished ){
printk(KERN_INFO "procfs_read fonksiyonu okumayi bitirdi.\n");
finished = 0;
return 0;
}

finished = 1;

/*
* put_to_user'ı string'i kernel'ın hafıza bölümünden çağrılan process'in
* hafıza bölümüne kopyalamak için kullanıyoruz.
*/

if( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
return -EFAULT; /* Bad adress */
}

printk(KERN_INFO "procfs_read fonksiyonu %lu bytes okudu.\n", procfs_buffer_size);

return procfs_buffer_size; /* "read" bytes bilgisini döndürür */
}

static ssize_t procfs_write(struct file *file, const char *buffer, size_t len, loff_t *off)
{
char *msg;
char *num1;
char *num2;
char *ch;
char opr;

if( len > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
else {
procfs_buffer_size = len;
}

msg = procfs_buffer; /* diziyi msg pointer değişkenine atıyoruz */

if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return -EFAULT; /* Bad adress */
}

num1 = strsep( &msg," "); /* strsep fonksiyonu ile  boşluk karekterini
görene kadar olan değerleri aldık. burada ilk değerimiz alıyoruz */
ch = strsep( &msg," "); /* burada ikinci değerimizi alıyoruz yani ortaki operand
değişkenini alıyoruz. */
num2 = strsep( &msg," "); /* burada sondeğeri aldık */

sscanf(num1, "%d", &n1); /* num1 e gelen değeri integer tipine çevirerek n1
değişkenine attık */
sscanf(ch, "%s", &opr); /* ch pointer değişkenine gelen değeri string  tipine çevirerek opr değişkenine attık  */
sscanf(num2, "%d", &n2); /* num2 e gelen değeri integer tipine çevirerek n2 değişkenine attık  */

if( opr == '+' ){ /* opr değerlerimizin kontolü */
result = n1 + n2;
}
else if( opr == '-' ){
result = n1 - n2;
}
else if( opr == '/' ){
result = n1 / n2;
}
else if( opr == '*' ){
result = n1 * n2;
}

printk(KERN_INFO "Sonuc --> %s %s %s = %d\n",num1, ch, num2, result);

printk(KERN_INFO "procfs_write fonksiyonu %lu bytes yazdi.\n", procfs_buffer_size);
return procfs_buffer_size;
}

int procfs_open(struct inode *inode, struct file *file){
try_module_get(THIS_MODULE); /*  user katmanından veriyi almak için kullanılır */
return 0; /* success */
}

int procfs_close(struct inode *inode, struct file *file){
module_put(THIS_MODULE); /* kernel katmanından->user katmanına geri yüklemek için kullanılır */
return 0; /* success */
}

static struct file_operations File_Ops_4_Our_Proc_File = {
.read = procfs_read,
.write = procfs_write,
.open = procfs_open,
.release = procfs_close,
};

/*
 * Module initialization and cleanup
 */

int init_calculator(void)
{
/* /proc file dosyası yaratma */
Our_Proc_File = proc_create(PROCFS_NAME, 0644, NULL, &File_Ops_4_Our_Proc_File);

/* /proc dosyasının başarılı bir şekilde yaratıldığını kontro etme */
if(Our_Proc_File == NULL){
printk(KERN_INFO "Hata: /proc/%s yaratilamadi.\n", PROCFS_NAME);
return -ENOMEM; /* Out of memory */
}

printk(KERN_INFO "/proc/%s yaratildi.\n", PROCFS_NAME);

return 0; /* success */
}

void cleanup_calculator(void)
{
remove_proc_entry(PROCFS_NAME, NULL);
printk(KERN_INFO "/proc/%s kaldirildi.\n", PROCFS_NAME);
}

module_init(init_calculator);
module_exit(cleanup_calculator);

Bu C dosyasini derleyebilmek icin Makefile dosyasi olusturarak asagidaki kod parcacigini yaziyoruz.


Artik terminalde make komutuyla C dosyamizi derleyebiliriz.
Derleme isleminden sonra modulu kernele yuklemek icin insmod calculator.ko komutunu calistiriyoruz.
Modulu yukledikten sonra proc dosyamizin /proc dizininde yaratildigini gorebiliriz.
cd /proc komutuyla proc dizinine gidip proc dosyamiza echo 53 + 46 > /proc/calculator komutuyla islemimizi yaziyoruz.
Sonucumuzun loga dustugunu gorebilmek icin dmesg  komutunu calistiriyoruz.
Islemimizi tamamladiktan sonra modulu kernelden kaldirmak icin rmmod calculator.ko komutunu calistiriyoruz.
dmesg komutuyla loglara baktigimizda modulun kaldirildigi mesajini gorebiliriz.
     
      Grup Üyeleri:



Yorumlar

Bu blogdaki popüler yayınlar

Kernel Modülü Programlama

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ı