假设磁盘上保存了一个大文件,并且我想对文件中包含的每个数据 block 运行计算。
我为此编写的 C/C++ 代码将加载文件的一部分,然后进行处理,然后加载下一部分,然后进行下一部分的处理,依此类推。
但是,如果我有兴趣在尽可能短的时间内完成此操作,我实际上可以执行以下操作:首先,告诉 DMA Controller 加载文件的第一部分。当加载该部分时,告诉 DMA Controller 加载第二部分(在内存的其他部分),然后立即开始处理第一部分。
如果我在处理第一部分期间收到来自 DMA 的中断,我会完成第一部分,然后告诉 DMA 用文件的第三部分覆盖它;然后我处理第二部分。
如果在处理第一部分期间没有收到 DMA 的中断,我会完成第一部分并等待 DMA 的中断。
根据与磁盘读取相关的处理时间,这应该是两倍的速度。当然,在现实中,人们必须进行衡量。但这不是我要问的问题。
问题是:是否可以使用一些非标准扩展在 C 中执行 a) 或在汇编中执行 b)?或者操作系统一般不允许这样的事情吗?这个问题主要是在单线程上下文中提出的,尽管我也有兴趣知道如何使用两个线程来完成它。另外,我对具体代码感兴趣;这更多的是一个理论问题。
最佳答案
你是对的,默认情况下你不会受益于此,因为阻塞读取会阻止你的线程进行任何处理。 Hans 是对的,现代操作系统已经处理了 DMA 和中断完成例程的所有小细节。
您需要使用您所描述的架构,在使用数据之前发出请求。发出异步 I/O 请求(在 Windows 上,这些请求称为 OVERLAPPED
)。然后流程将完全按照您的设想进行,但 DMA 和中断是在驱动程序中处理的。
在 Windows 上,请查看 FILE_FLAG_OVERLAPPED
(至CreateFile
)和ReadFile
(如果您喜欢事件)或 ReadFileEx
(如果你喜欢回调)。如果您不必按任何特定顺序处理数据,则可以向组合中添加一个完成端口,它将完成响应排队。
在 Linux、OSX 和许多其他类 Unix 操作系统上,请查看 aio_read
。或fadvise
。或者使用mmap
与 madvise
.
您甚至无需编写 native 代码即可获得这些好处。 .NET 最近添加了 ReadAsync
其 FileStream
的方法,可以与 Task
形式的连续传递样式一起使用对象,带有 async
/await
C# 编译器中的语法糖。
关于c - 从磁盘读取文件期间使用中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20164309/