Linux下字符设备驱动程序的结构

来源:互联网 发布:好的游戏优化软件 编辑:程序博客网 时间:2024/05/19 23:27

首先,希望可以明确一下概念:

1、 要说的是,驱动,必然是与内核紧密相连的底层程序;并且接口对用户是不可见的。所以你要想到的是如何把驱动和内核联系起来,第一个就想到了模块(modules),模块就像一个载体,一个容器,通过它,会把你写好的程序插入(装载)到内核可见的区域,从而使内核感知到你的驱动的存在,然后用户空间才能通过系统调用的形式联系到驱动,从而完成它的任务,所以你首要了解模块。

2、 驱动位于OS之下,为OS提供硬件操作(当然驱动也有可能不是针对硬件的)的逻辑和底层抽象的封装,所以他要上下兼顾,上边必须符合OS的驱动调用接口,下边要处理好硬件的操作。

3、 Linux比较特殊,把所有的设备都抽象成了文件,这样的话操作接口会比较统一,并且给开发也带来了很大的方便。Linux下设备文件有三种:字符设备、块设备、网络设备。

简单的介绍一下做一个驱动(字符设备驱动)需要做哪些:

1、 表征设备存在的结构体cdev:


struct cdev{ struct kobject kobj;  /* 内嵌的kobject对象*/ struct module *owner;  /*所属模块*/struct file_operations *ops; /*文件操作结构体*/struct list_head list;dev_t dev; /*设备号,为32 位,其中高12 位为主设备号,低20 位为次设备号*/ unsigned int count;};


整个过程都是围绕着这个结构体在进行。对他的各元素赋值并通过模块加载到内核即可。我们逐一的说明一下。

对于,kobject的初始化是在cdev_init里边完成的,它在Fs/Char_dev.c :


void cdev_init(struct cdev *cdev, const struct file_operations *fops){memset(cdev, 0, sizeof *cdev);INIT_LIST_HEAD(&cdev->list);kobject_init(&cdev->kobj, &ktype_cdev_default);cdev->ops = fops;}

这里连带着把kobject、list_head、file_operations也都做了赋值或初始化;这里做为参数你要有一个file_operations来用于赋值,,而file_operations包含了对该字符设备进行操作的所有可能用到的函数(接口)。从而就引出了file_operations,它是整个字符驱动的核心,也是要把所有处理逻辑绑定的对象:


static const struct file_operations globalmem_fops={      .owner = THIS_MODULE,      .read = globalmem_read,      .write = globalmem_write,      .open = globalmem_open,      .release = globalmem_release,  };

这里是个简单的例子,我们要做的就是实现那些等号后边的函数,并对其赋值。下边是file_operations的原型,很完备的接口,只用实现你用到的就可以了(在include/linux/fs.h中):


struct file_operations {struct module *owner;loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);int (*readdir) (struct file *, void *, filldir_t);unsigned int (*poll) (struct file *, struct poll_table_struct *);int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);long (*compat_ioctl) (struct file *, unsigned int, unsigned long);int (*mmap) (struct file *, struct vm_area_struct *);int (*open) (struct inode *, struct file *);int (*flush) (struct file *, fl_owner_t id);int (*release) (struct inode *, struct file *);int (*fsync) (struct file *, struct dentry *, int datasync);int (*aio_fsync) (struct kiocb *, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *);ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);int (*check_flags)(int);int (*flock) (struct file *, int, struct file_lock *);ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);int (*setlease)(struct file *, long, struct file_lock **);};

到这里,通过cdev的初始化,我们已经把你写的逻辑和cdev联系起来了(通过file_operations),然后通过:

    cdev.owner = THIS_MODULE;

直接复制把cdev和当前模块联系了起来。然后是通过:

    dev_tdevno =MKDEV(222,0); 

用MKDEV宏生成一个主设备号222,此设备号0的dev_t类型的设备号变量devno,之后是把设备号和设备结构体cdev关联起来,这样设备才能间接找到它的处理函数,用这个来完成关联:

    cdev_add(&dev->cdev,devno,1);

well,设备结构体准备好了,和具体的设备号也约定好了(这样属于该类型的设备会直接来找它进行具体的处理),另外,也和当前模块挂接好了,还差一步就是让内核知道它的存在,用下边的函数:

    register_chrdev_region(devno,1,"globalmem");

把当前设备注册到内核,这个和cdev没有关系,只是对虚拟设备globalmem进行内核的注册,而他们联系的纽带就是devno。当然对应的还有注销函数:

    unregister_chrdev_region(devno,1);

他们一般是成对出现的。

 

这样就差不多了,整个过程及原理也就是这样了,更详细的,可以好好品读一下Linux驱动开发详解的第六章。讲得非常详细。另外看一下另外一篇blog,【Linux下第一个驱动程序】,是一个实例,并附有大量说明,这样应该可以建立一个初步的概念。然后就是循循渐进了,哈哈。

 

【本文doc文档下载】



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 利客来购物卡丢了怎么办 乐天玛特倒闭卡怎么办 lv皮带买长了怎么办 密袋鼠咬了人怎么办 lv皮带如果长了怎么办 天赐农场公众号进不去了怎么办 苹果删了订阅号怎么办 蚂蚁借呗没有自动扣款怎么办 有对方qq号名字怎么办 腾讯模拟器刺激现场注册上限怎么办 丹阳智慧人社登入密码忘了怎么办? ipad系统被锁了怎么办 电脑管理员账号删了怎么办 自己电脑删文件需要管理员怎么办 苹果电脑管理员密码忘记了怎么办 电脑提示安全设置不允许下载怎么办 微信和ipad同步怎么办 苹果6空间已满怎么办 苹果6内存虚满怎么办 监控主机密码忘了怎么办 加购物车不下单怎么办 绑定qq账号消息不见了怎么办 现在的注册微信怎么办 爱奇艺手机号码被别人绑定了怎么办 手机号码换了支付宝账号怎么办 qq换手机号了怎么办呢 公司被注销了公众号怎么办 qq号被限制查找怎么办 qq号别人查找不到怎么办 qq邮箱已被注册怎么办 微信付款没网络怎么办 天猫买的假货店铺关门了怎么办 鞋小了半码怎么办 迅雷会员种子不能加速怎么办 迅雷会员为什么不能加速怎么办 持有st创智股票怎么办 租的房子床坏了怎么办 宜家定时器不响怎么办 新插座插不进去怎么办 本溪人社app打不开怎么办 南宁电车超过上牌时间怎么办