这可能看起来很愚蠢,但是,我使用的是 libaio(不是 posix aio),我可以向文件中写入一些内容,但我也会向文件中写入额外的内容。
我看了iocb的对齐要求和buffer字段的数据类型。
这里是代码示例(仅使用相关部分,用于表示)
aio_context_t someContext;
struct iocb somecb;
struct io_event someevents[1];
struct iocb *somecbs[1];
somefd = open("/tmp/someFile", O_RDWR | O_CREAT);
char someBuffer[4096];
... // error checks
someContext = 0; // this is necessary
io_setup(32, &someContext ); // no error checks pasted here
strcpy(someBuffer, "hello stack overflow");
memset(&somecb, 0, sizeof(somecb));
somecb.aio_fildes = somefd ;
somecb.aio_lio_opcode = IOCB_CMD_PWRITE;
somecb.aio_buf = (uint64_t)someBuffer;
somecb.aio_offset = 0;
somecb.aio_nbytes = 100; // // //
// I am avoiding the memeaign and sysconf get page part in sample paste
somecbs[0] = &somecb; // address of the solid struct, avoiding heap
// avoiding error checks for this sample listing
io_submit(someContext, 1, somecbs);
// not checking for events count or errors
io_getevents(someContext, 1, 1, someevents, NULL);
输出:
这段代码确实创建了文件,并写入了预期的字符串 你好堆栈溢出到文件/tmp/someFile。
问题:
文件/tmp/someFile 还在预期的字符串之后依次包含, @^@^@^@^@^@^@^@^@^ 和文件本身的一些部分(代码部分),可以说是垃圾。
我在某种程度上确定这是数据字段中的某个指针出错了,但无法破解。
- 如何使用 aio(而非 posix)将“hello world”准确且仅写入文件?
我知道到目前为止,所有文件系统可能都不支持 aio 调用。我反对的人确实支持。
编辑 - 如果您想要这次尝试的入门包,您可以从这里获得。
http://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt
编辑 2:粗心大意,我在文件中设置了更多要写入的字节数,并且代码遵守了它。简而言之,在 iocb 的 bytes 字段中,要准确地写入 'hw' 需要不超过 2 个字节。
最佳答案
这里发生了一些事情。首先,您提到的对齐要求是 512 字节或 4096 字节,具体取决于您的底层设备。尝试从 512 字节开始。它适用于:
您在文件中写入的偏移量必须是 512 字节的倍数。它可以是 0、512、1024 等。您可以像这里一样在偏移量 0 处写入,但不能在偏移量 100 处写入。
写入文件的数据长度必须是 512 字节的倍数。同样,您可以写入 512 字节、1024 字节或 2048 字节等等 - 512 的任意倍数。您不能像此处尝试的那样写入 100 字节。
包含您正在写入的数据的内存地址必须是 512 的倍数。(为了安全起见,我通常使用 4096。)在这里,您需要能够执行
someBuffer % 512
和得到 0。(按照现在的代码,很可能不会。)
根据我的经验,未能满足上述任何要求实际上并不会返回错误!相反,它将使用正常的、常规的旧阻塞 I/O 来完成 I/O 请求。
未对齐的 I/O:如果您真的、真的需要写入少量数据或以未对齐的偏移量写入,那么即使在 io_submit
接口(interface)之上和之外,事情也会变得棘手。您需要进行对齐读取以覆盖您需要写入的数据范围,然后修改内存中的数据并将对齐区域写回磁盘。
例如,假设您想修改磁盘上从 768 到 1023 的偏移量。您需要将偏移量 512 处的 512 个字节读入缓冲区。然后,memcpy()
将 256 字节写入该缓冲区的 256 字节。最后,您在偏移量 512 处发出 512 字节缓冲区的写入。
未初始化的数据:正如其他人所指出的,您还没有完全初始化您正在编写的缓冲区。使用 memset()
将其初始化为零以避免写入垃圾。
分配对齐指针:为了满足数据缓冲区的指针要求,您需要使用 posix_memalign()
。例如,要分配 4096 字节且对齐限制为 512 字节:posix_memalign(&ptr, 512, 4096);
最后,考虑您是否需要这样做。即使在最好的情况下,io_submit
仍然会“阻塞”,尽管是在 10 到 100 微秒的级别。带有 pread
和 pwrite
的普通阻塞 I/O 为您的应用程序提供了很多好处。而且,如果它变得繁重,您可以将其委托(delegate)给另一个线程。如果您有一个对延迟敏感的应用程序,您无论如何都需要在另一个线程中执行 io_submit!
关于c - 使用 Linux AIO,能够执行 IO,但也会将垃圾写入文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45735455/