嵌入式Linux驱动开发——Hello驱动(后附百问网课程视频链接)

1.如何编写驱动程序

2.编写驱动程序

①确定主设备号

register_chrdev函数

cpp 复制代码
函数原型:
    int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
函数功能:

    为字符设备注册一个主号码。
入参:

    1. unsigned int major:用于动态分配的主要设备号或0,如果给0内核回自动分配主设备号

    2. const char *name:这一系列设备的名称

    3. const struct file_operations:与此设备相关联的文件操作
回参:
    返回主设备号

②file_operations结构体

cpp 复制代码
static void __init hello_exit(void)
{
	
	class_destroy(hello_class);
	device_destroy(hello_class, MKDEV(major, 0));
	unregister_chrdev(major,"hello");
}

③实现对应的函数,填入结构体

copy_from_user函数

cpp 复制代码
函数原型:
    copy_from_user(void *to, const void __user *from, unsigned long n)
作用:
    将@form地址中的数据拷贝到@to地址中去,拷贝长度是n
入参:
    1. to 将数据拷贝到内核的地址
    2. from 需要拷贝数据的地址
    3. n 拷贝数据的长度(字节)
回参:
    失败返回没有被拷贝的字节数,成功返回0.

copy_to_user函数

cpp 复制代码
函数原型:
    long copy_to_user(void __user *to, const void *from, unsigned long n);
作用:
    将内核空间的数据复制到用户空间。
入参:
    1. void __user *to:这是用户空间的目标地址,数据将被复制到这个地址。
    2. const void *from:这是内核空间的源地址,数据将从这个地址被复制。
    3. unsigned long n:要复制的字节数。
回参:
    返回值是一个 long 类型;
    如果复制成功,返回 0;
    如果在复制过程中发生错误,返回一个负数,表示未能成功复制的字节数。

④注册驱动程序

register_chrdev函数

cpp 复制代码
函数原型:
    int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
函数功能:

    为字符设备注册一个主号码。
入参:

    1. unsigned int major:用于动态分配的主要设备号或0

    2. const char *name:这一系列设备的名称

    3. const struct file_operations:与此设备相关联的文件操作

⑤入口函数

cpp 复制代码
static int __init hello_init(void)

写好入口函数后,需要使用module_init告诉内核这是入口函数

cpp 复制代码
module_init(hello_init);

⑥出口函数

cpp 复制代码
static void __init hello_exit(void)

同理,写好出口函数后,需要使用module_exit告诉内核这是出口函数

cpp 复制代码
module_exit(hello_init);

⑦提供设备信息,创建设备节点

class_create()函数

cpp 复制代码
函数原型:
    #define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})
函数功能:
    宏class_create()用于动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加进Linux内核系统中。此函数的执行效果就是在/sys/class/目录下创建一个新的文件夹,此文件夹的名字为此函数的第二个输入参数,但此文件夹是空的。宏class_create()在实现时,调用了函数__class_create()。

入参:

    1. owner:一个struct module结构体类型的指针,指向函数__class_create()即将创建的、"拥有"这个struct class的模块。一般赋值为THIS_MODULE,此结构体的详细定义见文件include/linux/module.h。

    2. name:char类型的指针,代表即将创建的struct class变量的名字,用于给struct class的name字段赋值。通俗地说,就是指向struct class名称的字符串的指针。

device_creat()函数

cpp 复制代码
函数原型:
    struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);

函数功能:

    函数device_create()用于动态地创建逻辑设备,并对新的逻辑设备类进行相应的初始化,\将其与此函数的第一个参数所代表的逻辑类关联起来,然后将此逻辑设备加到Linux内核系统的设备驱动程序模型中。\函数能够自动地在/sys/devices/virtual目录下创建新的逻辑设备目录,在/dev目录下创建与逻辑类对应的设备文件。

入参:

    1.struct class *cls:输入参数代表与即将创建的逻辑设备相关的逻辑类。

    2.struct device *parent:输入参数代表即将创建的逻辑设备的父设备的指针,子设备与父设备的关系是:当父设备不可用时,子设备不可用,子设备依赖父设备,父设备不依赖子设备。

    3.dev_t devt:输入参数是逻辑设备的设备号。

    4.void *drvdata:输入参数是void类型的指针,代表回调函数的输入参数。

    5.const char *fmt:输入参数是逻辑设备的设备名,即在目录/sys/devices/virtual/和/dev创建的逻辑设备目录的目录名。

课程链接:

12_Hello驱动上机实验_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1XK411D7wK?p=13&spm_id_from=pageDriver&vd_source=3a9afee9fda50350a1c881b4325e007d

相关推荐
wuminyu3 分钟前
Java锁膨胀机制之偏向锁到轻量级锁源码剖析
java·linux·c语言·jvm·c++
xhtdj3 分钟前
技术采用曲线回望二十年
运维·数据库·人工智能·clickhouse·动态规划
SuperArc19994 分钟前
Grafana相关数据可视化平台基础教程-序言
运维·信息可视化·数据分析·grafana
半部论语8 分钟前
openEuler 安装 LibreOffice 技术指南
linux
r-t-H8 分钟前
Docker进阶与容器编排实践-第二章
运维·docker·容器·dockerfile·docker compose·docker网络
凡人叶枫14 分钟前
Effective C++ 条款13:以对象管理资源(RAII)
java·linux·开发语言·c++·嵌入式开发
爱喝水的鱼丶18 分钟前
SAP-ABAP:SAP多表连接视图实战:内连接/外连接配置逻辑与性能优化技巧
运维·开发语言·学习·性能优化·sap·abap
cgsthtm19 分钟前
Jenkins添加用户和角色并分配相应Job权限
运维·jenkins·jenkins用户·jenkins角色·jenkins权限·jenkins job
mnasd22 分钟前
Gitlab + Jenkins 实现 CICD
运维·gitlab·jenkins
難釋懷28 分钟前
Nginx测试工具charles
运维·nginx·php