You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux块驱动如何确保卸载前所有I/O操作已完成?

Linux块设备驱动资源释放的同步机制

Linux块设备驱动会分配struct gendisk及相关元数据,并提供队列或submit_bio函数的实现,以处理来自操作系统的I/O请求。当磁盘被移除时,通常会执行以下流程:

del_gendisk(brd->brd_disk);
blk_cleanup_disk(brd->brd_disk);
...
kfree(brd);

以ramdisk驱动的brd_cleanup例程为例,核心的资源释放同步逻辑如下:

一、确保submit_bio/bio_end_io执行完成的机制

驱动依赖块层的引用计数和队列冻结+等待机制避免野指针问题:

  • struct gendisk内部维护disk->openers引用计数,跟踪设备的打开句柄;每个bio结构体也自带引用计数,保证I/O操作完成前不会被提前释放。
  • del_gendisk调用时,首先通过blk_queue_freeze冻结设备请求队列,彻底禁止新I/O提交;随后调用blk_wait_queue_empty等待队列中所有已提交的请求处理完成,确保队列无残留任务。
  • 对于直接使用submit_bio的无队列驱动,需自行实现同步逻辑:清理前先停止接收新I/O,通过自定义引用计数(submit_bio时递增,bio_end_io时递减)等待计数归0,确认所有回调执行完毕后再释放资源。

二、del_gendisk的深层同步逻辑

del_gendisk的作用不止于阻止新请求:
它内部会调用disk_release_partitions和disk_put_partitions清理分区资源,同时触发驱动的release回调。核心是等待gendisk的引用计数归0,以及disk->openers计数归0——这意味着所有打开的设备文件句柄都已关闭,不会有新的submit_bio调用发起。
后续的blk_cleanup_disk会进一步清理队列的内存和资源,确保没有残留的回调函数能访问已释放的结构体。

三、等待文件句柄关闭的代码位置

等待设备/分区所有打开句柄关闭的逻辑集中在块层源码block/disk.c的del_gendisk和disk_release函数中:

  • del_gendisk调用disk_put递减gendisk的引用计数,当计数归0时触发disk_release。
  • disk_release会检查disk->openers计数,若不为0则调用wait_event进入阻塞,直到disk->openers变为0。
  • 当用户空间关闭设备文件句柄时,会触发驱动的release回调(如ramdisk的brd_release),该回调递减disk->openers计数并唤醒等待的清理线程。

内容的提问来源于stack exchange,提问作者Reinstate Monica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:53:10