首页服务器Linux服务器 Linux 字符设备驱动框架详细介绍

Linux 字符设备驱动框架详细介绍

Linux 字符设备驱动框架 字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标…

Linux 字符设备驱动框架

字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标、键盘、显示器、串口等等,当我们执行ls -l /dev的时候,就能看到大量的设备文件,c就是字符设备,b就是块设备,网络设备没有对应的设备文件。编写一个外部模块的字符设备驱动,除了要实现编写一个模块所需要的代码之外,还需要编写作为一个字符设备的代码。

驱动模型

Linux一切皆文件,那么作为一个设备文件,它的操作方法接口封装在struct file_operations,当我们写一个驱动的时候,一定要实现相应的接口,这样才能使这个驱动可用,Linux的内核中大量使用"注册+回调"机制进行驱动程序的编写,所谓注册回调,简单的理解,就是当我们open一个设备文件的时候,其实是通过VFS找到相应的inode,并执行此前创建这个设备文件时注册在inode中的open函数,其他函数也是如此,所以,为了让我们写的驱动能够正常的被应用程序操作,首先要做的就是实现相应的方法,然后再创建相应的设备文件。

#include <linux/cdev.h> //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);  ...}
本文来自网络,不代表1号站长-站长学院|资讯交流平台立场。转载请注明出处: https://www.1cn.cc/fwq/Linux/8923.html
上一篇Linux下实现UTF-8和GB2312互相转换的方法
下一篇 linux tar压缩排除某个文件夹的方法
admin

作者: admin

这里可以再内容模板定义一些文字和说明,也可以调用对应作者的简介!或者做一些网站的描述之类的文字或者HTML!

为您推荐

评论列表()

    联系我们

    联系我们

    0898-88888888

    在线咨询: QQ交谈

    邮箱: email@wangzhan.com

    工作时间:周一至周五,9:00-17:30,节假日休息

    关注微信
    微信扫一扫关注我们

    微信扫一扫关注我们

    关注微博
    返回顶部