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

相关推荐
Youkiup3 分钟前
【linux 常用命令】
linux·运维·服务器
qq_297504616 分钟前
【解决】Linux更新系统内核后Nvidia-smi has failed...
linux·运维·服务器
_oP_i12 分钟前
.NET Core 项目配置到 Jenkins
运维·jenkins·.netcore
weixin_4373982119 分钟前
Linux扩展——shell编程
linux·运维·服务器·bash
小燚~21 分钟前
ubuntu开机进入initramfs状态
linux·运维·ubuntu
小林熬夜学编程29 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
炫彩@之星32 分钟前
Windows和Linux安全配置和加固
linux·windows·安全·系统安全配置和加固
上海运维Q先生33 分钟前
面试题整理15----K8s常见的网络插件有哪些
运维·网络·kubernetes
hhhhhhh_hhhhhh_43 分钟前
ubuntu18.04连接不上网络问题
linux·运维·ubuntu
冷心笑看丽美人1 小时前
探秘 DNS 服务器:揭开域名解析的神秘面纱
linux·运维·服务器·dns