嵌入式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

相关推荐
€☞扫地僧☜€1 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
hjjdebug1 小时前
linux 下 signal() 函数的用法,信号类型在哪里定义的?
linux·signal
其乐无涯1 小时前
服务器技术(一)--Linux基础入门
linux·运维·服务器
Diamond技术流1 小时前
从0开始学习Linux——网络配置
linux·运维·网络·学习·安全·centos
写bug的小屁孩1 小时前
前后端交互接口(三)
运维·服务器·数据库·windows·用户界面·qt6.3
斑布斑布1 小时前
【linux学习2】linux基本命令行操作总结
linux·运维·服务器·学习
紅色彼岸花1 小时前
第六章:DNS域名解析服务器
运维·服务器
Spring_java_gg1 小时前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
✿ ༺ ོIT技术༻1 小时前
Linux:认识文件系统
linux·运维·服务器
会掉头发2 小时前
Linux进程通信之共享内存
linux·运维·共享内存·进程通信