
🎬 渡水无言 :个人主页渡水无言
❄专栏传送门 :linux专栏
⭐️流水不争先,争的是滔滔不绝
目录
五、[Linux 驱动与软硬件系统的 "朋友圈"](#Linux 驱动与软硬件系统的 “朋友圈”)
前言
之前我们把linux系统移植介绍完了,现在我们正式开始对Linux驱动开发进行介绍,首先我们先与裸机开发进行区别介绍一下。
一、为什么要上操作系统呢?
在嵌入式开发早期,很多设备是 "裸机运行" 的 ------ 没有操作系统,程序直接跑在 CPU 上。这时候的驱动开发更像 "全栈工程师":既要管硬件寄存器操作,又要处理业务逻辑。
比如做一个智能灯泡,用 51 单片机控制 LED:
首先得配置 GPIO 引脚(通用输入输出口)的寄存器,设置为输出模式;
然后写代码控制引脚的高低电平(高电平亮,低电平灭);
还要处理按键输入,检测用户是否按下开关;
甚至得自己实现 "软定时器",让灯泡支持闪烁功能。
这种模式下,驱动和业务逻辑完全绑定,代码复用性极差。如果换一款不同型号的单片机(比如从 STC89C52 换成 STM32),GPIO 寄存器的地址和配置方式可能完全不同,几乎要重写整个驱动。
随着嵌入式设备功能越来越复杂,裸机开发的局限性越来越明显:
硬件资源(CPU、内存)需要高效调度,否则多个任务会 "打架";
不同硬件的驱动代码需要隔离,避免某个驱动崩溃导致整个系统死机;
开发者希望 "一次编写,多处运行",减少重复劳动。
这时候操作系统(比如 Linux)就登场了。操作系统就像一个 "大管家",把驱动从业务逻辑中解放出来,让它们专注做一件事:和硬件 "对话"。
比如在 Linux 系统中,驱动只需要负责:
初始化硬件(比如配置摄像头的 I2C 寄存器);
处理硬件中断(比如收到传感器数据时触发中断);
提供统一的接口给上层应用(比如应用调用read()函数就能获取传感器数据)。
而任务调度、内存管理、文件系统这些 "杂活",都由操作系统内核处理。驱动开发者终于可以 "术业有专攻" 了。
二、裸机驱动开发回顾
裸机驱动开发更加底层一些,直接跟寄存器打交道,虽然一些MCU提供了库,但相比Linux驱动开发还是更加底层了一些。
三、Linux驱动开发思维
1、Linux下驱动开发一般不直接操作寄存器,比较复杂,不现实。
2、根据Linux下的各种驱动框架进行开发。一定要满足框架,也就是Linux下各种驱动框架的掌握。
3、驱动最终表现就是/dev/xxx文件。打开、关闭、读写。
4、Linux内核支持设备树,这个一个.dts文件,此文件描述了板子的设备信息。
四、 L inux驱动开发分类
Linux 设备的 "三大门派"
Linux 把硬件设备分成了三大类,就像武侠小说里的**"少林、武当、峨眉"**,各有各的套路
1、总体框图

2、字符设备驱动(最常见)
特点是数据传输以字节为单位,没有固定的块结构。常见的键盘、鼠标、串口、传感器(如温湿度传感器)都属于这类。
例子:用串口调试助手发送 "Hello",驱动会把数据拆成'H'、'e'、'l'、'l'、'o'逐个发送,接收方也是逐个字节读取。
字符设备的核心是**cdev结构体(字符设备描述符)** ,驱动需要实现file_operations结构体中的函数(比如open、read、write),这些函数就是上层应用和硬件交互的 "桥梁"。
// 典型的字符设备file_operations实现
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.write = led_write,
};
3、块设备驱动
特点是数据传输以块为单位(通常是 512 字节、4KB 等),支持随机访问。最典型的就是硬盘、U 盘、SSD(固态硬盘)。
3、网络设备驱动(玩 "数据包" 的 "通信专家")
网络设备和前两类不同,它不直接提供read/write接口,而是专注于数据包的收发。常见的网卡、Wi-Fi 模块、蓝牙模块都属于这类。
网络设备驱动的核心是net_device结构体,驱动需要实现ndo_start_xmit(发送数据包)和中断处理函数(接收数据包),Linux 内核还提供了netdev子系统,负责数据包的分片、路由、协议栈处理。
注意:一个设备不说是一定只属于某一个类型。比如USB WIFI,SDIO WIFI,属于网络设备驱动,因为他又有USB和SDIO,因此也属于字符设备驱动。
五、Linux 驱动与软硬件系统的 "朋友圈"
要理解 Linux 驱动的位置,可以想象一个 "三层金字塔":
顶层:应用程序(各种软件、比如音乐播放器);
中层:操作系统内核(包括进程调度、内存管理、文件系统);
底层:硬件(CPU、内存、外设)。
驱动就 "卡" 在中层和底层之间:
对上,通过系统调用(如open()、ioctl())向内核提供接口,内核再把这些接口暴露给应用程序;
对下,直接操作硬件寄存器(比如通过ioremap()映射物理地址),处理硬件中断(比如设置中断服务函数 ISR)。
六、区别总结

总结
本期博客介绍了Linux驱动开发与裸机开发的区别。
