20191013 (24)ARM Linux 字符设备驱动(1)驱动开发摸板(框架)

驱动基础介绍

在这里插入图片描述

1 驱动加载成功以后会在 /dev 目录下生成一个相应文件夹,通过对文件夹下的内容进行调用

加粗样式
2 include/linux/fs.h 中的 file_operations 结构体定义了 linux 内核驱动操作函数集合

在这里插入图片描述
在这里插入图片描述

owner 拥有该结构体的模块的指针,一般设置为 THIS_MODULE
llseek 函数用于修改文件当前的读写位置
read 函数用于读设备文件
write 函数用于写设备文件
poll 轮询函数,用于查询设备是否可以进行非阻塞的读写
unlocked_ioctl 函数提供对于设备的控制功能,与应用程序中的 ioctl 函数对应
compat_ioctl 与 Unlocked_ioctl 区别在于在 64 位系统上,32 位的应用程序调用将会使用此函数,而在 32 位系统调用 unlocked_ioctl
mmap 用于将设备的内存映射到进程空间(用户空间),一般帧缓冲设备会使用此函数,例如 LCD 驱动的显存,可以避免来回复制
open 函数打开设备文件
release 函数释放(关闭) 设备文件,与应用程序中的 close 函数对应
fasync 函数用于刷新待处理的数据,用于将缓冲区中的数据刷新到磁盘中
aio_fasync 函数是异步处理


驱动模块接口

1 出入口函数
insmod xxx.ko 加载驱动
rmmod xxx.ko 卸载驱动
lsmod 已加载驱动的列表
modprobe -r xx.ko 一键卸载驱动模块所依赖的其它模块

在文件中需要声明

//驱动入口
static int   __init xx_init(void) 
{
    return 0;
}

//驱动出口
static void   __exit xxx_exit(void) 
{
    
}

//向 linux 声明出入口函数
module_init(xxx_init);
module_exit(xxx_exit);

2 字符设备注册与注销

static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

static inline void unregister_chrdev(unsigned int major, const char *name)
// major 主设备号,Linux 下每一个设备都又一个设备号
// name 设备名字
// fops  结构体 file_operations 类型指针,指向设备的操作函数集合变量
ll 例程
static struct file_operations test_fops;

static int   __int xxx_init(void) 
{
    int retvalue = 0;
    retvalue = register_chrdev(200, "chrtest", &test_fops);
    if (retvalue < 0) {
        //字符设备注册失败,自行处理
    }
    
    return 0;
}

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

module_init(xxx_init):
module_exit(xxx_init);

注意: cat /proc/devices 要确保设备号没有被使用

3 实现具体操作函数
3.1 开 / 关
3.2 读 / 写

//打开设备
static int chrtest_open(struct inode *inode, struct file *filp) {
    //具体实现功能
    return 0;
}

//从设备读取
static ssize_t chrtest_read(struct file *filp, char __user *buf,
size_t cnt, loff_t *offt) {
    //具体功能
    retunr 0;
}

//向从设备写数据
static ssize_t chrtest_write(struct file *filp, 
                                    const char __user *buf,
                                    size_t cnt, loff_t *offt)
{
    //具体功能
    return 0;
}

//关闭 / 释放设备
static int chrteat_release(struct inode *inode, struct file *filp) 
{
    //具体功能
    retunr 0;
}
//核心
static struct file_operations test_fops = {
    .owner = THIS_MODULE,
    .open = chrtest_open,
    .read = chrtest_read,
    .write = chrtest_write,
    .release = chrtest_release,
};

static int    __init xxx_init(void) 
{
    int retvalue = 0;
    retvalue = register_chrdev(200, "chrtest", &test_fops);
    if (retvalue < 0) {
        //注册失败自行处理
    }
    return 0;
}

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

module_init(xxx_init);
module_exit(xxx_exit);

MODULE_LICENSE("GPL"); //证书必须加
MODULE_AUTHOR("xxxxx"); //作者 非必须
发布了120 篇原创文章 · 获赞 27 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_24890953/article/details/102537099