一、linux驱动开发-1.1-字符设备开发步骤

本文详细介绍了Linux字符设备驱动的开发,包括字符设备的基本概念、驱动加载和卸载、设备注册和注销、以及如何实现设备的具体操作函数。通过示例代码展示了如何注册字符设备,并提供了open、close、write、read等基本操作函数的模板。同时强调了添加license信息的重要性。
摘要由CSDN通过智能技术生成

目录

一、字符设备简介

二、字符设备驱动开发步骤

2.1、驱动模块的加载和卸载

2.2、字符设备的注册和注销

2.3、实现设备的具体操作函数

2.4、添加license信息


一、字符设备简介

       字符设备就是一个一个字节,按照字节流进行读写的设备,读写数据分先后顺序的。常用的led、按键,i2c,spi,lcd等都是字符设备。

       应用程序调用驱动程序如图所示:

       当编好的驱动加载成功后,就会在/dev目录下生成一个相应的文件,如/dev/xxx,应用程序对这个文件进行相应的操作即可实现对硬件的操作。

       应用程序运行在用户空间,驱动运行在内核空间,因为用户空间不能对内核空间进行操作,必须使用一个叫做“系统调用”的方法实现从用户空间陷入到内核空间,C库中提供的open、close、write、read等函数就属于这种“系统调用”。具体的流程如下:

       在linux内核文件include/linux/fs.h中file_operations的结构体,就是内核驱动操作函数的集合。file_operation常用的重要函数:

file_opration
owner拥有该结构体的模块的指针,一般是THIS_MODULE
llseek  修改文件当前的读写位置
read读取设备文件
write向设备文件写入数据
poll查询设备是否可以进行非阻塞的读写
unlocked_ioctl提供对设备的控制功能,应用程序中使用ioctl函数
compat_ioctl与unlocked_ioctl函数功能一样
mmap用于将设备的内存映射到用户空间,一般帧缓冲设备会使用此函数
open打开设备文件
release关闭设备文件,与应用中的close函数一致
fasync用于刷新待处理的数据,将缓冲区中的数据刷新到磁盘
aio_fsync与fsync功能类似,属于异步刷新待处理的数据

       字符设备驱动开发中,最主要的工作就是实现这个结构体中的函数,具体实现哪些看具体的硬件要求,一般的open、close、write、read等是要实现的。

二、字符设备驱动开发步骤

        在linux中,驱动开发要按照规定的框架来编写,一般有:

        ①、驱动的加载和卸载

        ②、设备注册和注销

        ③、实现设备的具体操作

        ④、添加license信息

2.1、驱动模块的加载和卸载

       linux驱动有两种运行模式:将驱动编译至内核中,内核启动后自动运行该驱动程序;将驱动编译成模块(扩展名为.ko),内核启动后用“insmod”加载驱动模块。

      推荐使用modprobe命令加载模块,因为insmod命令不能解决依赖关系,modprobe会分析模块的依赖关系,然后将所有依赖模块都加载到内核中,更智能一点。

       在调试阶段,一般是先编译成模块,没问题后再编译进内核,这样做的好处是不用编译整个linux代码,也不用重启整个系统,只需要加载卸载驱动模块即可。

       模块的加载和卸载函数如下,

module_init(xxx_init);    //注册模块加载函数
modele_exit(xxx_exit);    //注册模块卸载函数

       module_init函数用来向linux内核注册一个模块加载函数,参数xxx_init就是需要注册的具体函数,当使用“insmod”命令加载驱动的时候,xxx_init就会被调用。module_exit函数用来向linux内核注册一个模块卸载函数,参数xxx_exit就是需要注册的具体函数,当使用“rmmod”命令卸载具体的驱动时候,xxx_exit就会被调用。

        模板如下:

/* 驱动入口函数 */
static int __init xxx_init(void)
{
    /* 入口函数具体内容,需实现 */
    return 0;
}

/* 驱动出口函数 */
static void __exit xxx_exit(void)
{
   /* 出口函数具体内容,需实现 */
}

/* 将上面两个函数指定为驱动的入口和出口函数 */
module_init(xxx_init);
module_exit(xxx_exit);

2.2、字符设备的注册和注销

       驱动模块加载成功后需要注册字符设备卸载驱动模块的时候需要注销字符设备,函数原型如下:

/*
@major:主设备号
@name:设备名字
@fops:设备操作函数集合
*/
static inline int register_chrdev(unsigned int major, 
                                  const char *name,
                                  const struct file_operations *fops);

/*
@major:主设备号
@name:设备名字
*/
static inline void unregister_chrdev(unsigned int major, 
                                     const char *name);

       设备号要用系统中没用掉的,用cat /proc/devices可以查看当前已经使用掉的设备号。

   

        设备号链接如下:

         一般字符设备的注册在驱动模块的入口函数中进行,注销在出口函数中进行,               模板如下:

static struct file_operations fops;

static int __init xxx_init(void)
{
    register_chrdev(200, "chrtest", &fops);
}

static void __exit xxx_exit(void)
{
    unregister_chrdev(200, "chrtest");
}

module_init(xxx_init);
module_exit(xxx_exit);

2.3、实现设备的具体操作函数

        实现file_operations机构体中的函数 ,具体实现哪些看需求。一般包括open、close、write、read。

        模板如下:

static int chrtest_open(struct inode *inode, struct file *filp)
{
    //用户代码
}

static ssize_t chrtest_read(struct file *filp, __user char *buf, size_t count,loff_t *ppos)
{
    //用户代码
}

static ssize_t chrtest_write(struct file *filp, const char __user *buf,
			 size_t count, loff_t *ppos)
{
    //用户代码
}

static int chrtest_release(struct inode *inode, struct file *filp)
{
    //用户代码
}

static const struct file_operations chrtest_fops = {
    .owner = THIS_MODULE,
    .open  = chrtest_open,
    .read  = chrtest_read,
    .write = chrtest_write,
    .close = chrtest_release,

};

static int __init xxx_init(void)
{
    int ret = 0;

    ret = register_chrdev(200, "chrtest", &chrtest_fops);
    if (ret < 0)
    {
        //注册失败处理
    }
    return 0;
}

static void __exit xxx_exit(void)
{
    unregister_chrdev(200, "chrtest");
}

module_init(xxx_init);
module_exit(xxx_exit);




2.4、添加license信息

        licence是必须添加的,否则编译会报错,作者信息可以不添加。

MODULE_LICENSE();    //添加模块license信息
MODULE_AUTHOR();     //添加模块作者信息

//eg:
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZK");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值