首页 Linux系统字符设备驱动框架笔记

Linux系统字符设备驱动框架笔记

举报
开通vip

Linux系统字符设备驱动框架笔记Linux系统字符设备驱动框架笔记   不积跬步,何以至千里。掌握知识都是从很小的点开始的。下面是整理的Linux系统字符设备驱动框架笔记,欢迎阅读!   字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行 ls -l /dev 的时候,就能看到大量的设备文件, c 就是字符设备, b 就是块设备,网络设备没有对应的设备文件。编写一个外部模块的字符设备驱动,除了要实现编写一个模块...

Linux系统字符设备驱动框架笔记
Linux系统字符设备驱动框架笔记   不积跬步,何以至千里。掌握知识都是从很小的点开始的。下面是整理的Linux系统字符设备驱动框架笔记,欢迎阅读!   字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行 ls -l /dev 的时候,就能看到大量的设备文件, c 就是字符设备, b 就是块设备,网络设备没有对应的设备文件。编写一个外部模块的字符设备驱动,除了要实现编写一个模块所需要的代码之外,还需要编写作为一个字符设备的代码。   驱动模型   Linux一切皆文件,那么作为一个设备文件,它的操作方法接口封装在 struct file_operations ,当我们写一个驱动的时候,一定要实现相应的接口,这样才能使这个驱动可用,Linux的内核中大量使用"注册+回调"机制进行驱动程序的编写,所谓注册回调,简单的理解,就是当我们open一个设备文件的时候,其实是通过VFS找到相应的inode,并执行此前创建这个设备文件时注册在inode中的open函数,其他函数也是如此,所以,为了让我们写的驱动能够正常的被应用程序操作,首先要做的就是实现相应的方法,然后再创建相应的设备文件。   #include //for struct cdev   #include //for struct file   #include //for copy_to_user   #include //for error number   /* 准备操作方法集 */   /*   struct file_operations {   struct module *owner; //THIS_MODULE   //读设备   ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);   //写设备   ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);   //映射内核空间到用户空间   int (*mmap) (struct file *, struct vm_area_struct *);   //读写设备参数、读设备状态、控制设备   long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);   //打开设备   int (*open) (struct inode *, struct file *);   //关闭设备   int (*release) (struct inode *, struct file *);   //刷新设备   int (*flush) (struct file *, fl_owner_t id);   //文件定位   loff_t (*llseek) (struct file *, loff_t, int);   //异步通知   int (*fasync) (int, struct file *, int);   //POLL机制   unsigned int (*poll) (struct file *, struct poll_table_struct *);   。。。   };   */   ssize_t myread(struct file *filep, char __user * user_buf, size_t size, loff_t* offset)   {   return 0;   }   struct file fops = {   .owner = THIS_MODULE,   .read = myread,   ...   };   /* 字符设备对象类型 */   struct cdev {   //public   struct module *owner; //模块所有者(THIS_MODULE),用于模块计数   const struct file_operations *ops; //操作方法集(分工:打开、关闭、读/写、...)   dev_t dev; //设备号(第一个)   unsigned int count; //设备数量   //private   ...   };   static int __init chrdev_init(void)   {   ...   /* 构造cdev设备对象 */   struct cdev *cdev_alloc(void);   /* 初始化cdev设备对象 */   void cdev_init(struct cdev*, const struct file_opeartions*);   /* 为字符设备静态申请设备号 */   int register_chedev_region(dev_t from, unsigned count, const char* name);   /* 为字符设备动态申请主设备号 */   int alloc_chedev_region(dev_t* dev, unsigned baseminor, unsigned count, const char* name);   MKDEV(ma,mi) //将主设备号和次设备号组合成设备号   MAJOR(dev) //从dev_t数据中得到主设备号   MINOR(dev) //从dev_t数据中得到次设备号   /* 注册字符设备对象cdev到内核 */   int cdev_add(struct cdev* , dev_t, unsigned);   ...   }   static void __exit chrdev_exit(void)   {   ...   /* 从内核注销cdev设备对象 */   void cdev_del(struct cdev* );   /* 从内核注销cdev设备对象 */   void cdev_put(stuct cdev *);   /* 回收设备号 */   void unregister_chrdev_region(dev_t from, unsigned count);   ...   }   实现read,write   Linux下各个进程都有自己独立的进程空间,即使是将内核的数据映射到用户进程,该数据的PID也会自动转变为该用户进程的PID,由于这种机制的存在,我们不能直接将数据从内核空间和用户空间进行拷贝,而需要专门的拷贝数据函数/宏:   long copy_from_user(void *to, const void __user * from, unsigned long n)   long copy_to_user(void __user *to, const void *from, unsigned long n)   这两个函数可以将内核空间的数据拷贝到回调该函数的用户进程的用户进程空间,有了这两个函数,内核中的read,write就可以实现内核空间和用户空间的数据拷贝。   ssize_t myread(struct file *filep, char __user * user_buf, size_t size, loff_t* offset)   {   long ret = 0;   size = size > MAX_KBUF?MAX_KBUF:size;   if(copy_to_user(user_buf, kbuf,size)   return -EAGAIN;   }   return 0;   }
本文档为【Linux系统字符设备驱动框架笔记】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_842972
暂无简介~
格式:doc
大小:7KB
软件:Word
页数:0
分类:互联网
上传时间:2017-03-15
浏览量:7