開發環境: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 <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#define GLOBALMEM_SIZE 0x1000//global mem size#define GLOBALMEM_MAJOR 238//major number#define MEM_CLEAR 0x1 //clear global memstatic int globalmem_major=GLOBALMEM_MAJOR;static struct class *globalmem_class;struct globalmem_dev{struct cdev cdev;unsigned char mem[GLOBALMEM_SIZE];};struct globalmem_dev *globalmem_devp;static int globalmem_open(struct inode *inode,struct file *filp){struct globalmem_dev *dev;dev=container_of(inode->i_cdev,struct globalmem_dev,cdev);filp->private_data=dev;return 0;}static int globalmem_release(struct inode *inode,struct file *filp){return 0;}static ssize_t globalmem_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos){unsigned long p=*ppos;int ret=0;struct globalmem_dev *dev=filp->private_data;if(p>GLOBALMEM_SIZE)return 0;if(count>GLOBALMEM_SIZE-p)count=GLOBALMEM_SIZE-p;if(copy_to_user(buf,(void*)(dev->mem+p),count))ret= -EFAULT;else{*ppos+=count;ret=count;printk(KERN_INFO "read %d bytes(s) from %d\n",count,p);}return ret;}static ssize_t globalmem_write(struct file *filp,const char __user *buf,size_t count,loff_t *ppos){unsigned long p=*ppos;int ret=0;struct globalmem_dev *dev=filp->private_data;if(p>GLOBALMEM_SIZE)return 0;if(count>GLOBALMEM_SIZE-p)count=GLOBALMEM_SIZE-p;if(copy_from_user(dev->mem+p,buf,count))ret=-EFAULT;else{*ppos+=count;ret=count;printk(KERN_INFO "written %d bytes(s) from %d\n",count,p);}return ret;}static loff_t globalmem_llseek(struct file *filp,loff_t offset,int orig){loff_t ret;switch(orig){case 0:if(offset<0){ret=-EINVAL;break;}if(offset>GLOBALMEM_SIZE){ret=-EINVAL;break;}filp->f_pos=(unsigned int)offset;ret=filp->f_pos;break;case 1:if((filp->f_pos+offset)>GLOBALMEM_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 globalmem_ioctl(struct inode *inodep,struct file *filp,unsigned int cmd,unsigned long arg){struct globalmem_dev *dev=filp->private_data;switch(cmd){case MEM_CLEAR:memset(dev->mem,0,GLOBALMEM_SIZE);printk(KERN_INFO "globalmem is set to zero\n");break;default:return -EINVAL;}return 0;}static const struct file_operations globalmem_fops={.owner=THIS_MODULE,.llseek=globalmem_llseek,.read=globalmem_read,.write=globalmem_write,.ioctl=globalmem_ioctl,.open=globalmem_open,.release=globalmem_release,};static void globalmem_setup_cdev(struct globalmem_dev *dev,int index){int err,devno=MKDEV(globalmem_major,index);cdev_init(&dev->cdev,&globalmem_fops);dev->cdev.owner=THIS_MODULE;err=cdev_add(&dev->cdev,devno,1);if(err)printk(KERN_NOTICE "ERROR %d adding globalmem %d",err,index);}int globalmem_init(void){int result;dev_t devno=MKDEV(globalmem_major,0);if(globalmem_major)result=register_chrdev_region(devno,2,"globalmem");else{result=alloc_chrdev_region(&devno,0,2,"globalmem");globalmem_major=MAJOR(devno);}if(result<0)return result;globalmem_devp=kmalloc(2*sizeof(struct globalmem_dev),GFP_KERNEL);if(!globalmem_devp){result=-ENOMEM;goto fail_malloc;}memset(globalmem_devp,0,2*sizeof(struct globalmem_dev));globalmem_setup_cdev(&globalmem_devp[0],0);globalmem_setup_cdev(&globalmem_devp[1],1);globalmem_class=class_create(THIS_MODULE,"globalmem");if(IS_ERR(globalmem_class)) { printk(KERN_INFO " create class faild!\n"); return -1; } class_device_create(globalmem_class, NULL, MKDEV(globalmem_major, 0),NULL,"globalmem%d",0); class_device_create(globalmem_class, NULL, MKDEV(globalmem_major, 1),NULL,"globalmem%d",1);return 0;fail_malloc:unregister_chrdev_region(devno,1);return result;}void globalmem_exit(void){cdev_del(&globalmem_devp->cdev);kfree(globalmem_devp);unregister_chrdev_region(MKDEV(globalmem_major,0),1);class_device_destroy(globalmem_class, MKDEV(globalmem_major, 0)); class_device_destroy(globalmem_class, MKDEV(globalmem_major, 1)); class_destroy(globalmem_class); }module_param(globalmem_major,int,S_IRUGO);module_init(globalmem_init);module_exit(globalmem_exit);MODULE_LICENSE("GPL");
遇到的錯誤:
1、globalmem_write中的 const char __user *buf沒有加const,編譯的時候提示了,自己沒有注意結果出現段錯誤。
2、類裝置檔案的建立的時候要用class_device_create().