绕过I/O调度和Linux内核页面缓存

3

我想要实现的目标:

Developing an linux application in C language, that "exclusively" accesses a

PATA/SATA硬盘驱动器可以发送ATA命令(实际上只有那些不修改访问的HDD上的任何字节的ATA命令,例如:READ_SECTOR,IDENTIFY_DEVICE,SET_FEATURES等)。
“独占”是指只要硬盘被开启(一个自定义的硬件-一个简单的开关,确保只有当应用程序加载并需要时才会将硬盘开启),对该硬盘的第一次和唯一的访问只属于我的应用程序。换句话说,除了我的应用程序外,甚至连Linux内核(包括SCSI子系统)也无法访问该硬盘,也没有其他应用程序、进程或人工用户能够访问该硬盘,除非我的应用程序指示/允许它们这样做。
我的应用程序还有另一个要求: 由于在我们的应用程序中,对HDD的访问是相当关键的(从控制而不是性能方面),因此不希望任何I/O调度程序参与应用程序所做的事务(这个HDD的性能并不是约束因素)。同时,也不希望从HDD读取的数据被内核缓冲区或页面缓冲区缓存。应用程序将仅以512字节的块大小或其倍数进行读取。
现在我面临的问题是: SCSI子系统位于I/O调度程序和内核缓冲区或页面缓冲区缓存之下。
虽然SCSI子系统提供了“sg-driver”来直接发送命令(Linux SCSI子系统命令,不是ATA或SCSI直接命令-然后由libata将其转换为实际的ATA命令。我在这里是正确的吗?)到HDD,但这是一种I/O方法-你提供输入并获取输出,即你对数据传输协议的过程没有控制(例如PIO、DMA和ATA状态和错误寄存器等)和设备配置(通过Set Features ATA命令)。此外,错误报告机制必须健全,并且特定于ATA协议,而不仅仅是Linux SCSI子系统错误代码。换句话说,我的应用程序需要访问PATA/SATA HDD上的ATA错误寄存器和ATA状态寄存器。
我的应用程序要求独占控制HDD-例如发出一个READ_SECTOR ATA命令,然后直接通过读取I/O端口或通过“libata”从HDD本身检索数据,并满足上述要求。
我不能做什么?
我不打算编写PATA/SATA HBA设备驱动程序或市场上可用的每个HBA,因为这些已经包含在libata的内核中。
我现在学到了什么?
为了完成所需的任务,我可能(或可能不需要?)需要编写一个块设备驱动程序,直接与VFS层交互(或是否有任何方法可以绕过VFS,以便我的应用程序可以直接与此块驱动程序通信),而不涉及/干扰内核缓冲区或页面缓冲区和I/O调度程序。这个块驱动程序将直接与libata通信(绕过SCSI子系统上层),然后与PATA/SATA HBA驱动程序通信。
有没有可能以与CPU架构无关的方式编写这样的驱动程序?
这种方法可行吗?如果是,那么这会影响其他连接的未被我的应用程序访问的硬盘驱动器的I/O性能吗?在这种情况下,我需要为我的应用程序编写一个系统调用来与我的块驱动程序通信吗(如果可能的话绕过VFS)?
还是说我的块设备驱动程序可以直接与为libata编写的PATA/SATA HBA驱动程序通信?但是同样地,这种方法会影响其他连接的未被我的应用程序访问的硬盘驱动器的I/O性能吗?另外,我的应用程序如何与这个块设备驱动程序通信?
对于相同的场景,我想知道应用程序的情况,只有一个区别-除了PATA/SATA驱动器之外,如果我有SCSI硬盘及其变体-特别是SAS、光纤通道和USB。当然,这次我不会使用libata和ATA命令,而是使用SCSI协议命令。
您是否想建议一个包含大多数HBA的PATA/SATA HBA libata驱动程序(-不适用于IDE子系统,因为我将不会使用它,因为它已经过时,因此可能不会更新与HBA驱动程序相关的内容)的live cd发行版,作为我的应用程序主机。
简而言之,Linux应用程序访问PATA/SATA或SCSI/SAS/光纤通道HDD的最直接方式是什么?
我希望我已经提供了关于我的问题足够的信息,但如果您需要更多的信息或更多的澄清,请随时提问。
更新1(于2012年6月27日):
通过与Chris的有益讨论和我的研究,我得出了以下结论:
1.预制的USB到PATA/SATA适配器无法解决我的目的,因为它不允许我的应用程序或驱动程序在运行时更改数据传输模式(PIO vs DMA),也不允许我的应用程序或驱动程序读取ATA寄存器。
2.定制的USB到PATA/SATA适配器可能有所帮助,但这将需要实现ATA协议的嵌入式处理器或实现整个ATA协议的FPGA芯片。但是,嵌入式处理器解决方案涉及GPIO,并且对于SATA来说并不好,因为它需要专门的收发器,并且对于PATA和SATA的I/O性能都会成为一个问题。
这样的适配器将通过自定义协议与我的Linux内核驱动程序(或通过libusb)交互,以帮助我的应用程序与嵌入式处理器上的ATA协议进行通信。在FPGA芯片解决方案的情况下,我需要在FPGA本身中实现这个协议以及ATA协议。
但是,就劳动力、时间和金钱而言,在我实现FPGA解决方案和嵌入式处理器解决方案方面是不可行的。所以我只能使用纯软件解决方案
最后,似乎我可能需要复制并修改所有内容,直到硬件接口层,以满足克里斯的要求。
那么,在VFS层和HBA驱动程序或libata层之间,我应该如何进行?哪些东西需要实现,哪些不需要?
可以有人解决这个问题吗?任何想法吗? 更新2(于2012年1月7日)
我正在努力解决这个问题。在SO上有没有人可以启迪我一下?
1个回答

