我想要实现的目标:
Developing an linux application in C language, that "exclusively" accesses a
PATA/SATA硬盘驱动器(HDD)发送ATA命令(实际上只有那些不要修改访问的HDD上的任何字节,例如READ_SECTOR、IDENTITYDEVICE、SET_FEATURES,等等)
所谓"独占",我的意思是,一旦HDD通电(一种自定义硬件,它是一个简单的开关,确保HDD在加载应用程序之前不会通电,并且希望这样做),对该HDD的第一次也是唯一一次访问仅限于我的应用程序。IOW,除了我的应用程序,甚至linux内核(包括SCSI子系统),也没有任何其他应用程序或进程或人类用户能够访问该HDD,除非我的应用软件指示/允许他们这样做。
我的申请还有另一项要求:由于对HDD的访问在我们的应用程序中非常关键(就控制而言,而不是性能而言)。,因此,不希望任何I/O调度器参与应用程序完成的事务(该HDD的性能不受限制。)。此外,也不希望从HDD读取的数据由内核缓冲区或页面缓冲区缓冲。应用程序将读取512字节或其倍数的块大小。
现在我面临的问题是:
SCSI子系统位于I/O调度程序和内核缓冲区或页面缓冲区缓存下面(并编写为与之一起使用)。
虽然SCSI子系统提供了"sg驱动程序"来直接向HDD发送命令(Linux SCSI子系统命令,而不是ATA或SCSI命令,然后由libata将其转换为实际的ATA命令。我在这里吗?),但这是一种I/O方法-你给I/p,然后得到O/p,即,您无法控制数据传输协议(如PIO、DMA和ATA状态以及错误寄存器等)和设备配置(通过Set Features ATA命令)的过程
此外,错误报告机制必须是健全的,并且特定于ATA协议,而不仅仅是Linux SCSI子系统错误代码。IOW我的应用程序需要访问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架构的方式编写这样的驱动程序吗?
这是一种可行的方法吗?如果是,那么它会影响我的应用程序无法访问的其他连接HDD的I/O性能吗。以这种方式。在这种情况下,我是否需要通过VFS编写一个系统调用(或者如果可能的话绕过它),以便我的应用程序与我的块驱动程序通信?请告诉我这种方法。
或者我的块设备驱动程序是否可以直接与为libata编写的PATA/SATA HBA驱动程序通信,但这种方法会再次影响我的应用程序无法访问的其他连接HDD的I/O性能吗。以这种方式。此外,我的应用程序将如何与这个块设备驱动程序通信?
请开导我。
此外,我还想了解我的应用程序的相同场景,但有一个不同之处——如果我有SCSI硬盘驱动器及其变体,那该怎么办?特别是SAS、光纤通道和USB。当然,这次我不会使用libata和ATA命令,而是使用SCSI协议命令。
您是否建议使用一个livecd发行版作为我的应用程序主机,它包含大多数HBA的PATA/SATA HBA libata驱动程序(-不适用于IDE子系统,因为我不会使用它,因为它现在已经贬值,因此可能不会针对HBA驱动程序进行更新。)。
简而言之,linux应用程序访问PATA/SATA或SCSI/SAS/光纤通道HDD的最直接方式是什么。
我希望,我已经就我的问题提供了足够的信息,但如果你想得到更多的信息或更多的澄清,请随时询问。
更新1(2012年6月27日):
通过与Chris的有益讨论(见下文)和我的研究,我得出了以下结论:
现成的USB到PATA/SATA适配器无法解决我的目的,因为它不允许我的应用程序。或驱动程序更改数据传输模式(PIO vs DMA),它不允许我的应用程序。或驱动程序来读取ATA寄存器。
定制的USB到PATA/SATA适配器可能会有所帮助,但这需要一个需要实现ATA协议的嵌入式处理器,或者一个实现整个ATA协议的FPGA芯片。但是嵌入式处理器解决方案涉及GPIO,对SATA不好,因为它需要专门的收发器,I/O性能对PATA和SATA都是一个问题,对我的应用程序来说太慢了。
这样的适配器将与我的应用程序的linux内核驱动程序(或通过libusb)进行通信。通过一个自定义协议,有助于与我的应用程序进行通信。以及嵌入式处理器上的ATA协议。在FPGA芯片解决方案的情况下,我需要在FPGA本身和ATA协议中实现该协议。
但在这一点上,对我来说,实现FPGA解决方案和嵌入式处理器解决方案在劳动力、时间和金钱方面都是不可行的。所以我只能使用仅限软件的解决方案。
最后,我可能不得不复制和修改所有的东西,直到硬件接口层,以满足Chris所说的需求。
因此,VFS层和HBA驱动程序或libata层之间的,我应该如何进行。哪些事情需要实施,哪些不需要
有人能阐明这个问题吗?有什么想法吗??
更新2(2012年7月1日):
我正在处理这个问题。SO上有人能启发我吗?
实际上,如果你想要这种级别的细节控制,最终将不得不编写自己的低级驱动程序。
您在避免I/O缓冲和调度方面的限制可能特别具有挑战性——您可能会避免DMA,但出于性能原因,现代处理器的I/O与内部操作相当解耦。也许,如果您可以完全禁用所有中断,那么您至少可以在做事时标记时间戳。您可能希望驱动器位于自己的接口适配器上,当然不会与正在运行的文件系统共享。
从用户空间做事情可能需要通过内核中的代理来工作——不过,您需要在内核端做时间关键的事情。
如果能满足您的需求,一个简单得多的解决方案是使用USB到SATA或PATA适配器。您可以使用modprobe的怪癖模式告诉现有的内核驱动程序忽略VID/PID,然后从用户空间通过libusb与设备通信。然而,肯定会有延迟。
为了获得最佳的控制水平,您可能需要将驱动器连接到没有I/O缓冲的嵌入式处理器,甚至可能需要连接FPGA。对于PATA的低数据速率来说,这并不特别困难,SATA可能需要专门的收发器,但可能不在可能的范围内(或者您可以通过其中一个适配器工作)。你可能最终会通过USB甚至串行端口将这个自定义外设连接到电脑,并使用它来发布任务和获取结果(如果你设置它,让电脑可以下载设备的固件/比特流,这会很方便,所以你有灵活性)。