当前位置: 首页 > news >正文

linux实现设备驱动-字符型设备驱动和杂项设备驱动

linux驱动分类

(1)字符设备驱动 (Character Device Driver):

  • 特点: 数据按字节流 (byte stream) 形式访问,即数据访问有严格的顺序性。
  • 数据传输为字节流形式,顺序读写,不带缓存,无固定块大小。
  • 通常采用中断驱动或轮询方式处理 I/O 请求,响应实时性较强。
  • 设备节点通常位于 /dev 目录下,通过文件描述符进行操作。
  • 示例: LED灯、按键、串口(UART)等,输入输出设备(鼠标、键盘、屏幕、摄像头)
  • 管理方式: 通过设备号 (Device Number) 管理。

(2)块设备驱动 (Block Device Driver):

  • 特点: 数据以固定大小的块 (block)(大小为512k) 为单位进行访问,带缓存,通常用于存储设备。
  • 示例: 硬盘、SSD、U盘等。访问时可以随机读取任意位置的数据,不受顺序限制。
  • 管理方式: 通过设备号 (Device Number) 管理。

(3)网络设备驱动 (Network Device Driver):

  • 特点: 集成复杂的协议栈 (Protocol Stack),如TCP/IP、UDP等。
  • 示例: 网卡。
  • 管理方式: 按照名字 (Name) 管理,如 ens33

一、字符型设备驱动:

1.字符型设备驱动不自动生成设备节点(‘myled)
  • 手动创建设备节点 :(在开发板中创建)

①前提条件:开发板已运行 Linux 内核,且需知道目标设备的主设备号次设备号(可通过内核日志dmesg或驱动代码获取)。

③验证与权限设置:

  • 自动生成设备节点 class_create() device_create()

在init函数中调用class_createdevice_create接口,结合sysfs自动生成设备节点。

2.设备号 (Device Number):设备号是内核用于管理驱动设备的一个32位无符号整数 (u32)。它被划分为两部分:

  • 主设备号 (Major Number): 高12位,用于区分设备类型。例如,所有LED灯使用同一个主设备号,所有按键使用另一个主设备号。
  • 次设备号 (Minor Number): 低20位,用于区分同一类型设备中的不同个体。例如,4个LED灯分别使用不同的次设备号(0, 1, 2, 3)。

(1)嵌入式 Linux 设备驱动调用流程示意图分析:

1.用户应用层(user app)

  • 应用程序通过open(led)fopen(led)发起设备操作请求,依赖libc库将请求转换为系统调用。

2. 根文件系统层(rootfs)

  • 设备节点(如led_1key_2uart_3)存在于 /dev 目录,是用户层与驱动层的交互入口。

3. 系统调用与驱动管理层

  • 系统调用syscall_open(led)将用户请求传入内核,内核通过设备号匹配对应的驱动(如 LED 驱动匹配设备号 1)。
  • 内核驱动管理模块(含open操作与驱动索引 “1、2、3”)负责分发请求到具体驱动。

4. 设备驱动层

  • 包含LED_DRVKEY_DRVUART_DRV三类字符设备驱动,是硬件操作的直接实现层,完成如 LED 点亮、按键检测、串口数据收发等具体功能。

5. 硬件设备层

  • 对应实际硬件(LED、KEY、UART),驱动通过硬件寄存器、中断等机制完成物理层操作。

(2)字符型设备驱动开发流程:

将驱动程序写在内核顶层目录/driver/char目录下:

1.Linux 内核模块的 “标准注册接口”:

确保驱动能被内核正确加载和卸载,是字符设备驱动(如示例中的 LED 驱动)模块化管理的关键实现。

2.确定设备号,设备名称:

为驱动程序分配一个唯一的设备号。通常,主设备号从较大的数字开始分配(如255),因为较小的号码已被系统占用。

// 定义主设备号、次设备号和设备名称
#define MAJOR_NUM 248 // 主设备号
#define MINOR_NUM 0   // 次设备号
#define DEV_NAME "led1" // 设备名称

