如何在Linux

时间:2017-02-27 07:54:31

标签: c linux linux-device-driver network-block-device

我正在为linux编写块设备驱动程序。 支持不安全删除(如usb unplug)至关重要。换句话说,我希望能够关闭块设备而不会造成内存泄漏/崩溃,即使应用程序在我的设备上保存打开的文件或执行IO,或者它是使用文件系统安装的。 当然,不安全的删除可能会破坏存储在设备上的数据,但这是客户愿意接受的。

以下是我完成的基本步骤:

  1. 在不安全删除时,阻止设备会生成一个僵尸,它将自动失败所有新的IO请求,ioctls等。僵尸替换make_request函数并更改其他函数指针,因此内核不需要原始块设备。
  2. 阻止设备等待所有正在运行的IO(并使用我的内部资源)完成
  3. 它确实是del_gendisk();但是这并没有真正释放内核资源,因为它们仍在使用。
  4. 阻止设备释放自己。
  5. 僵尸跟踪块设备上的opens()和close()的数量,当最后close()发生时,它自动free()本身
    1. 结果 - 我没有泄漏阻止设备,请求队列,生成磁盘等
  6. 然而,这是一个非常困难的机制,需要大量的代码,并且非常容易出现竞争条件。我仍在努力应对角落案件,perocpu计算io和偶尔的崩溃

    我的问题:内核中是否有机制可以做到这一点?我搜索了块设备驱动程序,ram磁盘和USB驱动程序的手册,文献和无数源代码示例,但找不到解决方案。我确信,我不是第一个遇到这个问题的人。

    编辑: 我从下面的答案中了解到Dave S关于热插拔机制,但它对我没有帮助。我需要一个如何安全地关闭驱动程序而不是如何通知内核驱动程序关闭的解决方案。

    一个问题的示例: blk_queue_make_request()注册一个函数,我的块设备通过该函数为IO服务。在该函数中,我增加per_cpu计数器以了解每个cpu在飞行中有多少IO。但是有一个函数被调用的竞争条件但是计数器还没有增加,所以我的设备认为有0个IO,释放资源然后IO来崩溃系统。据我所知,Hotplug不会帮助我解决这个问题

2 个答案:

答案 0 :(得分:1)

大约十年前,我在软件驱动程序项目中使用了热插拔,以安全地添加/删除与嵌入式Linux驱动的机顶盒接口的外部USB磁盘驱动器。

对于您的项目,您还需要编写热插拔。热插拔是一种程序,当某些重要(通常是硬件相关的)事件发生时,内核使用该程序通知用户模式软件。例如,刚刚插入或移除USB设备。

从Linux 2.6内核开始,hotplugging已与驱动程序模型核心集成,因此任何总线或类都可以在添加或删除设备时报告热插拔事件。

在内核树中,/ usr / src / linux / Documentation / usb / hotplug.txt包含有关热插拔的USB设备驱动程序API支持的基本信息。 另请参阅此链接,以及GOOGLE以及示例和文档。

http://linux-hotplug.sourceforge.net/

另一个非常有用的文档讨论了与块设备的热插拔,可以在这里找到:

https://www.kernel.org/doc/pending/hotplug.txt

本文档还提供了一个说明热插拔事件处理的好例子:

下面是您应该了解的主要变量表:

Hotplug事件变量:

每个hotplug事件应至少提供以下变量:

ACTION
The current hotplug action: "add" to add the device, "remove" to remove it.
The 2.6.22 kernel can also generate "change", "online", "offline", and
"move" actions.

DEVPATH
Path under /sys at which this device's sysfs directory can be found.

SUBSYSTEM
If this is "block", it's a block device.  Anything other subsystem is
either a char device or does not have an associated device node.

还为某些设备提供了以下变量:

MAJOR and MINOR
If these are present, a device node can be created in /dev for this device.
Some devices (such as network cards) don't generate a /dev node.

DRIVER
If present, a suggested driver (module) for handling this device.  No
relation to whether or not a driver is currently handling the device.

INTERFACE and IFINDEX
When SUBSYSTEM=net, these variables indicate the name of the interface
and a unique integer for the interface.  (Note that "INTERFACE=eth0" could
be paired with "IFINDEX=2" because eth0 isn't guaranteed to come before lo
and the count doesn't start at 0.)

FIRMWARE
The system is requesting firmware for the device. 

答案 1 :(得分:1)

如果驱动程序正在创建设备,则可能会突然将其删除:

  1. mAdapter.refresh(mUploads); ,其中echo 1 > /sys/block/device-name/device/delete可能是device-name,例如

  1. sde,其中h是HBA编号,c是HBA上的通道,t是SCSI目标ID,l是LUN。

就我而言,它完美地模拟了破坏写入和从日记中恢复数据的方案。

通常情况下,echo 1 > /sys/class/scsi_device/h:c:t:l/device/delete删除设备需要执行更多步骤,因此删除设备对于数据来说是非常严重的事件,可能对测试有用:)

请考虑以下问题:

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/online_storage_reconfiguration_guide/removing_devices

http://www.sysadminshare.com/2012/09/add-remove-single-disk-device-in-linux.html