C 使用Linux AIO,可以执行IOs操作,但也可以将垃圾写入文件

C 使用Linux AIO,可以执行IOs操作,但也可以将垃圾写入文件,c,linux,pointers,io,aio,C,Linux,Pointers,Io,Aio,这可能看起来很傻,但是,我使用libaio(不是posixaio),我可以在文件中写入一些内容,但我也在向文件中写入额外的内容 我阅读了有关对齐要求和iocb缓冲区字段的数据类型的信息 这是代码示例(仅用于表示相关的使用部分) 输出: 这段代码确实创建了文件,并写入了预期的字符串 hello堆栈溢出到文件/tmp/someFile中 问题: 文件/tmp/someFile在预期字符串后面还包含, @^@^@^@^@^@^@^@^@^文件本身的某些部分(代码部分)可以说是垃圾 在某种程度上,我确信

这可能看起来很傻,但是,我使用libaio(不是posixaio),我可以在文件中写入一些内容,但我也在向文件中写入额外的内容

我阅读了有关对齐要求和iocb缓冲区字段的数据类型的信息

这是代码示例(仅用于表示相关的使用部分)

输出:

这段代码确实创建了文件,并写入了预期的字符串 hello堆栈溢出到文件/tmp/someFile中

问题:

文件/tmp/someFile在预期字符串后面还包含, @^@^@^@^@^@^@^@^@^文件本身的某些部分(代码部分)可以说是垃圾

在某种程度上,我确信这是数据字段中的某个指针出错,但无法破解它

  • 如何使用aio(而不是posix)将“hello world”准确且仅写入文件
我知道,到目前为止,并非所有文件系统都支持aio调用。我的对手确实支持我

编辑-如果您想要此尝试的入门包,您可以从这里获得


编辑2:粗心大意,我在文件中设置了更多要写入的字节数,代码对此表示尊重。简单地说,要准确地写“hw”,在iocb的bytes字段中只需要不超过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
    接口之上,事情也会变得棘手。您需要执行对齐读取以覆盖需要写入的数据范围,然后修改内存中的数据并将对齐区域写回磁盘

    例如,假设您想修改磁盘上的偏移量768到1023。您需要将偏移量512处的512字节读入缓冲区。然后,
    memcpy()。最后,在偏移量512处对512字节缓冲区进行写入

    未初始化数据:正如其他人指出的,您尚未完全初始化正在编写的缓冲区。使用
    memset()
    将其初始化为零,以避免写入垃圾

    分配对齐指针:要满足数据缓冲区的指针要求,需要使用
    posix_memalign()
    。例如,要分配具有512字节对齐限制的4096字节:
    posix_memalign(&ptr,512,4096)


    <强>最后,考虑是否需要这样做。< /强>即使在最好的情况下,<代码> IOSUpjiS/<代码>仍然是“块”,尽管在10到100微秒级别。使用

    pread
    pwrite
    的正常阻塞I/O为您的应用程序提供了许多好处。而且,如果它变得繁重,您可以将它降级到另一个线程。如果你有一个对延迟敏感的应用程序,无论如何你都需要在另一个线程中执行io_submit

    您想要的字符串长度是100字节,还是可能更短?
    /tmp/someFile
    的文件大小最终是100,对吗?@Hasturkun更短。请注意,您正在设置在
    somecb.aio_nbytes=100中写入100字节,我假定这是您的最终文件大小。您可能正在写入缓冲区的初始化部分。编写时可能需要使用实际字符串长度。1)somecb.aio_buf=(uint64_t)someBuffer:我看这里没有演员阵容。2) 
    struct iocb*somecbs[1]你不需要这个。3) 您假设缓冲区为零/空。>根据我的经验,未能满足上述任何要求实际上不会返回错误!我该如何确切地证明它?strace是否足够?是的,使用
    strace-T
    。这将为您提供每次系统调用所花费的时间。如果您呼叫io_submit的时间超过50微秒,则可能是使用缓冲I/O。如果我的回答对您有所帮助,请接受。谢谢
    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);