3.定义并实现操作方法 (file_operations结构体)

定义一个 struct file_operations 结构体(驱动层操作函数集合),其中包含指向驱动程序具体操作函数的指针,如 openreadwriterelease (close)。

// 声明操作函数原型
static int open(struct inode *node, struct file *file);
static ssize_t read(struct file *file, char __user *buf, size_t len, loff_t *loff);
static ssize_t write(struct file *file, const char __user *buf, size_t len, loff_t *loff);
static int close(struct inode *node, struct file *file);// 定义并初始化 file_operations 结构体
static struct file_operations fops = {.owner = THIS_MODULE, // 指向当前模块,用于防止模块在被引用时被卸载.open = open,         // 绑定 open 函数.read = read,         // 绑定 read 函数.write = write,       // 绑定 write 函数.release = close      // 绑定 release (close) 函数
};

4. 定义一个cdev结构体:

描述字符型设备相关的信息(设备号、设备名称...),绑定设备号与操作方法

static dev_t devno;          // 设备号变量
static struct cdev cdev;     // cdev 结构体实例// 在模块初始化函数中执行绑定
static int __init led1_init(void)
{int ret = 0;// 1. 使用 MKDEV 宏组合主、次设备号devno = MKDEV(MAJOR_NUM, MINOR_NUM);// 2. 初始化 cdev 结构体,关联操作方法cdev_init(&cdev, &fops);// 3. 将 cdev 添加到内核中,指定设备号和数量ret = cdev_add(&cdev, devno, 1);if(ret < 0)goto err_cdev_add; // 错误处理...
}

5.实现对应init函数(向内核注册驱动入口函数 insmod xxx.ko)

注册字符型设备

  • 静态注册:register_chrdev_region(使用预先定义的 MAJOR_NUM 和 MINOR_NUM 向内核申请设备号范围)
  • 动态注册:alloc_chrdev_region(如果静态省请未成功,系统自动分配一个未被占用的设备号)

②初始化cdev结构体:

③将cdev结构体添加到系统

④自动生成设备节点:

6.驱动层实现硬件交互逻辑read/write等接口中,通过寄存器操作、中断处理或 DMA 完成硬件数据读写。

