我正在为 linux 编写块设备驱动程序。支持不安全的移除(如 USB 拔出)至关重要。换句话说,我希望能够关闭块设备而不会造成内存泄漏/崩溃,即使应用程序持有打开的文件或在我的设备上执行 IO,或者如果它与文件系统一起挂载。当然,不安全的删除可能会破坏存储在设备上的数据,但这是客户愿意接受的。
这是我完成的基本步骤:
- 在不安全删除时,块设备会产生一个僵尸,它将自动使所有新的 IO 请求、ioctl 等失败。僵尸替代 make_request 函数并更改其他函数指针,因此内核不需要原始块设备。
- 块设备等待现在正在运行的所有 IO(并使用我的内部资源)完成
- 它确实 del_gendisk(); 但是,这并没有真正释放内核资源,因为它们仍在使用中。
- 块设备释放自己。
- 僵尸跟踪块设备上 opens() 和 close() 的数量,当最后一个 close() 发生时,它会自动释放() 本身
- 结果 - 我没有泄漏块设备、请求队列、生成磁盘等。
然而,这是一个非常困难的机制,需要大量代码并且极易出现竞争条件。我仍在为极端情况、io 的 per_cpu 计数和偶尔的崩溃而苦苦挣扎
我的问题:内核中是否有一种机制可以做到这一点?我搜索了手册、文献和无数块设备驱动程序、ram 磁盘和 USB 驱动程序的源代码示例,但找不到解决方案。我敢肯定,我不是第一个遇到这个问题的人。
编辑: 我从 Dave S 下面的答案中了解到热插拔机制,但这对我没有帮助。我需要一个如何安全关闭驱动程序而不是如何通知内核驱动程序已关闭的解决方案。
一个问题的示例: blk_queue_make_request() 注册了一个函数,我的块设备通过该函数为 IO 提供服务。在该函数中,我增加 per_cpu 计数器以了解每个 cpu 正在运行的 IO 数量。然而,有一个函数被调用但计数器还没有增加的竞争条件,所以我的设备认为有 0 个 IO,释放资源,然后 IO 来了并使系统崩溃。据我了解,Hotplug 不会帮助我解决这个问题