Linux Device Driver-globalfifo character devices support blocking and polling

Source: Internet
Author: User

Development Environment:WINXP (host) + visualbox + fedora9 (Virtual Machine 2.6.25.4 kernel)

Function:The globalmem character device framework analysis (supports two devices) allows for dynamic creation of device files and supports blocking and non-blocking and polling drivers of devices.

 
 
#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/poll.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#define DEVICE_NAME  "globalfifo"#define GLOBALFIFO_SIZE 20//global mem size#define GLOBALFIFO_MAJOR 240//major number#define MEM_CLEAR 0x1 //clear global memstatic int globalfifo_major=GLOBALFIFO_MAJOR;static struct class *globalfifo_class;struct globalfifo_dev{struct cdev cdev;unsigned int current_len;unsigned char mem[GLOBALFIFO_SIZE];struct semaphore sem;wait_queue_head_t r_wait;wait_queue_head_t w_wait;};struct globalfifo_dev *globalfifo_devp;static int globalfifo_open(struct inode *inode,struct file *filp){filp->private_data=globalfifo_devp;return 0;}static int globalfifo_release(struct inode *inode,struct file *filp){return 0;}//lun xun operationstatic unsigned int globalfifo_poll(struct file *filp,poll_table *wait){unsigned int mask=0;struct globalfifo_dev *dev=filp->private_data;down(&dev->sem);poll_wait(filp,&dev->r_wait,wait);poll_wait(filp,&dev->w_wait,wait);if(dev->current_len!=0)mask|=POLLIN|POLLRDNORM;if(dev->current_len!=GLOBALFIFO_SIZE)mask|=POLLOUT|POLLWRNORM;up(&dev->sem);return mask;}static ssize_t globalfifo_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos){int ret=0;struct globalfifo_dev *dev=filp->private_data;DECLARE_WAITQUEUE(wait,current);down(&dev->sem);add_wait_queue(&dev->r_wait,&wait);while(dev->current_len==0){if(filp->f_flags&O_NONBLOCK){return ret= -EAGAIN;goto out;}__set_current_state(TASK_INTERRUPTIBLE);up(&dev->sem);schedule();if(signal_pending(current)){ret=-ERESTARTSYS;goto out2;}down(&dev->sem);}if(count>dev->current_len)count=dev->current_len;if(copy_to_user(buf,dev->mem,count)){ret= -EFAULT;goto out;}else{memcpy(dev->mem,dev->mem+count,dev->current_len-count);dev->current_len-=count;printk(KERN_INFO "read %d bytes(s) current_len %d\n",count,dev->current_len);wake_up_interruptible(&dev->w_wait);ret=count;}out:up(&dev->sem);out2:remove_wait_queue(&dev->r_wait,&wait);set_current_state(TASK_RUNNING);return ret;}static ssize_t globalfifo_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos){int ret=0;struct globalfifo_dev *dev=filp->private_data;DECLARE_WAITQUEUE(wait,current);down(&dev->sem);add_wait_queue(&dev->w_wait,&wait);while(dev->current_len==GLOBALFIFO_SIZE){if(filp->f_flags&O_NONBLOCK){return ret= -EAGAIN;goto out;}__set_current_state(TASK_INTERRUPTIBLE);up(&dev->sem);schedule();if(signal_pending(current)){ret=-ERESTARTSYS;goto out2;}down(&dev->sem);}if(count>GLOBALFIFO_SIZE-dev->current_len)count=GLOBALFIFO_SIZE-dev->current_len;if(copy_from_user(dev->mem+dev->current_len,buf,count)){ret= -EFAULT;goto out;}else{dev->current_len+=count;printk(KERN_INFO "write %d bytes(s) current_len %d\n",count,dev->current_len);wake_up_interruptible(&dev->r_wait);ret=count;}out:up(&dev->sem);out2:remove_wait_queue(&dev->w_wait,&wait);set_current_state(TASK_RUNNING);return ret;}static loff_t globalfifo_llseek(struct file *filp,loff_t offset,int orig){loff_t ret;switch(orig){case 0:if(offset<0){ret=-EINVAL;break;}if(offset>GLOBALFIFO_SIZE){ret=-EINVAL;break;}filp->f_pos=(unsigned int)offset;ret=filp->f_pos;break;case 1:if((filp->f_pos+offset)>GLOBALFIFO_SIZE){ret=-EINVAL;break;}if((filp->f_pos+offset)<0){ret=-EINVAL;break;}filp->f_pos+=offset;ret=filp->f_pos;break;default:ret=-EINVAL;}return ret;}static int globalfifo_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg){struct globalfifo_dev *dev=filp->private_data;switch(cmd){case MEM_CLEAR:memset(dev->mem,0,GLOBALFIFO_SIZE);printk(KERN_INFO "globalfifo is set to zero\n");break;default:return -EINVAL;}return 0;}static const struct file_operations globalfifo_fops={.owner=THIS_MODULE,.llseek=globalfifo_llseek,.read=globalfifo_read,.write=globalfifo_write,.ioctl=globalfifo_ioctl,.open=globalfifo_open,.release=globalfifo_release,.poll=globalfifo_poll,};static void globalfifo_setup_cdev(struct globalfifo_dev *dev,int index){int err,devno=MKDEV(globalfifo_major,index);cdev_init(&dev->cdev,&globalfifo_fops);dev->cdev.owner=THIS_MODULE;err=cdev_add(&dev->cdev,devno,1);if(err)printk(KERN_NOTICE "ERROR %d adding globalfifo %d",err,index);}int globalfifo_init(void){int result;dev_t devno=MKDEV(globalfifo_major,0);if(globalfifo_major)result=register_chrdev_region(devno,1,"globalfifo");else{result=alloc_chrdev_region(&devno,0,1,"globalfifo");globalfifo_major=MAJOR(devno);}globalfifo_devp=kmalloc(sizeof(struct globalfifo_dev),GFP_KERNEL);if(!globalfifo_devp){result=-ENOMEM;goto fail_malloc;}if(result<0)return result;memset(globalfifo_devp,0,sizeof(struct globalfifo_dev));globalfifo_setup_cdev(globalfifo_devp,0);init_MUTEX(&globalfifo_devp->sem);init_waitqueue_head(&globalfifo_devp->r_wait);init_waitqueue_head(&globalfifo_devp->w_wait);globalfifo_class=class_create(THIS_MODULE,DEVICE_NAME);if(IS_ERR(globalfifo_class))     { printk(KERN_INFO " create class faild!\n"); return -1;    } class_device_create(globalfifo_class, NULL, MKDEV(globalfifo_major, 0),NULL,DEVICE_NAME); return 0;fail_malloc:unregister_chrdev_region(devno,1);return result;}void globalfifo_exit(void){cdev_del(&globalfifo_devp->cdev);kfree(globalfifo_devp);unregister_chrdev_region(MKDEV(globalfifo_major,0),1);class_device_destroy(globalfifo_class, MKDEV(globalfifo_major, 0));     class_destroy(globalfifo_class); }module_param(globalfifo_major,int,S_IRUGO);module_init(globalfifo_init);module_exit(globalfifo_exit);MODULE_LICENSE("GPL");
Test procedure:
#include <stdio.h>#include <stdlib.h>#include <time.h>#include <unistd.h>#include<linux/fcntl.h>#define FIFO_CLEAR 0x1#define BUFFER_LEN 20 int main(){int fd,num;char rd_ch[BUFFER_LEN];fd_set rfds,wfds;fd=open("/dev/globalfifo",O_RDONLY | O_NONBLOCK);if(fd!=-1){if(ioctl(fd,FIFO_CLEAR,0)<0)printf("ioctl command failed\n");while(1){FD_ZERO(&rfds);FD_ZERO(&wfds);FD_SET(fd,&rfds);FD_SET(fd,&wfds);select(fd+1,&rfds,&wfds,NULL,NULL);if(FD_ISSET(fd,&rfds))printf("Poll monitor:can be read\n");if(FD_ISSET(fd,&wfds))printf("Poll monitor:can be writen\n");}}else{printf("Device open failure\n");} } 


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.