Linux驱动开发(2)——驱动编程

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)

  • 功能:解除映射
相关推荐
2601_960567969 小时前
电商套图自动化效率的工程量化分析——从逐张生成到批量套图的架构演进
运维·架构·自动化
吳所畏惧9 小时前
宝塔面板Redis密码修改指南:SSH命令修改 vs 面板UI界面修改,哪个更靠谱?
运维·服务器·数据库·redis·缓存·ssh
DFT计算杂谈9 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
HiDev_10 小时前
【非标自动化】2、认识元器件(确定目标)
运维·自动化
Zhang~Ling11 小时前
从 fopen 到 struct file:从零开始拆解 Linux 文件 I/O
linux·运维·服务器
DeeplyMind11 小时前
Linux 深入 per-VMA lock:Linux 缺页路径如何摆脱 mmap_lock
linux·per-vma lock
爱写代码的森11 小时前
蒙三方库 | harmony-utils之FileUtil文件重命名与属性查询详解
linux·运维·服务器·华为·harmonyos·鸿蒙·huawei
中微极客11 小时前
2026主流AI Agent框架技术选型与性能对比
运维·网络·人工智能
久曲健的测试窝11 小时前
智能座舱自动化测试落地方案:数字仿真搭配实车实测,解决用例运维与场景失真难题
运维
XMAIPC_Robot12 小时前
软硬协同实时控制|RK3588业务调度+FPGA硬件时序,ethercat实现半导体设备微秒级响应(125us)
linux·arm开发·人工智能·fpga开发