我正在编写一些类似Bittorrent客户端的应用程序,以便从网上下载文件并将其写入本地文件。我将获得部分数据并将其写入文件。
例如,我将下载一个1GB的文件,我将得到offset 100, data: 312 bytes
,offset 1000000, data: 12345
,offset 4000000, data: 888 bytes
。
我正在使用Linux本机AIO(io_setup
,io_submit
,io_getevents
),我发现了
使用Linux内核AIO时,要求文件以O_DIRECT模式打开。这引入了所有读写操作的进一步要求,以使其文件偏移,内存缓冲区和大小对齐到512字节。
那么如何将数据写入未512对齐的偏移量中?
例如,首先我将4个字节写入文件,因此我必须执行以下操作:
fd = open("a.txt", O_CREAT | O_RDWR | O_DIRECT, 0666);
struct iocb cb;
char data[512] = "asdf";
cb.aio_buf = ALIGN(data, 512);
cb.aio_offset = 512;
cb.aio_nbytes = 512;
然后我想在asdf
之后附加数据:
struct iocb cb2;
char data2[512] = "ghij";
cb2.aio_buf = ALIGN(data2, 512);
cb2.aio_offset = 5;
cb2.aio_nbytes = 512;
写时会报错
Invalid argument (-22)
那怎么办?
答案 0 :(得分:1)
如果您不使用O_DIRECT
,则必须执行驱动程序将要做的事情。即,读取整个块,更新所需的部分,然后将其写回。阻止设备根本不允许较小的访问。
自己动手做会更有效率(例如,您可以为一次读和写操作而在同一块中更新许多断开连接的序列)。但是,由于您不让驱动程序执行工作,因此在读取-修改-写入操作中也不会获得任何原子性保证。
答案 1 :(得分:1)
你不知道。 Linux AIO API没用,尤其是对于您要尝试执行的操作而言。它是为了Oracle而添加的,Oracle希望绕开内核的文件系统并为Reasons™阻止设备缓冲层。它与POSIX AIO无关,也与其他人在谈论“ AIO”时的意思无关。