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.
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:
- Abdülkadir Azmanoğlu (Grup Reisi)
- İbrahim Demir
- İlyas Gülen
- Gökhan Terzioğlu
- Mustafa Temur
- Mehmet Sıraç Demir
Yorumlar
Yorum Gönder