AI助攻,用Claude Code复活25年老内核驱动
你能想象吗?一段 25 年前的 Linux 内核驱动,在现代系统上几乎不可能运行——但一位工程师用了两个晚上借助 AI 助手 Claude Code,让它重获新生。这个驱动曾经服务于老旧磁带设备,如今经过现代化改造,不仅可以在最新 Linux 上编译,还能与真实硬件顺利通信。可谓 AI 立大功!
背景
简单做一下背景介绍,我业余时间的兴趣爱好之一是帮助人们从旧磁带盒中恢复数据,比如 QIC-80 磁带。这种磁带在 1990 年代相当流行,是个人、小型企业、BBS 运营者等常用的备份产品。我对磁带介质有一种特别的情感;手里捏着这些磁带的触感,总能让整个过程变得非常愉快,尽管 QIC 磁带以设计缺陷多而臭名昭著。不过,只要经过仔细检查和适当翻新,这些磁带上的数据即便多年之后仍然可以完全恢复。
每次有人送来 QIC-80 磁带让我恢复数据时,我都会启动我一台老旧 PC 工作站,这台电脑上连着对应的磁带驱动器,然后启动一个非常老的 Linux 版本(搭载的是 CentOS 3.5)。之所以用这么老的系统,是因为只有这个系统才能用 ftape 驱动,这是与磁带驱动器通信所必需的内核驱动,可以把磁带上的二进制内容完整读取出来。
这种磁带驱动器是接在主板的软驱控制器上的。这其实是个聪明的“省钱招”:本来高端磁带通常要用单独的 SCSI 接口,但这样你就可以直接用已经有的软驱接口,不用额外买硬件。而且它还能和现有的软驱共用同一条排线!当然,代价是速度被软驱控制器限制了,大概只有 500 Kbps(注意,是千比特,不是千字节)。
另外一个麻烦是,通过软驱控制器和磁带驱动器通信的协议非常乱、非标准,而且支持也不好。这完全是一个“黑客式”的做法:主板 BIOS 根本不知道磁带驱动器的存在,所有控制都得靠用户端的软件自己搞定,包括操作硬件 I/O 端口、时序、中断等,让软驱控制器“乖乖”把命令发给磁带驱动器。
当年只有少数专有工具能在 MS-DOS 和 Windows 3.x/9x 下操作这些磁带驱动器,而在 Linux 上,开源实现几乎只有 ftape 这一种。当然,用原来的 DOS/Windows 工具也能读取磁带,但 ftape 的优势在于它能直接读取磁带的“原始”二进制内容,不管最初是哪个专有软件写入的。这也是我更喜欢用 ftape 来导出磁带内容的原因:先把二进制完整读出来,再去处理那些专有的逻辑格式,最后再提取出文件。
问题是,ftape 驱动从大约 2000 年起就不再维护了,很快也从 Linux 内核中被移除了。这就是为什么每次处理这种磁带时,我都不得不运行一个非常老的 Linux 版本。如果 ftape 能在现代 Linux 发行版上运行,那就太好了——既能保留原有功能,又能享受现代系统的各种便利。
向 Claude Code 发问
几周前,我突然想到向 Claude Code 提出一个简单的请求:
这个仓库是一个 Linux 内核驱动,用于与主板上连接到软盘控制器(FDC)的老式磁带驱动器通信。不幸的是,这个驱动已经很久没有维护了,而且只能在 2.4 版本的内核下编译。我希望将其现代化,使其能够在最新版本的内核上构建。
Claude 回应说,它可以帮我现代化这个用于老式磁带驱动器的 Linux 内核驱动。这是一项相当庞大的任务,需要更新代码以兼容现代内核的 API 和约定。
经过几轮所谓的“组合优化”以及 Claude 自称的其他操作后,我突然得到了一个可以编译且无错误的内核驱动。
这是因为 Claude 能够读取编译器输出,并将其反馈给自身,直到编译正确为止。
从 2.4 内核到 6.8 内核的漫长时间里,有大量内核函数和结构已被弃用或替换。
令人惊讶的是,Claude 找到了所有过时的部分,并用正确的现代等效代码替换了它们,只需要对部分代码做少量手动调整(稍后会详细说明)。
不过,此时的内核驱动仍然需要作为完整内核树的一部分来编译,而我只是希望它能成为一个独立的可加载内核模块。于是我问:
有没有办法只在原地编译这个模块,而不用把它复制到内核源码树里?
Claude 回答:可以!你可以在内核源码树外编译内核模块,无需复制到内核源代码中。我来为 ftape 驱动创建一个独立的构建系统吧。
……结果它真的做到了,而且无需进一步提示。
在这个阶段结束时,我得到了一个可加载的内核模块(.ko 文件),可以尝试在实际硬件上使用。毫不意外,这个模块还没有完全起“作用”——它能加载,但无法正确与磁带驱动通信。
不过我没有放弃。
从这一步开始,由于加载/卸载内核模块需要 sudo 权限,我不能再让 Claude 自行“迭代”这种敏感操作。
幸运的是,ftape 驱动里已经有大量日志信息(printk() 调用会打印到 dmesg),于是我自己加载了模块,并将 dmesg 输出手动粘贴给 Claude,让它与我之前保存的、成功读取磁带时的“已知良好” dmesg 日志进行对比。经过几轮这样的迭代,Claude 找出了阻止模块与硬件通信的剩余问题。
完美!这个模块有一些可以设置的参数。问题在于,如果不进行配置,所有的基地址都会默认为 -1,而在配置函数里,这个值会被转换成 0xffff,导致检测失败。
“No such device or address”(ENXIO)错误的原因是 ftape-internal 模块没有用正确的 I/O 端口基地址配置软驱控制器。问题出在 fdc-internal.c的第 735–737 行:如果 fdc->sra == 0xffff,函数就会返回 -ENXIO。由于没有提供任何配置,所有值都默认为 -1,也就变成了 0xffff……
最终,我得到了一个可以做到以下操作的内核模块:
a) 能加载;
b) 能检测到磁带驱动器;
c) 能导出测试磁带的内容!
心得体会
使用 ftape 驱动在现代内核上工作——曾经看似完全不可能的任务——居然在两个晚上就完成了。
GitHub 地址:https://github.com/dbrant/ftape
需要强调的是,我自己对内核模块有一些基础经验,对 C 语言也比较熟悉,所以我不想过度夸大 Claude 在这个场景中的作用。
也就是说,这并不是三条指令就让 Claude 输出了一个可用的内核模块,而是经历了多轮来回交流,以及几次手动修正代码。如果没有对内核模块内部机制的基本理解,这种现代化工作根本无法完成。
这让我对使用此类编码助手有了一些心得:
1. 真正把它当作协作伙伴
与 Claude Code 互动的感觉就像是在和另一位工程师合作。有人把它比作“初级工程师”,我觉得大体准确:它会尽力按照你的指示去做,积极配合,有时自信过头,但犯错时会快速道歉,并称你“绝对正确”。
因此,人类仍然需要提供护栏、做产品决策、遵循架构规范,并尽早发现潜在问题。
2. 尽量具体,确保使用领域相关关键词
我不敢说自己突然成了 prompt 工程师,但我发现最有效的提示是:先清楚描述功能的“语言框架”,再指出框架中的空缺,让模型去补充。
3. 培养对适合交给模型完成任务类型的直觉
这些大模型不是万能的,如果让它做不擅长的事情,你会沮丧,并可能在它展现能力前就放弃它。在这点上,了解 LLM 的工作方式很有帮助,可以让你更好判断它的优势和局限。
4. 把它作为自己能力的倍增器
理论上,我完全可以自己完成这次现代化工作,但那意味着得学习 25 年前的内核开发方法,要花几周时间查阅今天已经没用的文档。相反,我用几天时间和助手交流,让它解释每一步操作。
当然,我会验证和测试它所做的修改,同时也学到了很多实际有用的东西,比如现代内核规范、x86 架构细节,以及一些命令行操作技巧,都将成为我的常用工具。
5. 用它快速上手新框架
我本身不是内核开发者,但这次经历激发了我对内核级工作的兴趣,事实证明内核开发并没有想象中那么难。在另一场“vibe coding”中,我甚至没用过 Flutter 就做出了一个 Flutter 应用。如果你和我一样,喜欢边做边学,这些工具可以大幅加快你学习新框架的速度,让你有更多精力进行高层次架构思考。
总结
总而言之,现在我很高兴地说,ftape 依然活着!在距其最后一次官方发布已 25 年之后,它终于可以在现代 Linux 上编译和使用。我还在进行一些进一步的调整和新功能添加,但已经验证它能正常工作,无论是我的软驱磁带驱动器,还是它支持的并口驱动器。
物理设备设置看起来几乎没变,但操作系统现在是 Xubuntu 24.04,而不是以前的 CentOS 3.5!
原文链接:https://dmitrybrant.com/2025/09/07/using-claude-code-to-modernize-a-25-year-old-kernel-driver
本文来自微信公众号“CSDN”,作者:Dmitry Brant,36氪经授权发布。