搭建字符驱动的框架

  1、驱动三要素:

/*头文件*/
#include <linux/init.h>
#include <linux/module.h>

/*加载函数*/
module_init();
/*卸载函数*/
module_exit();

  2、驱动初始化

1)申请设备号

/*静态申请*/
int register_chrdev_region(dev_t from, unsigned count, const char *name)
指定从设备号from开始,申请count个设备号,在
/proc/devices中的名字为name。 返回值: 成功返回0,失败返回错误码。
/*动态申请*/ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
动态申请从次设备号baseminor开始的count个设备号,在
/proc/devices中的名字为name,并通过dev指针把分配到的设备号返回给调用函数者。 返回值: 成功返回0,失败返回错误码。

2)字符设备的注册(告诉内核操作设备的函数)

注册函数用结构体struct cdev来表示一个字符设备。字符设备的注册就是要定义一个这样的结构体并且填上对应的内容。

先看一下结构体的成员,没注释的是内核自己要填的。
/*/include/linux/cdev.h*/
struct cdev {
    struct kobject kobj;
    struct module *owner;    //一般初始化为THIS_MODULE
    const struct file_operations *ops;    //文件操作结构体
    struct list_head list;
    dev_t dev;    //设备号
    unsigned int count;    //添加的设备个数
};

注册也分为三个步骤:

  1)分配cdev

  2)初始化cdev

  3)添加cdev

分配cdev简单的说就是定义一个cdev结构体

 

方法一:直接定义:
struct cdev test_cdev;
方法二:调用函数:struct cdev* cdev_alloc(void)
struct cdev* test_cdev;
test_cdev = cdev_alloc();

 

初始化cdev将文件操作结构体添加到cdev中:

void cdev_init(struct cdev *cdev, const struct file_operations *fops)
参数:
cdev:之前我定义的cdev结构体;
fops:设备对应的文件操作结构体。
返回值:(函数有可能失败,查看返回值是必须的)
成功返回0,示范返回对应的错误码

这个函数干了两件事情:

  1)内核自己填充了结构体中list和kobj的内容

  2)把我传入的文件操作结构体也填充进去。

一般的,还要手工定义结构体成员owner。

struct file_operations test_fops;
cdev_init(&test_cdev, &test_fops);
test_cdev->owner = THIS_OWNER    //指定模块的所属

添加cdevcdev结构体与设备号关联起来:

 

int cdev_add(struct cdev *cdev, dev_t dev, unsigned count)
参数:
cdev:指定要被添加的cdev结构体;
dev:对应的设备号
count:从设备号dev开始添加count个设备.
返回值:
成功返回0,失败返回对应的错误码。

 

函数干了也两件事:

  1)把cdev结构体中还没填充的两个成员dev和count按照传入参数赋值。

  2)把cdev结构体中传入内核,这样内核就知道对应设备号和具体的文件操作结构体了。

 

 

 

  3、实现设备操作

定义file_operation,并添加实现函数

  4、驱动注销

/*删除cdev*/
void
cdev_del(struct cdev *p)
使用:这是添加的逆操作,模块卸载时调用
/*释放设备号*/

 void unregister_chrdev_region(dev_t from, unsigned count)

 使用:释放从from开始count个设备号。

此外,还可以自动生成字符类设备节点:

首先定义

static struct class *xxx_class;

static struct class_device *xxx_class_dev;

1、创建设备类

class_create

2、释放设备类

class_destroy

3、创建字符类设备节点

class_device_create

4、摧毁设备节点

class_device_unregister

posted on 2016-08-24 09:55  yiyedada  阅读(176)  评论(0编辑  收藏  举报

导航