Advertisement
sayefsakin

Chardev

Oct 6th, 2011
383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.94 KB | None | 0 0
  1. /*
  2.  * Course           :CSE-326 System Programming Lab
  3.  *
  4.  * Assignment No    :03
  5.  * Assignment Name  :Kernel Module Programming by creating a simple character device driver
  6.  * Module name      :sakin_dev.ko
  7.  * Devices          :sakin-0, sakin-1
  8.  * Plateform        :kernel 2.6.38.6 or later
  9.  * Compiling the module: make (By running Makefile)
  10.  * Create the necessary devices and insert the module by executing: ./sakin_load
  11.  * To remove the module and to delete the devices execute: ./sakin_unload
  12.  *
  13.  * Author           :Sayef Azad Sakin
  14.  * Roll             :1563
  15.  * Language         :c
  16.  */
  17.  
  18. #ifndef __KERNEL__
  19. #  define __KERNEL__
  20. #endif
  21. #ifndef MODULE
  22. #  define MODULE
  23. #endif
  24.  
  25. #include <linux/module.h>
  26. #include <linux/moduleparam.h>
  27. #include <linux/init.h>
  28. #include <linux/slab.h>     /* kmalloc() */
  29. #include <linux/kernel.h>       /* printk(), min() */
  30. #include <linux/fs.h>           /* everything... */
  31. #include <linux/proc_fs.h>
  32. #include <linux/errno.h>        /* error codes */
  33. #include <linux/types.h>        /* size_t */
  34. #include <linux/fcntl.h>        /* O_ACCMODE */
  35. #include <linux/wait.h>
  36. #include <linux/cdev.h>
  37. #include <asm/uaccess.h>        /* copy_*_user */
  38. #include <linux/semaphore.h>
  39. #include <asm/system.h>     /* cli(), *_flags */
  40. #include <linux/sched.h>
  41.  
  42. #define DEVICE_NAME "sakin_dev"
  43. #define MAJOR_NUMBER 249
  44. #define SAKIN_NR_DEVS 2
  45. #define MIN_MINOR_NUMBER 0
  46. #define MAX_MINOR_NUMBER 1
  47. #define DEVICE_COUNT 2
  48. #define BUFFER_SIZE 1024
  49. #define PDEBUG(fmt, args...) printk( KERN_DEBUG "sakin: " fmt, ## args)
  50.  
  51. MODULE_AUTHOR("Sayef Azad Sakin");
  52. MODULE_LICENSE("GPL");
  53. MODULE_DESCRIPTION("A simple character device driver.");
  54. MODULE_SUPPORTED_DEVICE(DEVICE_NAME);
  55.  
  56. char *buffer0, *end0, *buffer1, *end1;          /* begin of buf, end of buf */
  57. char *rp0, *wp0, *rp1, *wp1;                    /* where to read, where to write */
  58. struct sakin_dev {
  59.         wait_queue_head_t inq, outq;            /* read and write queues */
  60.         int buffersize;                                 /* used in pointer arithmetic */
  61.         int nreaders, nwriters;                     /* number of openings for r/w */
  62.         struct semaphore sem;                   /* mutual exclusion semaphore */
  63.         struct cdev cdev;                           /* Char device structure */
  64. };
  65.  
  66. dev_t sakin_devno;
  67. static struct sakin_dev *sakin_devices;
  68.  
  69. int sakin_init_module( void ) ;
  70. void sakin_cleanup_module( void );
  71. static int sakin_open( struct inode*, struct file* );
  72. static int sakin_release( struct inode*, struct file* );
  73. static ssize_t sakin_read( struct file*, char*, size_t, loff_t* );
  74. static int sakin_getwritespace(struct sakin_dev *dev, struct file *filp, const int c_minor);
  75. static int spacefree(struct sakin_dev *dev, const int c_minor);
  76. static ssize_t sakin_write( struct file*, const char*, size_t, loff_t* );
  77. //int sakin_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
  78.  
  79. /* Called when a process tries to open the device file */
  80. static int sakin_open( struct inode *inode, struct file *filp ) {
  81.    
  82.     struct sakin_dev *dev;
  83.  
  84.     dev = container_of(inode->i_cdev, struct sakin_dev, cdev);
  85.     filp->private_data = dev;
  86.  
  87.     if (down_interruptible(&dev->sem))
  88.         return -ERESTARTSYS;
  89.     if (!buffer0) {
  90.         // allocate the buffer
  91.         buffer0 = kmalloc(BUFFER_SIZE, GFP_KERNEL);
  92.         if (!buffer0) {
  93.             up(&dev->sem);
  94.             return -ENOMEM;
  95.         }
  96.         dev->buffersize = BUFFER_SIZE;
  97.         end0 = buffer0 + dev->buffersize;
  98.         rp0 = wp0 = buffer0; // rd and wr from the beginning
  99.     }
  100.     if (!buffer1) {
  101.         // allocate the buffer
  102.         buffer1 = kmalloc(BUFFER_SIZE, GFP_KERNEL);
  103.         if (!buffer1) {
  104.             up(&dev->sem);
  105.             return -ENOMEM;
  106.         }
  107.         dev->buffersize = BUFFER_SIZE;
  108.         end1 = buffer1 + dev->buffersize;
  109.         rp1 = wp1 = buffer1; // rd and wr from the beginning
  110.     }
  111.     dev->buffersize = BUFFER_SIZE;
  112.     /* use f_mode,not  f_flags: it's cleaner (fs/open.c tells why) */
  113.     if (filp->f_mode & FMODE_READ)
  114.         dev->nreaders++;
  115.     if (filp->f_mode & FMODE_WRITE){
  116.         if(dev->nwriters){
  117.             up(&dev->sem);
  118.             return -EACCES;
  119.         }
  120.         dev->nwriters++;
  121.     }
  122.     up(&dev->sem);
  123.  
  124.     return nonseekable_open(inode, filp);
  125. }
  126.  
  127.  
  128. /* Called when a process closes the device file. */
  129. static int sakin_release( struct inode *inode, struct file *filp ) {
  130.  
  131.     struct sakin_dev *dev = filp->private_data;
  132.     down(&dev->sem);
  133.     if (filp->f_mode & FMODE_READ)
  134.         dev->nreaders--;
  135.     if (filp->f_mode & FMODE_WRITE)
  136.         dev->nwriters--;
  137.     up(&dev->sem);
  138.     return 0;
  139. }
  140.  
  141.  
  142. /* Called when a process, which already opened the dev file, attempts to read from it. */
  143. static ssize_t sakin_read( struct file *filp, char *buf, size_t count, loff_t *f_pos ) {
  144.    
  145.     struct sakin_dev *dev = filp->private_data;
  146.     int c_minor = iminor(filp->f_dentry->d_inode);
  147.     if(c_minor==1){
  148.         if (down_interruptible(&dev->sem))
  149.             return -ERESTARTSYS;
  150.  
  151.         while (rp1 == wp1) { /* nothing to read */
  152.             up(&dev->sem); /* release the lock */
  153.             if (filp->f_flags & O_NONBLOCK)
  154.                 return -EAGAIN;
  155.             PDEBUG("\"%s\" reading: going to sleep %d in inq1\n", current->comm, c_minor);
  156.             PDEBUG("read p %p write p %p && read p %p write p %p in reading", rp0, wp0, rp1, wp1);
  157.             if (wait_event_interruptible(dev->inq, (rp1 != wp1)))
  158.                 return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  159.             /* otherwise loop, but first reacquire the lock */
  160.             PDEBUG("Wake up from inq1 having %d\n",c_minor);
  161.             if (down_interruptible(&dev->sem))
  162.                 return -ERESTARTSYS;
  163.         }
  164.         /* ok, data is there, return something */
  165.         if (wp1 > rp1)
  166.             count = min(count, (size_t)(wp1 - rp1));
  167.         else /* the write pointer has wrapped, return data up to dev->end */
  168.             count = min(count, (size_t)(end1 - rp1));
  169.         if (copy_to_user(buf, rp1, count)) {
  170.             up (&dev->sem);
  171.             return -EFAULT;
  172.         }
  173.         rp1 += count;
  174.         if (rp1 == end1)
  175.             rp1 = buffer1; /* wrapped */
  176.         up (&dev->sem);
  177.  
  178.         /* finally, awake any writers and return */
  179.         wake_up_interruptible(&sakin_devices[0].outq);
  180.         PDEBUG("\"%s\" did read %li bytes %d\n",current->comm, (long)count, c_minor);
  181.     }
  182.     else if(c_minor==0){
  183.         if (down_interruptible(&dev->sem))
  184.             return -ERESTARTSYS;
  185.  
  186.         while (rp0 == wp0) { /* nothing to read */
  187.             up(&dev->sem); /* release the lock */
  188.             if (filp->f_flags & O_NONBLOCK)
  189.                 return -EAGAIN;
  190.             PDEBUG("\"%s\" reading: going to sleep %d in inq0\n", current->comm, c_minor);
  191.             PDEBUG("read p %p write p %p && read p %p write p %p in reading", rp0, wp0, rp1, wp1);
  192.             if (wait_event_interruptible(dev->inq, (rp0 != wp0)))
  193.                 return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  194.             /* otherwise loop, but first reacquire the lock */
  195.             PDEBUG("Wake up from inq0 having %d\n",c_minor);
  196.             if (down_interruptible(&dev->sem))
  197.                 return -ERESTARTSYS;
  198.         }
  199.         /* ok, data is there, return something */
  200.         if (wp0 > rp0)
  201.             count = min(count, (size_t)(wp0 - rp0));
  202.         else /* the write pointer has wrapped, return data up to dev->end */
  203.             count = min(count, (size_t)(end0 - rp0));
  204.         if (copy_to_user(buf, rp0, count)) {
  205.             up (&dev->sem);
  206.             return -EFAULT;
  207.         }
  208.         rp0 += count;
  209.         if (rp0 == end0)
  210.             rp0 = buffer0; /* wrapped */
  211.         up (&dev->sem);
  212.  
  213.         /* finally, awake any writers and return */
  214.         wake_up_interruptible(&sakin_devices[1].outq);
  215.         PDEBUG("\"%s\" did read %li bytes %d\n",current->comm, (long)count, c_minor);
  216.     }
  217.     return count;
  218. }
  219.  
  220. /* Wait for space for writing; caller must hold device semaphore.  On
  221.  * error the semaphore will be released before returning. */
  222. static int sakin_getwritespace(struct sakin_dev *dev, struct file *filp, const int c_minor)
  223. {
  224.     while (spacefree(dev, c_minor) == 0) { /* full */
  225.         DEFINE_WAIT(wait);
  226.        
  227.         up(&dev->sem);
  228.         if (filp->f_flags & O_NONBLOCK)
  229.             return -EAGAIN;
  230.         PDEBUG("\"%s\" writing: going to sleep\n",current->comm);
  231.         prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
  232.         if (spacefree(dev, c_minor) == 0)
  233.             schedule();
  234.         finish_wait(&dev->outq, &wait);
  235.         if (signal_pending(current))
  236.             return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  237.         if (down_interruptible(&dev->sem))
  238.             return -ERESTARTSYS;
  239.     }
  240.     return 0;
  241. }  
  242.  
  243. /* How much space is free? */
  244. static int spacefree(struct sakin_dev *dev, const int c_minor)
  245. {
  246.     if(c_minor==0){
  247.         if (rp1 == wp1)
  248.             return dev->buffersize - 1;
  249.         return ((rp1 + dev->buffersize - wp1) % dev->buffersize) - 1;
  250.     }
  251.     if (rp0 == wp0)
  252.         return dev->buffersize - 1;
  253.     return ((rp0 + dev->buffersize - wp0) % dev->buffersize) - 1;
  254. }
  255.  
  256. static ssize_t sakin_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){
  257.     struct sakin_dev *dev = filp->private_data;
  258.     int c_minor = iminor(filp->f_dentry->d_inode);
  259.     int result;
  260.  
  261.     if (down_interruptible(&dev->sem))
  262.         return -ERESTARTSYS;
  263.  
  264.     /* Make sure there's space to write */
  265.     result = sakin_getwritespace(dev, filp, c_minor);
  266.     if (result)
  267.         return result; /* sakin_getwritespace called up(&dev->sem) */
  268.  
  269.     if(c_minor==0){
  270.         /* ok, space is there, accept something */
  271.         PDEBUG("Write is called in %d\n",c_minor);
  272.         PDEBUG("read p %p write p %p && read p %p write p %p\n", rp0,wp0, rp1, wp1);
  273.         count = min(count, (size_t)spacefree(dev, c_minor));
  274.         if (wp1 >= rp1)
  275.             count = min(count, (size_t)(end1 - wp1)); /* to end-of-buf */
  276.         else /* the write pointer has wrapped, fill up to rp-1 */
  277.             count = min(count, (size_t)(rp1 - wp1 - 1));
  278.         PDEBUG("Going to accept %li bytes to %p from %p\n", (long)count, wp1, buf);
  279.         if (copy_from_user(wp1, buf, count)) {
  280.             up (&dev->sem);
  281.             return -EFAULT;
  282.         }
  283.         wp1 += count;
  284.         if (wp1 == end1)
  285.             wp1 = buffer1; /* wrapped */
  286.         up(&dev->sem);
  287.  
  288.         /* finally, awake any reader */
  289.         PDEBUG("read p %p write p %p while writing", rp1, wp1);
  290.         PDEBUG("Wake up from inq1 has %d\n",c_minor);
  291.         wake_up_interruptible(&sakin_devices[1].inq);  /* blocked in read() and select() */
  292.  
  293.         /* and signal asynchronous readers, explained late in chapter 5 */
  294.         /*if (dev->async_queue)
  295.             kill_fasync(&dev->async_queue, SIGIO, POLL_IN);*/
  296.         PDEBUG("\"%s\" did write %li bytes %d\n",current->comm, (long)count, c_minor);
  297.     }
  298.     else if(c_minor==1){
  299.         /* ok, space is there, accept something */
  300.         PDEBUG("Write is called in %d\n",c_minor);
  301.         count = min(count, (size_t)spacefree(dev, c_minor));
  302.         if (wp0 >= rp0)
  303.             count = min(count, (size_t)(end0 - wp0)); /* to end-of-buf */
  304.         else /* the write pointer has wrapped, fill up to rp-1 */
  305.             count = min(count, (size_t)(rp0 - wp0 - 1));
  306.         PDEBUG("Going to accept %li bytes to %p from %p\n", (long)count, wp0, buf);
  307.         if (copy_from_user(wp0, buf, count)) {
  308.             up (&dev->sem);
  309.             return -EFAULT;
  310.         }
  311.         wp0 += count;
  312.         if (wp0 == end0)
  313.             wp0 = buffer0; /* wrapped */
  314.         up(&dev->sem);
  315.  
  316.         /* finally, awake any reader */
  317.         PDEBUG("Wake up from inq0 has %d\n",c_minor);
  318.         PDEBUG("read p %p write p %p while writing", rp0, wp0);
  319.         wake_up_interruptible(&sakin_devices[0].inq);  /* blocked in read() and select() */
  320.  
  321.         /* and signal asynchronous readers, explained late in chapter 5 */
  322.         /*if (dev->async_queue)
  323.             kill_fasync(&dev->async_queue, SIGIO, POLL_IN);*/
  324.         PDEBUG("\"%s\" did write %li bytes %d\n",current->comm, (long)count, c_minor);
  325.     }
  326.     return count;
  327. }
  328.  
  329. static struct file_operations sakin_fops = {
  330.     .owner   = THIS_MODULE,
  331.     .read    = sakin_read,
  332.     .write   = sakin_write,
  333.     .open    = sakin_open,
  334.     .release = sakin_release,
  335.     //.ioctl   = sakin_ioctl
  336. };
  337.  
  338. static void sakin_setup_cdev(struct sakin_dev *dev, int index){
  339.     int err, devno = sakin_devno + index;
  340.     cdev_init(&dev->cdev, &sakin_fops);
  341.     dev->cdev.owner = THIS_MODULE;
  342.     dev->cdev.ops = &sakin_fops;
  343.     err = cdev_add (&dev->cdev, devno, 1);
  344.     if (err)
  345.         printk(KERN_NOTICE "Error %d adding sakin_dev %d", err, index);
  346. }
  347.  
  348. int sakin_init_module( void ) {/* called when module is loaded */
  349.     int result, i;
  350.     dev_t dev = 0;
  351.     dev = MKDEV(MAJOR_NUMBER, MIN_MINOR_NUMBER);
  352.     result = register_chrdev_region(dev, SAKIN_NR_DEVS, DEVICE_NAME);
  353.     printk(KERN_INFO "sakin: Hello, I am here in the kernel (Module loaded)\n");
  354.     if (result < 0) {
  355.         printk(KERN_NOTICE "Unable to get sakin_dev region, error %d\n", result);
  356.         return 0;
  357.     }
  358.     sakin_devno = dev;
  359.     sakin_devices = kmalloc(SAKIN_NR_DEVS * sizeof(struct sakin_dev), GFP_KERNEL);
  360.     if (sakin_devices == NULL) {
  361.         unregister_chrdev_region(dev, SAKIN_NR_DEVS);
  362.         return 0;
  363.     }
  364.     memset(sakin_devices, 0, SAKIN_NR_DEVS * sizeof(struct sakin_dev));
  365.     for (i = 0; i < SAKIN_NR_DEVS; i++) {
  366.         init_waitqueue_head(&(sakin_devices[i].inq));
  367.         init_waitqueue_head(&(sakin_devices[i].outq));
  368.         //init_MUTEX(&sakin_devices[i].sem);
  369.         //init_MUTEX(&sakin_devices[i].sem);
  370.         sema_init(&sakin_devices[i].sem,1);     //for kernel 2.6.38.6
  371.         sakin_setup_cdev(sakin_devices + i, i);
  372.     }
  373.     return 0;
  374. }
  375.  
  376. void sakin_cleanup_module( void ) {/* Called when module is unloaded */
  377.     int i;
  378.     if (!sakin_devices)
  379.         return; /* nothing else to release */
  380.  
  381.     for (i = 0; i < SAKIN_NR_DEVS; i++) {
  382.         cdev_del(&sakin_devices[i].cdev);
  383.     }
  384.     kfree(buffer0);
  385.     kfree(buffer1);
  386.     kfree(sakin_devices);
  387.     unregister_chrdev_region(sakin_devno, SAKIN_NR_DEVS);
  388.     sakin_devices = NULL; /* pedantic */
  389.     printk(KERN_INFO "sakin: Goodbye (Module unloaded).\n");
  390. }
  391.  
  392. module_init( sakin_init_module );
  393. module_exit( sakin_cleanup_module );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement