视频资源:

https://www.bilibili.com/video/BV18SE26cEjn?spm_id_from=333.788.videopod.sections&vd_source=92b7efa4daa5bb4fdcdc9f2db97c307b&p=5

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 代码略过

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