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

动手写 Linux 内核模块与驱动:从 hello 到 platform 总线(srvD)

动手写 Linux 内核模块与驱动:从 hello 到 platform 总线(srvD)

本篇基于 srvD(phase6)真实实操。我们写了三个内核模块:第一个模块hellomod、字符设备globalmem、以及一套 platform 总线设备/驱动,亲眼看到insmod/rmmod时的内核日志、/dev下的字符设备节点,以及 platform 总线"撮合"设备与驱动时probe的调用时机。


1. 环境准备

驱动编译依赖当前运行内核的头文件:

$uname-aLinux ecs-bee4-c6af-00046.8.0-106-generic#106-Ubuntu SMP PREEMPT_DYNAMIC x86_64$apt-getinstall-ybuild-essential kmod"linux-headers-$(uname-r)"$ls/lib/modules/$(uname-r)/build/|head-8

每个模块用标准Makefilemake -C $(KDIR) M=$(PWD) modules)调用内核构建系统。

2. 第一个内核模块 hellomod

模块源码里用module_param导出参数whotimesinit里打印加载信息,exit里打印卸载信息。

$cd/root/lab/phase6/hellomod&&makemake-C/lib/modules/6.8.0-106-generic/buildM=/root/lab/phase6/hellomod modules CC[M]/root/lab/phase6/hellomod/hellomod.o LD[M]/root/lab/phase6/hellomod/hellomod.ko $ insmod hellomod.kowho='嵌入式学员'times=2$dmesg|tail-4[9496.886426]hellomod: 模块被加载了!(init)[9496.886431]hellomod: Hello, 嵌入式学员!(1/2)[9496.886433]hellomod: Hello, 嵌入式学员!(2/2)

通过sysfs还能读出模块参数当前值:

$cat/sys/module/hellomod/parameters/who 嵌入式学员 $cat/sys/module/hellomod/parameters/times2

卸载时内核日志显示干净的退出:

$ rmmod hellomod&&dmesg|tail-2[9497.397667]hellomod: 模块被卸载了!(exit)

小提示:编译时有一条 “the compiler differs from the one used to build the kernel” 只是信息性提示(本机 gcc 与构建内核的 gcc 小版本一致),不影响加载。

3. 字符设备驱动 globalmem

globalmem是一个经典字符设备:申请设备号、实现read/writecdev_add后在/dev下生成节点。

$ insmod globalmem.ko&&dmesg|tail-3[9498.481937]globalmem: 申请到设备号major=239minor=0[9498.482029]globalmem: 驱动加载完成, /dev/globalmem 就绪 $ls-l/dev/globalmem crw-------1root root239,0Aug1418:36 /dev/globalmem $grepglobalmem /proc/devices239globalmem

用户态直接当文件读写,验证字符设备的"顺序读写"语义:

$echo'Hello 字符设备驱动! 这是用户态写给内核驱动的数据'>/dev/globalmem $cat/dev/globalmem Hello 字符设备驱动!这是用户态写给内核驱动的数据 $printf'第二次写入覆盖前面的内容'>/dev/globalmem&&cat/dev/globalmem 第二次写入覆盖前面的内容

globalmem内部用一块内核缓冲区,后一次写覆盖前一次——这就是最简字符设备的样子。卸载后/dev/globalmem节点随之消失。

4. platform 总线:设备与驱动如何"撮合"

platform 总线是嵌入式 SoC 上挂设备(GPIO、I2C、SPI 控制器等)的标准模型。我们的platdemo包含platdev.ko(注册一个名叫demo-led的平台设备)和platdrv.ko(注册匹配该设备的驱动)。

场景一:先注册设备,后注册驱动——驱动注册时总线立即撮合,调用probe

$ insmod platdev.ko&&insmod platdrv.ko&&dmesg|tail-5[9500.643310]platdrv:>>>probe 成功!匹配到设备 demo-led[9500.643313]platdrv: 平台数据:name=demo-led-1gpio=66[9500.643315]platdrv:(真实驱动会在这里完成 GPIO 申请/时钟使能等硬件初始化)

场景二:反过来,先注册驱动,后注册设备——设备注册时才触发probe

$ insmod platdrv.ko&&insmod platdev.ko&&dmesg|tail-4[9501.188115]platdrv:>>>probe 成功!匹配到设备 demo-led[9501.188120]platdrv: 平台数据:name=demo-led-1gpio=66

