Johannes 《Linux内核模块与设备驱动开发:编写Linux驱动程序》(5) hello_cdev (6) log_level
视频资源:
lesson5 字符设备 hello_cdev,说明了一个简易字符设备驱动。
lesson6 printk 的各种报告等级。lesson6 太水了,就是printk的各种格式,可以跳过去不看,真用的时候百度也是可以的。
hello_cdev.c
#include <linux/module.h>
#include <linux/init.h>
/*
* file_operations ,设备文件的常用读写操作
*/
#include <linux/fs.h>
//主设备号
static int major;
//重写 <linux/fs.h> 中的 read
static ssize_t my_read(struct file *f, char __user *u, size_t l, loff_t *o)
{
pr_info("hello_cdev - Read is called\n");
return 0;
}
//定义 .read
static struct file_operations fops = {
.read = my_read
};
//初始化
static int __init my_init(void)
{
//register_chrdev, 注册hello_cdev 字符设备,这里动态分派,所以第一个参数是0
major = register_chrdev(0, "hello_cdev", &fops);
if (major < 0) {
/*
pr_err ,内核封装的printk(),
#define pr_err(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
*/
pr_err("hello_cdev - Error registering chrdev\n");
return major;
}
// pr_info 也是printk() 的封装
pr_info("hello_cdev - Major Device Number: %d\n", major);
return 0;
}
//移除 模块 ,移除hello_cdev 设备
static void __exit my_exit(void)
{
unregister_chrdev(major, "hello_cdev");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes 4Linux");
MODULE_DESCRIPTION("A sample driver for registering a character device");
pr_err/pr_info 都是linux 给printk 函数做的封装,表明消息的等级。这个也是lesson6 中内容
register_chrdev(0,"hello_cdev",&fops); 注册字符设备hello_cdev,设备号可以固定写,也可以系统自动配置,这里选择了0,最后这个字符设备的读写操作是fops.
fops是结构 file_operations,这个结构在<linux/fs.h>头文件中定义,所以例子要添加了第三个头文件<linux/fs.h>, 重新定义的file_operations 里面只有读my_read()。fs.h中的读是ssize_t (*read) (struct file *, char __user *, size_t, loff_t *),例子里面是my_read(struct file *f, char __user *u, size_t l, loff_t *o),可见参数是可以重写的;
学过stme32单片机的,可以理解为<linux/fs.h>中这个函数是_weak ,hello_cdev.c重写这个函数重新定义了它。
lesson6 代码略过
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)