1.内核输出接口
Linux 内核日志划分1~7 优先级等级,只有日志自身优先级数值低于console_loglevel(控制台日志等级阈值)时,内核打印信息才会输出到串口终端。
printk: 内核最基础的打印接口,默认使用 4 级日志优先级。
**pr 函数族:**带日志等级分类的标准化打印接口,不同函数绑定固定优先级。
- **pr_info():**固定为6 级普通提示日志,多用于打印设备初始化、驱动加载、状态提示等常规非关键信息。
2.设备驱动
驱动方式:字符设备驱动、块设备驱动、网络设备驱动
2.1设备号:主设备号+次设备号
- 主设备号:表示设备类型
- 次设备号:该类型的第几个设备
2.2 自定义设备:cdev结构设备
cdev结构:设备号+对设备操作的方法
cs
struct cdev{
struct module *owner;//引用计数,计数使用cdev的设备个数
const struct file_operations *ops;//对设备操作的方法
dev_t dev;//该类型中第一个设备号
}
1).自定义设备
函数 :struct cdev *cdev_alloc(void);
- 功能:申请cdev结构
- 返回值:cdev结构体
函数 :int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name);
- 功能:申请设备号(内核自动分配主设备号)
- 参数:@dev --- 自动分配的主设备号,@baseminor --- 次设备号始编号0,@count --- 申请个数,@name --- 设备类型名称
函数 :int cdev_add(struct cdev *p, dev_t dev, unsigned count);
- 功能:加入到cdev链表中
- 参数:@p --- cdev结构体,@dev --- 主设备号,@count --- 次设备个数
函数 :class_create(owner, name);
- 功能:创建设备类型对应的文件系统目录
- 参数:@owner --- 引入计数,@name --- 设备类型名
函数 :struct device *device_create(struct class *class,struct device *parent,dev_t devt,void *drvdata,const char *fmt,...);
- 功能:创建类型对应的设备
- 参数:@class --- 设备所属的类,@parent --- 父设备,@devt --- 设备号,@@fmt --- 带格式的设备名
| 函数 | 功能 |
|---|---|
| cdev_del(struct cdev *p) | 释放cdev结构体 |
| unregister_chrdev_region(dev_t from, unsigned count); | 释放设备号 |
| class_destroy(struct class *cls); | 销毁设备类 |
| device_destroy(struct class *class, dev_t devt); | 销毁设备 |
2).自定义设备类型的操作方法
cs
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = open,
.release = close,
.read = read,
.write = write,
};
//内核层对应接口
int (*open)(struct inode*,struct file*);
int (*close)(struct inode*,struct file*);
ssize_t (*read)(struct file*,char __user*, size_t, loft_t*);
ssize_t (*write)(struct file*,char __user*, size_t, loft_t*);
函数 :unsigner long copy_from_user(void *to,const void __user *from,unsigned long n);
- 功能:内核层从用户层拷贝数据(write)
- 参数:@to --- 内核层数据的缓存区,from --- 用户层,@n --- 数据长度
函数 :unsigner long copy_to_user(void *to,const void __user *from,unsigned long n);
- 功能:用户层从内核层拷贝数据(read)
- 参数:@to --- 用户层,from --- 内核层数据,@n --- 数据长度
2.3 MMU内存映射
函数 :void __iomem *ioremap(phys_addr_t offset, size_t size);
- 功能:虚拟地址和实际物理地址的映射
- 参数:@offset --- 实际的寄存器地址,@size --- 地址大小(4byte)
函数 : void writel(u32 b, volatile void __iomem *addr)
- 功能:Linux 内核读取寄存器
- 参数:@b --- 要写入的值,@addr --- 虚拟地址
函数 :u32 readl(const volatile void __iomem *addr)
- 功能:Linux 内核写入寄存器,readl用于32位寄存器
函数 :void iounmap(const void __iomem *addr)
- 功能:解除映射