两种顺序都能probe成功,且gpio=66平台数据正确传递——这正是 platform 总线"设备树/板文件描述资源,驱动匹配后取用"的核心机制。卸载时remove被调用,资源释放:

$ rmmod platdrv;rmmod platdev platdrv:<<<remove: 释放设备 demo-led 的资源 platdev: 平台设备 demo-led 已注销

5. 小结

对象关键 API观察点
模块module_init/exitmodule_paramdmesg看加载/卸载日志,/sys/module/<name>/parameters看参数
字符设备register_chrdev/cdev_add/dev下生成节点,/proc/devices列主设备号
platformplatform_device/platform_driverprobe设备与驱动谁后到,probe就在谁注册时触发

写驱动的乐趣在于:你写的代码跑在内核态,一个insmod就能让dmesg吐出你自己的日志,/dev下多出一个你定义的设备


系列收官

四台服务器的实验到此全部跑通并验证:

  • srvAShell/文件IO:多文件 Makefile、静态/动态库、fork+execvp迷你 Shell ✅
  • srvB进程/线程/IPC:管道/FIFO/消息队列、共享内存竞态、互斥锁/条件变量、select/epoll
  • srvC交叉编译/QEMU:ARM 与 x86 双启动,踩平软链接、BINFMT、内核架构三道坑 ✅
  • srvD内核模块/驱动:hellomod、globalmem 字符设备、platform 总线 probe ✅

所有命令输出均来自真实远程实操记录(transcripts/*.log),可复现、可审计。

http://www.jsqmd.com/news/1400354/

相关文章:

  • InvesTool 部署与配置实战:四关点亮一套投资分析工具,附避坑清单
  • 跨省救护车出租怎么预约 北京长途转院车辆收费标准与卧床患者转运指南 - 产品推荐官
  • 旧款 Mac 免费升级 macOS 实测手记:OpenCore Legacy Patcher 让我那台“退休“电脑重新上岗
  • OpenMontage零密钥入门:把AI编码助手变成你的免费视频制作工作室
  • 终极API管理平台DreamFactory完整上手指南:5分钟把数据库变成REST API
  • Vue Query Builder高级技巧:提升查询构建体验的7个方法
  • Canta主题开发指南:如何为GTK应用贡献自定义样式
  • 终极内存管理方案:arena1/arena单文件C库完全指南
  • Taste-Skill 实用指南:让 AI 界面设计彻底告别模板化的终极方案
  • c语言中函数传递二级指针,修改指针指向
  • 如何使用Receptionist实现Swift分布式集群服务发现
  • DeepStream视频分割 pipeline:基于Portrait-Segmentation的多摄像头实时处理方案
  • Unity许可证验证绕过完整指南:用UniHacker快速解锁全平台开发
  • ncmdump 快速上手:3 关解锁网易云 NCM 文件转换
  • CDDIS 天顶总延迟(ZTD)数据下载教程
  • ComfyUI中文工作流快速上手指南:零基础玩转AI绘图不再难
  • 群星全DLC免费解锁实操:Stellaris DLC Unlocker 在 Windows 和 Linux 上的完整记录
  • 如何用Nail-Qwen3.6-35B-A3B-GGUF实现多轮对话?解锁262k tokens超长上下文能力
  • 掌握tumblr.js核心功能:用户信息、博客数据与内容发布全攻略
  • COSMO-RS 实操:从量子力学到热力学性质的“无参”预测之路
  • combo实战:5分钟快速上手模型组合,让你的分类器性能飙升
  • Ghidra逆向工程框架完全指南:从安装到实战,把“看不懂的二进制“变成“读得懂的代码“
  • 从Vim新手到高效开发者:一年Neovim实战配置与效率提升指南
  • C++输入输出、字符串分割
  • SOFARegistry集群部署教程:Docker Compose与Kubernetes方案
  • 30分钟上手Huginn:零基础打造自己的自动化工作流
  • PhotoGIMP实操指南:把免费GIMP 3改造成熟悉的Photoshop界面,告别高价订阅
  • 深入理解RAT-retrieval-augmented-thinking架构:ModelChain类与双客户端设计详解
  • 杭州黄金旧饰准备出手,聊聊老凤祥饰品回收相关注意事项 - 日常前沿快讯
  • 32B视觉语言模型如何塞进32GB显卡?RTX 5090上的INT8量化部署与显存优化全记录