字符设备特征:

APP 如何找到字符设备

当驱动加载后会产生一个设备文件,也会有一个唯一对应的innode结构体。当应用层调用open函数时,会进入内核发生一次软中断,从用户空间进入到内核空间。open会调用内核中的sys_open函数,该函数会根据open函数传入的文件名确定该文件是一个字符设备还是其他设备文件。如果是字符设备文件,则会通过字符设备的主设备号和次设备号在chrdevs结构体中找到对应的一项。该项中会有file_operation结构体,file_operation结构体中会有.open等函数。简单理解为,当APP调用open函数时会调用到驱动中对应的open函数。
字符设备驱动流程
1、确定主次设备号:静态指定或动态向内核申请。
2、实现 file_operations 方法:编写 open, read, write 等函数的具体代码。在这些函数中,你可能会:
从硬件寄存器读取数据(read)。
向硬件寄存器写入数据(write)。
配置硬件(ioctl)。
使用 copy_to_user() 和 copy_from_user() 在内核空间(驱动程序)和用户空间之间安全地传递数据。
3、注册字符设备
major=register_chrdev(主设备号,驱动名字,&file_operations)
4、创建设备文件:在 /dev 目录下使用 mknod 命令或通过驱动代码自动创建(使用 device_create)一个设备文件,并将其与你的设备号关联。
5、模块的加载和卸载:
在模块加载函数 (module_init) 中完成上述的申请设备号、注册 cdev 等操作。
在模块卸载函数 (module_exit) 中完成相反的清理工作:注销 cdev、释放设备号等
代码示例
驱动代码hello_driver
#include <linux/module.h>
int hello_init(void)
{
return 0;
}
void hello_exit(void)
{
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
Makefile
ARCH=arm64
CROSS_COMPILE=/home/ps/rk3568_linux_sdk/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-
KERN_DIR=/home/ps/rk3568_linux_sdk/kernel
all:
make -C $(KERN_DIR) M=$(PWD) modules
clean:
make -C $(KERN_DIR) M=$(PWD) clean
rm -rf modules.order Module.symvers
obj-m += hello_drv.o
make完成之后会生成驱动的.ko文件,将该文件传输到rk3568上执行
insmod hello_drv.ko
发现并没有什么输出,是因为我们在驱动中没有执行任何输出信息,执行lsmod之后可以找到该驱动即为成功。

可以使用rmmod hello_drv移除已经加载的驱动
加入打印信息
#include <linux/module.h>
int hello_init(void)
{
printk("init");
return 0;
}
void hello_exit(void)
{
printk("exit");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
加载之后并没有打印出任何信息:

printk函数会将打印信息放在一个内核的buf中,可以通过demsg函数查看

