Sunday 18 May 2014

Memory allocation using kmalloc in character driver in linux

#include <linux/module.h>
#include <linux/fs.h>  //various structures(fops)
#include <linux/major.h>
#include <linux/capability.h>
#include <asm/uaccess.h> //copy_to/from_user()
#include <linux/cdev.h>  //cdev
#include <linux/sched.h> //Task states (TASK_INTERRUPTIBLE etc)
#include <linux/slab.h>  //kmalloc/kfree

char *ptr;
#define BUF_SIZE PAGE_SIZE

static ssize_t sample_char_read(struct file * file, char __user * buf,
                       size_t count, loff_t *ppos)
{
 int err;

 printk("sample_char_read size(%ld)\n", count);
 err = copy_to_user((void *) buf, file->private_data, count);
 if (err)
  err = -EFAULT;

 return count;
}

static ssize_t sample_char_write(struct file *file, const char *buf,
                 size_t size, loff_t *offp)
{
 printk("sample_char_write size(%ld)\n", size);

 copy_from_user( (void *)file->private_data , buf, size);
 printk("in private =%s",file->private_data);
 return size;

}

int sample_char_open(struct inode *inode, struct file *filp)
{

 printk("sample_char_open\n");
 filp->private_data = ptr;
 return 0;
}

int sample_char_release(struct inode *inode, struct file *filp)
{
        kfree (ptr);
        printk("sample_char_release\n");
       return 0;
}

static struct file_operations sample_char_fops = {
       read:          sample_char_read,
       write:          sample_char_write,
       open:          sample_char_open,
       release:        sample_char_release,
};

#define sample_major_number 249
#define max_minors 1

static struct cdev char_cdev;
static dev_t dev;

int init_module(void)
{
 int ret = 0;

 dev = MKDEV(sample_major_number, 0);
 printk("\nLoading the sample char device driver\n");

 ret = register_chrdev_region(dev, max_minors, "sample_char");
 if (ret)
 {
  printk("register_chrdev_region Error\n");
  goto error;
 }
 cdev_init(&char_cdev, &sample_char_fops);
 ret = cdev_add(&char_cdev, dev, max_minors);
 if (ret) {
  printk("cdev_add Error\n");
  goto error_region;
 }

 ptr = kmalloc(BUF_SIZE, GFP_KERNEL);
 if (!ptr) {
  pr_info("unable to get memory block\n");
  ret = -ENOMEM;
  goto error_region;
 }
 memset (ptr, 0, BUF_SIZE);

 return 0;

 error_region:
  unregister_chrdev_region(dev, max_minors);
 error:
         return ret;
}

void cleanup_module(void)
{
  cdev_del(&char_cdev);
  unregister_chrdev_region(dev, max_minors);
         printk("\nUnloading the sample char device driver\n");

}

No comments:

Post a Comment