首页 > 解决方案 > io_setup 中的 nr_events 与 io_submit 和 io_getevents 中的 nr 是什么关系?

问题描述

   #include <linux/aio_abi.h>          /* Defines needed types */

   int io_setup(unsigned nr_events, io_context_t *ctx_idp);
   int io_submit(io_context_t ctx_id, long nr, struct iocb **iocbpp);
   int io_getevents(io_context_t ctx_id, long min_nr, long nr,
                    struct io_event *events, struct timespec *timeout);

问题一:

如果我使用io_setup(32, ctx_idp),我可以提交 100 次吗?还是只能提交32次,先用io_getevents处理数据,然后再提交?

io_submit(ctx_id, 100, iocbpp);

或者

for(I = 0; I<100; I++) {
    io_submit(ctx_id, 1, iocbpp);
}

问题2:

io_getevents是否long min_nr, long nr由 io_setup 中的 nr_events 决定?

1 <= min_nr <= 32 and 1 <= nr <= 32?

还是由nrio_submit 决定?所以

1 <= min_nr <= 100 and 1 <= nr <= 100?

标签: clinuxaio

解决方案


对问题 1 的回答:

是的,您可以创建一个上下文来处理 32 个并发请求io_setup并运行io_submit100 个请求,类似于io_submit(ctx_id, 100, iocbpp);. 我已经在 CentOS 7 上成功测试了这个(没有libaio使用这里的改编代码)。

回答问题 2:

io_getevents参数与提交的请求数有关io_submit(我也成功测试过)。

这是我使用的代码。它需要 2 个参数并允许写入单个文件,但在不同的偏移量处,您可以检查io_submit正在写入的内容。

/*
 * taio.c
 * 
 * test AIO on Linux
 * 
 * taio <number of operations for io_setup> <number of control blocks for io_submit>
 *
 *
 */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <linux/aio_abi.h>



inline int io_setup(unsigned nr, aio_context_t *ctxp) {
    return syscall(__NR_io_setup, nr, ctxp);
}

inline int io_destroy(aio_context_t ctx) {
    return syscall(__NR_io_destroy, ctx);
}

inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) {
    return syscall(__NR_io_submit, ctx, nr, iocbpp);
}

inline int io_getevents(aio_context_t ctx, long min_nr, long max_nr,
        struct io_event *events, struct timespec *timeout) {
    return syscall(__NR_io_getevents, ctx, min_nr, max_nr, events, timeout);
}

/*
 * size must match
 */
#define IO_SIZE 10 

int main(int argc, char *argv[]) {
    aio_context_t ctx;
    struct iocb *tcb;
    struct iocb **lcb;
    char *data;
    char **tdata;
    struct io_event *events;
    int ret;
    int fd;
        int i,j;
    long int nr_iosetup;
    long int nr_iosubmit;
    int current_offset;

    if (argc != 1 && argc != 3)
    {
        printf("taio: usage <number of operations for io_setup> <number of control blocks for io_submit>");
        return 1;
    }

    nr_iosetup = 1;
    nr_iosubmit = 1;
    for(i=0; i < argc; i++)
    {
        if (i == 1)
            nr_iosetup = atoi(argv[1]);
        if (i == 2)
            nr_iosubmit = atoi(argv[2]);
    }

    tdata = malloc(nr_iosubmit * sizeof(char *));
    if (tdata == NULL)  
    {
        perror("malloc tdata");
        return 1;
    }

    tcb = malloc(nr_iosubmit * sizeof(struct iocb));
    if (tcb == NULL)    
    {
        perror("malloc tcb");
        return 1;
    }

    lcb = malloc(nr_iosubmit * sizeof(struct iocb *));
    if (lcb == NULL)    
    {
        perror("malloc lcb");
        return 1;
    }

    for (j=0; j < nr_iosubmit; j++)
    {
        data = malloc(IO_SIZE);
        if (data == NULL)
        {
            perror("malloc data");
            return 1;
        }
        tdata[j] = data;
        sprintf(data, "%d\n", j);
    }

    events = malloc(nr_iosubmit * sizeof(struct io_event));
    if (events == NULL) 
    {
        perror("malloc events");
        return 1;
    }


    ret = unlink("/tmp/taio.dat");
    /* ignore error */

    fd = open("/tmp/taio.dat", O_RDWR | O_CREAT | O_EXCL,  S_IRWXU);
    if (fd < 0) {
        perror("open");
        return -1;
    }
    printf("open\t\t=> fd=%d\n", fd);

    ctx = (aio_context_t)0;
    ret = io_setup(nr_iosetup, &ctx);
    if (ret < 0) {
        perror("io_setup");
        return -1;
    }
    printf("io_setup\t=> nr_iosetup=%ld ret=%d\n", nr_iosetup, ret);


    /* command-specific options */
    for (j=0, current_offset=0; j < nr_iosubmit; j++)
    {
            /* setup I/O control block */
        memset(&tcb[j], 0, sizeof(struct iocb));
        tcb[j].aio_fildes = fd;
        tcb[j].aio_lio_opcode = IOCB_CMD_PWRITE;
        tcb[j].aio_buf = (uint64_t)tdata[j];
        tcb[j].aio_offset = current_offset;
        tcb[j].aio_nbytes = IO_SIZE;

        lcb[j] = &tcb[j];

        current_offset += IO_SIZE;
    }

    ret = io_submit(ctx, nr_iosubmit, lcb);
    if (ret < 0) 
    {
        perror("io_submit");
        return 1;
    }

    printf("io_submit\t=> nr_iosubmit=%ld ret=%d\n", nr_iosubmit, ret);

    ret = io_getevents(ctx, nr_iosubmit, nr_iosubmit, events, NULL);
    printf("io_getevents\t=> ret=%d\n", ret);

    ret = io_destroy(ctx);
    if (ret < 0) {
        perror("io_destroy");
        return -1;
    }
    printf("io_destroy\t=> ret=%d\n", ret);

    return 0;
}

执行:

./taio 32 100
open            => fd=3
io_setup        => nr_iosetup=32 ret=0
io_submit       => nr_iosubmit=100 ret=100
io_getevents    => ret=100
io_destroy      => ret=0

推荐阅读