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创建的逻辑设备目录的目录名。
课程链接: