[Linux Device Driver (Third edition)] -- high-speed cache

Source: Internet
Author: User
Document directory
  • Helloworld. c
  • Makefile
  • Create a device Node
  • Load
  • Test
  • Uninstall
[Linux Device Driver (Third edition)] ---- high-speed cache helloworld. c
#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/fs.h>//file_operations, file#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/aio.h>#include <linux/cdev.h>//cdev#include <asm/uaccess.h>//copy_to_user & copy_from_user#include <linux/proc_fs.h>//proc#include <linux/ioctl.h>//ioctlMODULE_LICENSE("Dual BSD/GPL");#define SCULL_QUANTUM 4000#define SCULL_QSET 1000#define SCULL_IOC_MAGIC 'k'#define SCULL_IOC_MAXNR 14#define SCULL_IOCRESET_IO(SCULL_IOC_MAGIC, 0)#define SCULL_IOCSQUANTUM_IOW(SCULL_IOC_MAGIC, 1, int)#define SCULL_IOCSQSET_IOW(SCULL_IOC_MAGIC, 2, int)#define SCULL_IOCTQUANTUM_IO(SCULL_IOC_MAGIC, 3)#define SCULL_IOCTQSET_IO(SCULL_IOC_MAGIC, 4)#define SCULL_IOCGQUANTUM_IOR(SCULL_IOC_MAGIC, 5, int)#define SCULL_IOCGQSET_IOR(SCULL_IOC_MAGIC, 6, int)#define SCULL_IOCQQUANTUM_IO(SCULL_IOC_MAGIC, 7)#define SCULL_IOCQQSET_IO(SCULL_IOC_MAGIC, 8)#define SCULL_IOCXQUANTUM_IOWR(SCULL_IOC_MAGIC, 9, int)#define SCULL_IOCXQSET_IOWR(SCULL_IOC_MAGIC, 10, int)#define SCULL_QUANTUM_IO(SCULL_IOC_MAGIC, 11)#define SCULL_IOCHQSET _IO(SCULL_IOC_MAGIC, 12)int scull_major = 250;int scull_minor = 0;int scull_nr_devs = 4;int scull_quantum = 4000;int scull_qset = 1000;module_param(scull_major, int, S_IRUGO);module_param(scull_minor, int, S_IRUGO);module_param(scull_nr_devs, int, S_IRUGO);module_param(scull_quantum, int, S_IRUGO);module_param(scull_qset, int, S_IRUGO);struct kmem_cache *scullc_cache;struct scull_qset {void **data;struct scull_qset *next;};struct scull_dev{struct scull_qset *data;int quantum;int qset;unsigned long size;unsigned int access_key;struct semaphore sem;struct cdev cdev;};struct scull_dev *scull_devices;int scull_read_procmem(char *buf, char **start, off_t offset, int count, int *eof, void *data){int len = 0;len += sprintf(buf + len, "Proc Test!\n");eof = -1;return len;}static void scull_create_proc(void){create_proc_read_entry("scullmem", 0, NULL, scull_read_procmem, NULL);}static void scull_remove_proc(void){remove_proc_entry("scullmem", NULL);}int scull_trim(struct scull_dev *dev){struct scull_qset *next, *dptr;int qset = dev->qset;int i;for(dptr = dev->data; dptr; dptr = next){if(dptr->data){for(i = 0; i < qset; i++)if(dptr->data[i])kmem_cache_free(scullc_cache, dptr->data[i]);kfree(dptr->data);dptr->data = NULL;}next = dptr->next;if(dptr != dev)kfree(dptr);}dev->size = 0;dev->quantum = scull_quantum;dev->qset = scull_qset;dev->data = NULL;return 0;}int scull_open(struct inode *inode, struct file *filp){struct scull_dev *dev;dev = container_of(inode->i_cdev, struct scull_dev, cdev);filp->private_data = dev;if(filp->f_flags & O_ACCMODE == O_WRONLY){scull_trim(dev);}return 0;}int scull_release(struct inode *inode, struct file *filp){return 0;}struct scull_qset *scull_follow(struct scull_dev *dev, int n){struct scull_qset *qs = dev->data;if(!qs){qs = dev->data = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);if(qs == NULL)return NULL;memset(qs, 0, sizeof(struct scull_qset));}while(n--){if(!qs->next){qs->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);if(qs->next == NULL)return NULL;memset(qs->next, 0, sizeof(struct scull_qset));}qs = qs->next;continue;}return qs;}ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){printk(KERN_NOTICE "Enter scull_read\n");struct scull_dev *dev = filp->private_data;struct scull_qset *dptr;int quantum = dev->quantum;int qset = dev->qset;int itemsize = quantum * qset;int item, s_pos, q_pos, rest;ssize_t retval = 0;if(down_interruptible(&dev->sem))return -ERESTARTSYS;if(*f_pos >= dev->size)goto out;if(*f_pos + count > dev->size)count = dev->size - *f_pos;item = (long)*f_pos / itemsize;rest = (long)*f_pos % itemsize;s_pos = rest / quantum;q_pos = rest % quantum;dptr = scull_follow(dev, item);if(dptr == NULL || !dptr->data || !dptr->data[s_pos])goto out;if(count > quantum - q_pos)count = quantum - q_pos;if(copy_to_user(buf, dptr->data[s_pos] + q_pos, count)){retval = -EFAULT;goto out;}*f_pos += count;retval = count;out:up(&dev->sem);return retval;}ssize_t scull_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){printk(KERN_NOTICE "Enter scull_write\n");struct scull_dev *dev = filp->private_data;struct scull_qset *dptr;int quantum = dev->quantum;int qset = dev->qset;int itemsize = quantum * qset;int item, s_pos, q_pos, rest;ssize_t retval = -ENOMEM;if(down_interruptible(&dev->sem))return -ERESTARTSYS;item = (long)*f_pos / itemsize;rest = (long)*f_pos % itemsize;s_pos = rest / quantum;q_pos = rest % quantum;dptr = scull_follow(dev, item);if(dptr == NULL)goto out;if(!dptr->data){dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);if(!dptr->data)goto out;memset(dptr->data, 0, qset * sizeof(char *));}if(!dptr->data[s_pos]){//dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);dptr->data[s_pos] = kmem_cache_alloc(scullc_cache, GFP_KERNEL);if(!dptr->data[s_pos])goto out;memset(dptr->data[s_pos], 0, scull_quantum);}if(count > quantum - q_pos)count = quantum - q_pos;if(copy_from_user(dptr->data[s_pos] + q_pos, buf,  count)){retval = -EFAULT;goto out;}*f_pos += count;retval = count;if(dev->size < *f_pos)dev->size = *f_pos;out:up(&dev->sem);return retval;}int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){int err = 0, tmp;int retval = 0;if(_IOC_TYPE(cmd) != SCULL_IOC_MAGIC)return -ENOTTY;if(_IOC_NR(cmd) > SCULL_IOC_MAXNR)return -ENOTTY;if(_IOC_DIR(cmd) & _IOC_READ)err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));else if(_IOC_DIR(cmd) & _IOC_WRITE)err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));if(err)return -EFAULT;switch(cmd){case SCULL_IOCRESET:scull_quantum = SCULL_QUANTUM;scull_qset = SCULL_QSET;break;case SCULL_IOCSQUANTUM:retval = __get_user(scull_quantum, (int __user *)arg);break;case SCULL_IOCTQUANTUM:scull_quantum = arg;break;case SCULL_IOCGQUANTUM:retval = __put_user(scull_quantum, (int __user *)arg);break;case SCULL_IOCQQUANTUM:return scull_quantum;case SCULL_IOCXQUANTUM:tmp = scull_quantum;retval = __get_user(scull_quantum, (int __user *)arg);if(retval == 0)retval = __put_user(tmp, (int __user *)arg);break;case SCULL_QUANTUM:tmp = scull_quantum;scull_quantum = arg;return tmp;case SCULL_IOCSQSET:retval = __get_user(scull_qset, (int __user *)arg);break;case SCULL_IOCTQSET:scull_qset = arg;break;case SCULL_IOCGQSET:retval = __put_user(scull_qset, (int __user *)arg);break;case SCULL_IOCQQSET:return scull_qset;case SCULL_IOCXQSET:tmp = scull_qset;retval = __get_user(scull_qset, (int __user *)arg);if(retval == 0)retval = put_user(tmp, (int __user *)arg);break;case SCULL_IOCHQSET:tmp = scull_qset;scull_qset = arg;return tmp;}}struct file_operations scull_fops = {.owner = THIS_MODULE,.open = scull_open,.release = scull_release,.read = scull_read,.write = scull_write,.ioctl = scull_ioctl,};static void scull_setup_cdev(struct scull_dev *dev, int index){int err, devno = MKDEV(scull_major, scull_minor + index);cdev_init(&dev->cdev, &scull_fops);dev->cdev.owner = THIS_MODULE;err = cdev_add(&dev->cdev, devno, 1);if(err)printk(KERN_NOTICE "Error %d adding scull%d", err, index);}static void scull_cleanup_module(void){printk(KERN_ALERT "Goodbye,world!\n");int i;dev_t devno = MKDEV(scull_major, scull_minor);if(scull_devices){for(i = 0; i < scull_nr_devs; i++){scull_trim(scull_devices + i);cdev_del(&scull_devices[i].cdev);}kfree(scull_devices);}if(scullc_cache)kmem_cache_destroy(scullc_cache);unregister_chrdev_region(devno, scull_nr_devs);scull_remove_proc();}static int __init scull_init_module(void){printk(KERN_ALERT "Hello, World!\n");int result, i;dev_t dev = 0;if(scull_major){dev = MKDEV(scull_major, scull_minor);result = register_chrdev_region(dev, scull_nr_devs, "scull");}else{result = alloc_chrdev_region(&dev, scull_major, scull_nr_devs, "scull");scull_major = MAJOR(dev);}if(result < 0){printk(KERN_WARNING "scull:can't get major %d\n", scull_major);return result;}scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);if(!scull_devices){result = -ENOMEM;goto fail;}memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));for(i = 0; i < scull_nr_devs; i++){scull_devices[i].quantum = scull_quantum;scull_devices[i].qset = scull_qset;init_MUTEX(&scull_devices[i].sem);scull_setup_cdev(&scull_devices[i], i);}printk(KERN_ALERT "kmem_cache_create before!\n");scullc_cache = kmem_cache_create("scullc", scull_quantum,0, SLAB_HWCACHE_ALIGN, NULL);printk(KERN_ALERT "kmem_cache_create after!\n");if(!scullc_cache){scull_cleanup_module();return -ENOMEM;}scull_create_proc();return 0;fail:scull_cleanup_module();return result;}module_init(scull_init_module);module_exit(scull_cleanup_module);
Makefile
obj-m:= HelloWorld.omodules-objs:= HelloWorld.oKDIR:= /usr/src/linux-headers-2.6.31-14-generic/PWD:= $(shell pwd)default:make -C $(KDIR) M=$(PWD) modulesclean:rm -rf *.ko *.mod.c *.mod.o *.o *.markers *.symvers *.order
Create a device Node
mknod /dev/scull c 250 0
Load
insmod scull.ko
Test
echo "Test" > /dev/scullcat /dev/scull

Output:

Test
Uninstall
rmmod scull

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.