3
实际上,如果您想要这种详细控制水平,您最好编写自己的低级驱动程序。
您希望避免I/O缓冲和调度的限制可能特别具有挑战性-您可能会避免DMA,但现代处理器出于性能原因将其I/O与内部操作分离。也许,如果您能完全禁用所有中断,您至少可以在执行操作时记录时间戳。您可能希望将驱动器放在自己的接口适配器上,而不是与正在运行的文件系统共享。
如果从用户空间进行操作,则可能需要通过内核代理来进行工作-您需要在内核端执行定时关键任务。
如果符合您的需求,一个简单得多的解决方案是使用USB到SATA或PATA适配器。您可以告诉现有的内核驱动程序使用modprobe的quirks模式忽略VID/PID,然后通过用户空间的libusb与设备通信。但是,那里肯定会有延迟。
对于最精细的控制水平,您可能需要将驱动器连接到没有I/O缓冲区的嵌入式处理器,甚至是FPGA。低速数据率的PATA实现起来并不是特别困难,SATA可能需要专门的收发器,但也可能不在不可能的范围内(或者您可以通过其中一个适配器进行工作)。您可能最终将这个自定义外设连接到PC上,通过USB甚至串口使用它来发布任务和获得结果(如果设置得当,PC可以下载设备的固件/位流,因此具有灵活性)。

1
感谢您提供替代方案的建议。 但是,正如我所提到的,我需要访问硬盘的ATA状态和ATA错误寄存器,以向我的应用程序报告实际的ATA状态和错误。使用USB或任何其他接口,除了PATA / SATA接口之外,这似乎是不可能的。此外,对于我来说,实现自定义FPGA和嵌入式处理器成本太高。数据传输(从硬盘读取)对我来说也很困难,因为我必须在FPGA或嵌入式处理器内部实现完整的ATA协议。 - jacks
1
如果该项目在PC类型的硬件上是可能的,那么您应该以尽可能低的级别编写它,即直接与处理器总线-PATA或SATA桥设备通信的级别。 - Chris Stratton
1
那么我是否需要编写PATA/SATA HBA驱动程序,还是可以使用现有的libata PATA/SATA HBA驱动程序,或者我的驱动程序只需要与libata通信,或者我的驱动程序需要与Linux PCI子系统通信(用于直接端口I/O?),或者采用其他方法? - jacks
1
为了满足一些奇怪的要求,你可能需要复制并修改所有东西,直到硬件接口层。这就是为什么你可能会发现使用裸机嵌入式平台更容易,因为该架构更加扁平,没有那么多需要剥离的层级。 - Chris Stratton
1
如果通过ARM或FPGA(我对FPGA不是很了解)实现此美国到PATA桥接器,那么是否可以随时选择PIO或DMA来检索数据? libusb是否支持USB2.0高速(480Mbps)设备? SATA也是我的一个问题(您说“ SATA可能需要专门的收发器”)。成本也是一个考虑因素。是否已经有可用于我的目的的USB到PATA / SATA桥接器可以编程? - jacks
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接