Implementation and test of the simplest character device driver in ldd3 Linux Device Driver

Source: Internet
Author: User
The source code is as follows:
#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/cdev.h>#include <asm/uaccess.h>//#include "scull.h"#define SCULL_MAJOR 0   /* dynamic major by default */#define SCULL_NR_DEVS 4    /* scull0 through scull3 */#define SCULL_P_NR_DEVS 4  /* scullpipe0 through scullpipe3 */#define SCULL_QUANTUM 4000#define SCULL_QSET    1000struct scull_qset {void **data;struct scull_qset *next;};struct scull_dev {struct scull_qset *data;  /* Pointer to first quantum set */int quantum;              /* the current quantum size */int qset;                 /* the current array size */unsigned long size;       /* amount of data stored here */unsigned int access_key;  /* used by sculluid and scullpriv */struct semaphore sem;     /* mutual exclusion semaphore     */struct cdev cdev;  /* Char device structure*/};intscull_major = SCULL_MAJOR;intscull_minor = 0;intscull_nr_devs = SCULL_NR_DEVS;intscull_quantum = SCULL_QUANTUM;intscull_qset = SCULL_QSET;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);MODULE_AUTHOR("BG2BKK");MODULE_LICENSE("Dual BSD/GPL");struct scull_dev *scull_devices;intscull_trim(struct scull_dev *dev){structscull_qset *next,*dptr;intqset = dev->qset;int i;for(dptr = dev->data; dptr;dptr = next){if(dptr->data){for (i=0;i<qset;i++)kfree(dptr->data[i]);kfree(dptr->data);dptr->data = NULL;}next = dptr->next;kfree(dptr);}dev->size= 0;dev->quantum= scull_quantum;dev->qset= scull_qset;dev->data= NULL;return 0;}intscull_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;}intscull_release(struct inode *inode,struct file *filp){printk(KERN_ALERT "scullrelease\n");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_tscull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){structscull_dev *dev = filp->private_data;structscull_qset *dptr;intquantum = dev->quantum, qset = dev->qset;intitemsize = quantum*qset;intitem,s_pos,q_pos,rest;ssize_tretval = 0;if(down_interruptible(&dev->sem))return -ERESTARTSYS;//printk("f_pos= %d\n",*f_pos);//printk("count= %d\n",count);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;}//printk("read scull: %d\n",count);*f_pos += count;retval = count;out:up(&dev->sem);return retval;}ssize_tscull_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){structscull_dev *dev = filp->private_data;structscull_qset *dptr;intquantum = dev->quantum,qset = dev->qset;intitemsize = quantum * qset;intitem,s_pos,q_pos,rest;ssize_tretval = -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);if(!dptr->data[s_pos])goto out;}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;}intscull_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){return 0;}loff_tscull_llseek(struct file *filp,loff_t off,int whence){struct scull_dev *dev = filp->private_data;loff_t newpos;switch(whence){case 0:newpos = off;break;case 1:newpos = filp->f_pos + off;break;case 2:newpos = dev->size + off;break;default:return -EINVAL;}if(newpos < 0) return -EINVAL;filp->f_pos = newpos;return newpos;}struct file_operations scull_fops = {.owner= THIS_MODULE,.llseek= scull_llseek,.read= scull_read,.write= scull_write,.ioctl= scull_ioctl,.open= scull_open,.release= scull_release,};void scull_cleanup_module(void){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);}#ifdefSCULL_DEBUG//scull_remove_proc();#endifunregister_chrdev_region(devno,scull_nr_devs);//scull_p_cleanup();//scull_access_cleanup();}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;dev->cdev.ops= &scull_fops;err = cdev_add(&dev->cdev, devno,1);if(err)printk(KERN_NOTICE "Error %d adding scull%d",err,index);}intscull_init_module(void){intresult,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_minor,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;}printk(KERN_ALERT "hello scullmajor %d\n minor %d\n",scull_major,scull_minor);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);}dev=MKDEV(scull_major,scull_minor+scull_nr_devs);//dev += scull_p_init(dev);//dev += scull_access_init(dev);#ifdefSCULL_DEBUGscull_create_proc();#endifreturn 0;fail:scull_cleanup_module();return result;}module_init(scull_init_module);module_exit(scull_cleanup_module)

The test code is as follows:

/************************************************************************* *fileName:    test.c *description: test the myscull.c *author:      Hzc *create time: 2007-04-20 *modify info: -*************************************************************************/#include <stdio.h>#include <fcntl.h>#include <sys/ioctl.h>#include <sys/types.h>/* device path */char path[] = "/dev/sculldev";int buf[40];int rbuf[40];int i;int t=1;int main(){int f = open(path, O_WRONLY);if (f == -1){printf("device open error!\n");return 1;}printf("Input a string to write device \n");//scanf("%s", buf);for(i=0;i<40;i++){buf[i]=i;write(f, buf+i,1 ); /* device wirte */}close(f);f= open(path,O_RDONLY);printf("Read the string from device...\n");if (f == -1){printf("device open error!\n");return 1;}for(i=0;i<40;i++){read(f, rbuf+i, 1); /* device wirte */}for(i=0;i<40;i++){printf("%d\t",rbuf[i]);if((i+1)%10 == 0) printf("\n");}close(f);}

The driver loading script is as follows:

#!/bin/shinsmod scull.komknod /dev/sculldev c 252 0

The driver uninstall script is as follows:

#!/bin/shrmmod scull.korm /dev/sculldev

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.