7.注销与清理:实现对应exit函数(驱动注销函数 rmmod xxx

①注销字符型设备unregister_chrdev_region();

注销cdev结构体 :cdev_del();

删除类和设备节点 class_destroy() ;device_destroy()

④释放硬件资源 :iounmap();

8.应用程序调用流程

用户程序通过标准库函数(如 openreadwrite)发起系统调用,最终由内核调用驱动程序中对应的函数。

// 用户空间应用程序 (led1_app.c)
int main(int argc, const char *argv[])
{int fd = open("/dev/led1", O_RDWR); // 调用 open 系统调用if(fd < 0) { /* 错误处理 */ }write(fd, "ledon", 5);  // 调用 write 系统调用write(fd, "ledoff", 6); // 调用 write 系统调用close(fd); // 调用 close 系统调用return 0;
}

(3)最后通过动态编译的方法将新的驱动模块加载到开发板中

二、杂项设备驱动:

特点:

  • 无需手动分配主设备号(固定使用主设备号10),只需指定次设备号和设备名称。
  • 自动生成设备节点
  • 开发高效:内核通过封装了杂项设备的file_operations默认实现,开发者只需关注具体硬件操作逻辑,减少代码量。
  • 适合快速开发简单字符设备(如 LED、按键等)。

(1)杂项设备驱动开发流程:

1.定义杂项设备结构体:

初始化 struct miscdevice,指定设备名称(name)、次设备号(minor,可设为 MISC_DYNAMIC_MINOR 动态分配)、操作接口(fops 关联 file_operations)。

static struct miscdevice my_miscdev = {.minor = MISC_DYNAMIC_MINOR, // 动态分配次设备号.name = "my_misc",           // 设备节点名 /dev/my_misc.fops = &my_fops,            // 关联操作函数集
};

2.实现 file_operations 操作集:

封装设备核心操作(open/read/write/release 等),与普通字符设备驱动逻辑一致。

static struct file_operations my_fops = {.owner = THIS_MODULE,.open = my_open,.read = my_read,.write = my_write,
};

3.模块初始化与注册在 module_init 函数中调用 misc_init 注册函数:

①注册杂项设备:misc_register();

static int __init my_misc_init(void) {return misc_register(&my_miscdev); // 注册成功自动创建设备节点
}
module_init(my_misc_init);

硬件资源初始化 :request_irq();

4.模块退出与注销:在 module_exit 函数中调用 misc_exit释放资源:

① 注销杂项设备: misc_unregister()
static void __exit my_misc_exit(void) {misc_deregister(&my_miscdev);
}
module_exit(my_misc_exit);
② 释放硬件资源: free_irq();

5.完成open read write release函数


后续操作同字符型驱动

(3)字符型设备驱动和杂项设备驱动的区别

对比维度字符型设备驱动杂项设备驱动
设备号管理需手动分配主设备号(静态register_chrdev_region或动态alloc_chrdev_region),次设备号按需定义主设备号固定为 10,次设备号可动态分配(MISC_DYNAMIC_MINOR)或手动指定
注册接口通过cdev_init+cdev_add注册,需手动关联file_operations通过misc_register注册,内核封装部分逻辑,只需初始化struct miscdevice
开发复杂度较高,需处理设备号、类注册、节点创建等全流程较低,内核简化注册流程,自动创建设备节点
适用场景复杂字符设备(串口、音频、传感器等,需精细设备号管理)简单字符设备(LED、按键、小型传感器等,追求开发效率)
设备节点创建需手动mknod或通过class_create+device_create自动创建注册后内核自动在/dev目录创建设备节点
灵活性可完全自定义设备号和操作逻辑,灵活性高受限于主设备号 10,功能相对单一

编写驱动→配置 Makefile,Kconfig→动态编译生成.ko→加载测试→(可选)集成到内核

http://www.dtcms.com/a/558972.html

相关文章:

  • 大英做网站wordpress主题选项单选框
  • 分类信息网站 建议 建设百度搜索推广采取
  • 招标网站建设招标方案建设我们的网站 教案
  • 安徽海川建设公司网站企业所得税计算公式2022
  • apache 配置网站做网站的哪里好
  • 广州wap网站建设广州在线网站制作公司
  • 做网站的策划方案汽车最好网站建设
  • Spring AI——入门介绍
  • 奢侈品网站怎么做tuig优化wordpress虚拟3d网站
  • 手机网站怎么做淘宝客个人网页制作的流程和步骤
  • 甘肃城乡建设局安全质量网站上海雍熙网站建设
  • 网站建设地域名app是什么意思
  • 云南品牌网站开发网站建设合同的注意点
  • 企业网站建设公司电话西安张家港做网站优化排名
  • 临高网站建设网络平台推广宣传方案
  • php mysql网站开发项目式教程怎么免费建设个人博客网站
  • 深圳移动网站建设公司价格贷款公司通过做网站来给予平台贷款
  • 数据结构算法学习day3——二分查找
  • 专业电商网站海口网站开发师招聘
  • 宁波网站建设有限公司导购网站开发
  • 什么网站做海报赚钱盐城网站建设设计
  • 网站免费正能量破解版网站开发工资咋样
  • 江苏公司响应式网站建设报价网页是啥
  • AlReader,一款多格式电子书阅读器
  • 如何推广企业官方网站内容瑞安做网站建设
  • 怎样做网站首页网站域名注册申请
  • 利用tex调用csv文件中的数据
  • 硅云网站建设视频wordpress观点
  • 花都建设网站保定厂家推荐信息流推广
  • Python 虚拟环境和包管理