c++aio

LibAio: Why I can obtain data without calling io_getevents method?


I tried to read file contents using Libaio, but I found that even if I didn't call io_getevents method, the expected contents are obtained.

Is it necessary to call the io_getevents method after I call the io_submit method?

If yes, why this issue happened?

If no, when should I call io_getevents to the read result? Can I repead to call it multi times?

here is the demo code:

#include <stdio.h>
#include <libaio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define error() printf("error [%s : %d]\n", __FILE__, __LINE__)
 
#define BUFF_SIZE 51
#define BUFF_CNT 50
#define READLEN 4194304
int main(int argc, char *argv[])
{
    int fd = open(__FILE__, O_RDONLY);
    if (fd == -1) {
        error();
        return -1;
    }

    io_context_t ctx = 0;
    int err = io_setup(BUFF_CNT, &ctx);
    if (err != 0) {
        error();
        return -1;
    }

    struct iocb *io = (struct iocb *)malloc(sizeof(struct iocb));
    if (NULL == io) {
        printf("alloc struct iocb failed");
        return -1;
    }
    memset(io, 0x00, sizeof(io));

    char double_check_m_buf[READLEN];
    io_prep_pread(io, fd, double_check_m_buf, READLEN, 0);

    int rc = io_submit(ctx, 1, &io);
    if (rc < 0) {
        printf("aio send read one block failed");
        return -1;
    }

    printf("aio send read one block success, len: %d \n content: %s",strlen(double_check_m_buf), double_check_m_buf);

Solution

  • There are two things that may be going on here.

    There are a bunch of cases where io_submit can't do asynchronous I/O. When those happen, it falls back to synchronous I/O. It's up to the caller to realize the requested I/O happened inline of the call.

    In your case, you need to open the file with O_RDONLY|O_DIRECT. That will likely do the trick, presuming your filesystem supports AIO.

    If you open __FILE__ with O_DIRECT, io_submit will bypass the kernel's buffer cache. It may still complete rapidly. Depending on what the underlying storage is, it may very well complete before you can inspect the buffer. It's an off-chance, but still, it's possible.

    The only way to be sure your I/O has completed is to call io_getevents. That's the only way to retrieve the error if it fails. Here, __FILE__ is likely far shorter than 4 MiB, so you'll need the length of the read that's returned in that structure as well.