Linux简单的字符文件驱动.doc_第1页
Linux简单的字符文件驱动.doc_第2页
Linux简单的字符文件驱动.doc_第3页
Linux简单的字符文件驱动.doc_第4页
Linux简单的字符文件驱动.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Linux 简单的字符文件驱动字符设备是Linux 设备驱动中最简单的。struct cdev struct kobject *kobj; struct module *owner; /所属模块 struct file_operations *ops; struct list_head_list; dev_t dev; unsigned int count;1 设备编号:dev_t类型,高12位表示主设备号,低20位表示次设备号。一般同一类设备拥有同样的主设备,表示使用相同的驱动程序。次设备号用以区分不同的具体的设备,一般从0开始编号。系统中注册的设备在/pro/devices,内核文档中的devices.txt描述了Linux设备号的分配情况,由LANANA组织维护。下面的宏可以用主设备号和次设备号来生成设备号:MKDEV(int major,int minor)可以通过这两个宏来获取主设备号和从设备号:MAJOR(dev_t dev)MINOR(dev_t dev)通过下面的函数可以申请主设备号:int register_chrdev_region(dev_t from,unsigned count,const char *name);/from指定了已知起始设备int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,char *name);/向系统动态申请未被占用的设备号。void unregister_chrdev_region(dev_t form,unsigned count); /回收之前申请的设备号2 与字符设备cdev主要的函数:void cdev_init(struct cdev *,struct file_operations *); /建立cdev和file_operations之间的联系struct cdev *cdev_alloc();/分配新的cdevvoid cdev_put(struct cdev *);/回收cdev的空间void cdev_del(struct cdev *);/向系统注销设备int cdev_add(struct cdev *,dev_t ,unsigned int count); /向系统注册设备3 file_operations当VFS接收到对设备的读取等请求时,会调用到file_operations中对应的函数。在实现read和write时可能会需要使用下面的函数,进行用户空间和内核空间的数据交换。unsigned long copy_from_user(void *to,const void _user *from,unsigned long count);unsigned long copy_to_user(void _user *to,const void *from,unsigned long count);这两个函数返回未能拷贝的字节,如果成功,返回为0.如果数据类型是简单的数据,int long char等,可以使用更为简单的函数:比如要传递一个int,int val;get_user(val,(int *)arg);/用户空间到内核空间,arg为用户空间地址put_user(val,(int *)arg);/内核空间到用户空间_user宏表明后面指向的地址为用户空间。宏container_of(ptr,type,member)可以通过结构体的子项来定位整个结构体的指针。例如:struct Tint a;int b;struct T t =0;container_of(&t.a,int,a)就会返回指向T的指针来自于linux设备驱动开发详解的一个例子如下:#include #include #include #include #include #include #include #include #include #include #include #define MAX_SIZE (4096*2)#define MAX_DEV (2)/支持的子设备数struct mem_dev struct cdev dev; char memMAX_SIZE;struct mem_dev *g_mem_devp = NULL; static int mem_open(struct inode *inode,struct file *filp) /通过结构体成员找到结构体指针 struct mem_dev *devp = NULL; devp = container_of(inode-i_cdev,struct mem_dev,dev); filp-private_data = devp; printk(KERN_INFO sucess to openn); return 0;static ssize_t mem_read(struct file *filp,char _user *buf,size_t size,loff_t *ppos) int ret = 0; unsigned long pos = *ppos; struct mem_dev *dev = filp-private_data; if(pos MAX_SIZE) return size 0 ? -ENXIO : 0; if(size MAX_SIZE - pos) size = MAX_SIZE - pos; if(copy_to_user(buf,(void *)(dev-mem + pos),size) /if(copy_to_user(buf,(void *)(hello),6) ret = -EFAULT; else *ppos += size; /需要修改pos ret = size; printk(KERN_INFO read %d bytes at %dn,size,pos); if(ret 0) printk(KERN_INFO sucess to readn); return ret;static ssize_t mem_write(struct file *filp,char _user *buf,size_t size,loff_t *ppos) int ret = 0; unsigned long pos = *ppos; struct mem_dev *dev = filp-private_data; if(pos MAX_SIZE) return size 0 ? -ENXIO : 0; if(size MAX_SIZE - pos) size = MAX_SIZE - pos; if(copy_from_user(void *)(dev-mem + pos),buf,size) ret = -EFAULT; else *ppos += size; ret = size; printk(KERN_INFO write %d bytes at %dn,size,pos); if(ret 0) printk(KERN_INFO sucess to writen); return ret;static loff_t mem_llseek(struct file *filp, loff_t offset, int orig) loff_t ret = 0; switch(orig) case SEEK_SET: if(offset MAX_SIZE) ret = -EINVAL; break; filp-f_pos = offset; ret = filp-f_pos; break; case SEEK_CUR: if(offset + filp-f_pos f_pos MAX_SIZE) ret = -EINVAL; break; filp-f_pos += offset; ret = filp-f_pos; break; default: /inlucde SEEK_END ret = -EINVAL; break; return ret;static struct file_operations g_mem_fops = .owner = THIS_MODULE, .llseek = mem_llseek, .read = mem_read, .open = mem_open, .write = mem_write,;static int mem_init_cdev(struct mem_dev *devp,dev_t devno) cdev_init(&devp-dev,&g_mem_fops); devp-dev.ops = &g_mem_fops; devp-dev.owner = THIS_MODULE; devp-dev.dev = devno; return cdev_add(&devp-dev,devno,1);static int globalmem_init() int ret = 0; int i = 0; dev_t devno = 0; int major = 0; if(alloc_chrdev_region(&devno,0,MAX_DEV,global_mem) 0) printk(failed in alloc_chrdev_region); return -1; major = MAJOR(devno); if(g_mem_devp = kmalloc(MAX_DEV*sizeof(struct mem_dev),GFP_KERNEL) = NULL) ret = -ENOMEM; goto ERR; memset(g_mem_devp,0,MAX_DEV*sizeof(struct mem_dev); for(i = 0; i MAX_DEV; +i) ret = mem_init_cdev(&g_mem_devpi,MKDEV(major,i); prin

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论