linux裝置驅動–globalfifo字元裝置支援阻塞和輪詢

來源:互聯網
上載者:User

開發環境:Winxp(主機)+ VisualBox +fedora9(虛擬機器2.6.25.4核心)

功能:   globalmem字元裝置架構分析(支援2個裝置),裝置檔案動態建立,支援裝置的阻塞與非阻塞和輪詢的驅動。



#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");
測試程式:
#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");} } 


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.