Linux设备驱动--(五)字符设备驱动-上

Linux设备驱动–(五)字符设备驱动-上

一、字符设备驱动基础

  1. 基本概念

    ​ 在前面几篇博客里,已经基本介绍了Linux的驱动的的分类情况。所谓的字符设备就是指其数据的处理是以字节流的形式。

    ​ 我们都知道有一句经典的话"linux下一切皆文件",这句话的意思意思是什么呢?这就意味着,我们的设备最终会议文件的形式被上层去调用(当然啦,网络设备是一个意外)。这样做的好处呢,就是为了统一上层接口。设想一下,字符设备多种多样,如果我们能够将其统一以文件的形式呈现给应用程序,那么这岂不是很方便,而且也很便于管理。设备文件通常位于/dev/目录下。我们可以使用一下指令渠道该目录下面去查看相关的设备文件。

    ls -l /dev
    

    ​ 虽说设备也被当做文件来看待,但是呢。涉备文件比普通文件多路两个数字。这两个数字就是主设备号次设备号。这两个号是设备在内核中的身份标志,是内核区分不同设备的唯一信息。

    主设备号:用来区别一类设备

    次设备号:用于区分同一类设备的不同个体

    路径名:用户层用来区别设备信息的

  2. 创建设备

    ​ 设备文件可以自动创建,有可以手动创建。

    1. 手动创建设备号

      手动创建设备文件使用命令mknod,其含义使make node,即创建一个设备结点,也说创建一个设备文件。(这里的节点是存在于磁盘上面的,也有存在于内存上面的节点)

    # mknode /dev/hello c 256 0
    
    @/dev/hello	:设备文件的路径
    @c : 代表字符设备,另外b代表块设备。你会发现没有网络设备的没有代表符啊,仔细看上面,网络设备是不能当做文件来看的,关于网络设备的驱动后米娜会介绍到,不着急。
    @256 :主设备号
    @0:次设备号
    
    //mknod命令将文件名,文件类型和主次设备号都保存到磁盘上。
    
    1. 自动创建
    struct class *class_create(owner, name)//创建一个类
    参数1: THIS_MODULE
    参数2: 字符串名字,自定义
    返回一个class指针
    
    //创建一个设备文件
    struct device *device_create(struct class * class, struct device * parent, dev_t devt, 
    void * drvdata, const char * fmt,...)
    参数1: class结构体,class_create调用之后到返回值
    参数2:表示父亲,一般直接填NULL
    参数3: 设备号类型 dev_t
    dev_t devt
    #define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
    #define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
    #define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))
    参数4:私有数据,一般直接填NULL
    参数56:表示可变参数,字符串,表示设备节点名字
    
    销毁动作:
    void device_destroy(devcls,  MKDEV(dev_major, 0));
    参数1: class结构体,class_create调用之后到返回值
    参数2: 设备号类型 dev_t
    
    void class_destroy(devcls);
    参数1: class结构体,class_create调用之后到返回值
    

二、字符设备驱动框架

  1. 应用程序与驱动程序间联系

    我们知道,我们的设备文件最终是要被应用程序调用的。那么应用程序最终有时怎样访问到我们的设备的呢?

    前面讲到过,在Linux中,每个文件都有一个struct inode结构体来描述,该结构体中记录了文件的所有信息,比如文件名,文件类型,访问权限等。

    另外还要提到一点,每当我们打开一个文件,Linux操作系统就会在VFS层为其分配一个struct file结构体来描述打开的的这个文件

  • 当我们打开设备文件时,会根据相应的设备文件相对应的struct inode结构体的描述信息,获取该设备的相关信息。如其实一个字符设备还是以个块设备以及其文件权限。同时Linux还会分配一个struct file结构体来描述我们打开的设备文件。

  • 根据struct inode结构体重还存放着描述字符设备的结构体struct cdev。struct cdev函数中有一个struct file_operations结构体记载着设备操作函数的接口。

  • 而我们struct file结构体中也有一个,struct file_operations结构体,当然了该结构体也是用来存放社诶相关操作函数的入口(其实就是相关操作函数的入口地址)。那么这个地址怎么来呢?我们通过open打开这个设备之后,Linux系统就会将struct inode结构体中记录的设备的操作函数的入口地址给拷贝到struct file结构体中。如此一来上层设备就获得的相关操作函数的地址了,就可以去操作相关的设备文件了。当然啦,实际上open函数系统调用底层还是很复杂的,这里将其做了非常大的简化。只是为了讲清楚其大体的框架。

    如果要追究其深层的原因,建议可以去看一下《Linux设备驱动程序》。

    当然啦,因为我个人比较懒,又没有找到一个很好的画图工具。说以就没有没有画图,只看文字的话可能初学者还是有点儿蒙的。所以呢,所以将之前在网上看到的一个讲字符驱动讲的很好的博客。链接如下:

    http://blog.chinaunix.net/uid-26833883-id-4369060.html

发布了49 篇原创文章 · 获赞 15 · 访问量 9255

猜你喜欢

转载自blog.csdn.net/wit_732/article/details/102945526