美文网首页
liburing API

liburing API

作者: lnsyyj | 来源:发表于2020-11-11 22:50 被阅读0次
    /*
    * Library interface to io_uring
    */
    struct io_uring_sq {
       unsigned *khead;
       unsigned *ktail;
       unsigned *kring_mask;
       unsigned *kring_entries;
       unsigned *kflags;
       unsigned *kdropped;
       unsigned *array;
       struct io_uring_sqe *sqes;
    
       unsigned sqe_head;
       unsigned sqe_tail;
    
       size_t ring_sz;
       void *ring_ptr;
    
       unsigned pad[4];
    };
    
    struct io_uring_cq {
       unsigned *khead;
       unsigned *ktail;
       unsigned *kring_mask;
       unsigned *kring_entries;
       unsigned *kflags;
       unsigned *koverflow;
       struct io_uring_cqe *cqes;
    
       size_t ring_sz;
       void *ring_ptr;
    
       unsigned pad[4];
    };
    
    struct io_uring {
       struct io_uring_sq sq;
       struct io_uring_cq cq;
       unsigned flags;
       int ring_fd;
    
       unsigned features;
       unsigned pad[3];
    };
    
    
    
    /*
    * Library interface
    */
    
    extern struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring);
    extern struct io_uring_probe *io_uring_get_probe(void);
    extern void io_uring_free_probe(struct io_uring_probe *probe);
    static inline int io_uring_opcode_supported(struct io_uring_probe *p, int op);
    
    extern int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, struct io_uring_params *p);
    
    extern int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags);    //初始化struct io_uring,函数内部会调用io_uring_queue_init_params。io_uring 是一个循环队列(ring_buffer)。第一个参数 entries 表示队列大小(实际空间可能比用户指定的大);第二个参数 ring 就是需要初始化的 io_uring 结构指针;第三个参数 flags 是标志参数,无特殊需要传 0 即可。
    
    extern int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring);
    extern int io_uring_ring_dontfork(struct io_uring *ring);
    extern void io_uring_queue_exit(struct io_uring *ring);
    unsigned io_uring_peek_batch_cqe(struct io_uring *ring, struct io_uring_cqe **cqes, unsigned count);
    extern int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr, struct __kernel_timespec *ts, sigset_t *sigmask);
    extern int io_uring_wait_cqe_timeout(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, struct __kernel_timespec *ts);
    extern int io_uring_submit(struct io_uring *ring);
    extern int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr);
    extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
    
    extern int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, unsigned nr_iovecs);
    extern int io_uring_unregister_buffers(struct io_uring *ring);
    extern int io_uring_register_files(struct io_uring *ring, const int *files, unsigned nr_files);
    extern int io_uring_unregister_files(struct io_uring *ring);
    extern int io_uring_register_files_update(struct io_uring *ring, unsigned off, int *files, unsigned nr_files);
    extern int io_uring_register_eventfd(struct io_uring *ring, int fd);
    extern int io_uring_register_eventfd_async(struct io_uring *ring, int fd);
    extern int io_uring_unregister_eventfd(struct io_uring *ring);
    extern int io_uring_register_probe(struct io_uring *ring, struct io_uring_probe *p, unsigned nr);
    extern int io_uring_register_personality(struct io_uring *ring);
    extern int io_uring_unregister_personality(struct io_uring *ring, int id);
    extern int io_uring_register_restrictions(struct io_uring *ring, struct io_uring_restriction *res, unsigned int nr_res);
    extern int io_uring_enable_rings(struct io_uring *ring);
    extern int __io_uring_sqring_wait(struct io_uring *ring);
    
    extern int __io_uring_get_cqe(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned submit, unsigned wait_nr, sigset_t *sigmask);
    #define io_uring_for_each_cqe(ring, head, cqe)
    
    static inline void io_uring_cq_advance(struct io_uring *ring, unsigned nr)
    static inline void io_uring_cqe_seen(struct io_uring *ring, struct io_uring_cqe *cqe)
    static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
    static inline void *io_uring_cqe_get_data(const struct io_uring_cqe *cqe)
    static inline void io_uring_sqe_set_flags(struct io_uring_sqe *sqe,
    static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd, const void *addr, unsigned len, __u64 offset)
    static inline void io_uring_prep_splice(struct io_uring_sqe *sqe, int fd_in, int64_t off_in, int fd_out, int64_t off_out, unsigned int nbytes, unsigned int splice_flags)
    static inline void io_uring_prep_tee(struct io_uring_sqe *sqe, int fd_in, int fd_out, unsigned int nbytes, unsigned int splice_flags)
    

    io_uring使用

    1、首先需要创建io_uring struct
    2、然后使用io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags);初始化io_uring struct,io_uring_queue_init函数内部会调用函数内部会调用io_uring_queue_init_params。
    
    io_uring struct在liburing中定义如下
    struct io_uring {
       struct io_uring_sq sq;
       struct io_uring_cq cq;
       unsigned flags;
       int ring_fd;
       unsigned features;
       unsigned pad[3];
    };
    
    3、获取并sqe struct
    一个 sqe(submission queue entry)代表一次 IO 请求,占用循环队列一个空位。io_uring 队列满时 io_uring_get_sqe 会返回 NULL,注意错误处理。注意这里的队列是指未提交的请求,已提交的(但未完成)请求不占位置。
    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    
    4、初始化sqe struct
    io_uring_prep_readv 或 io_uring_prep_writev 初始化 sqe struct。
    
    io_uring_prep_readv(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, unsigned nr_vecs, off_t offset)会调用io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset)
    io_uring_prep_rw的定义
    static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
                    const void *addr, unsigned len,
                    __u64 offset)
    {
       sqe->opcode = op;
       sqe->flags = 0;
       sqe->ioprio = 0;
       sqe->fd = fd;
       sqe->off = offset;
       sqe->addr = (unsigned long) addr;
       sqe->len = len;
       sqe->rw_flags = 0;
       sqe->user_data = 0;
       sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
    }
    
    io_uring_prep_writev(struct io_uring_sqe *sqe, int fd, const struct iovec *iovecs, unsigned nr_vecs, off_t offset)会调用io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset)
    io_uring_prep_rw的定义
    static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
                    const void *addr, unsigned len,
                    __u64 offset)
    {
       sqe->opcode = op;
       sqe->flags = 0;
       sqe->ioprio = 0;
       sqe->fd = fd;
       sqe->off = offset;
       sqe->addr = (unsigned long) addr;
       sqe->len = len;
       sqe->rw_flags = 0;
       sqe->user_data = 0;
       sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
    }
    
    sqe struct的定义
    /*
    * IO submission data structure (Submission Queue Entry)
    */
    struct io_uring_sqe {
       __u8   opcode;       /* type of operation for this sqe */
       __u8   flags;    /* IOSQE_ flags */
       __u16  ioprio;       /* ioprio for the request */
       __s32  fd;       /* file descriptor to do IO on */
       union {
          __u64  off;   /* offset into file */
          __u64  addr2;
       };
       union {
          __u64  addr;  /* pointer to buffer or iovecs */
          __u64  splice_off_in;
       };
       __u32  len;      /* buffer size or number of iovecs */
       union {
          __kernel_rwf_t rw_flags;
          __u32     fsync_flags;
          __u16     poll_events;   /* compatibility */
          __u32     poll32_events; /* word-reversed for BE */
          __u32     sync_range_flags;
          __u32     msg_flags;
          __u32     timeout_flags;
          __u32     accept_flags;
          __u32     cancel_flags;
          __u32     open_flags;
          __u32     statx_flags;
          __u32     fadvise_advice;
          __u32     splice_flags;
          __u32     rename_flags;
          __u32     unlink_flags;
       };
       __u64  user_data; /* data to be passed back at completion time */
       union {
          struct {
             /* pack this to avoid bogus arm OABI complaints */
             union {
                /* index into fixed buffers, if used */
                __u16  buf_index;
                /* for grouped buffer selection */
                __u16  buf_group;
             } __attribute__((packed));
             /* personality to use, if used */
             __u16  personality;
             __s32  splice_fd_in;
          };
          __u64  __pad2[3];
       };
    };
    
    5、提交sqe(也就是提交IO)
    /*
    * Submit sqes acquired from io_uring_get_sqe() to the kernel.
    *
    * Returns number of sqes submitted
    */
    int io_uring_submit(struct io_uring *ring)
    {
       return __io_uring_submit_and_wait(ring, 0);
    }
    
    static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr)
    {
       return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr);
    }
    
    /*
    * Submit sqes acquired from io_uring_get_sqe() to the kernel.
    *
    * Returns number of sqes submitted
    */
    static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
                  unsigned wait_nr)
    {
       unsigned flags;
       int ret;
    
    
       flags = 0;
       if (sq_ring_needs_enter(ring, &flags) || wait_nr) {
          if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL))
             flags |= IORING_ENTER_GETEVENTS;
    
    
          ret = __sys_io_uring_enter(ring->ring_fd, submitted, wait_nr,
                      flags, NULL);
          if (ret < 0)
             return -errno;
       } else
          ret = submitted;
    
    
       return ret;
    }
    
    int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete,
              unsigned flags, sigset_t *sig)
    {
       return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig,
                   _NSIG / 8);
    }
    
    int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete,
              unsigned flags, sigset_t *sig, int sz)
    {
       return syscall(__NR_io_uring_enter, fd, to_submit, min_complete,
             flags, sig, sz);
    }
    
    6、提交sqe后,我们只需要等待io完成
    
    
    
    
    

    鸣谢:
    https://segmentfault.com/a/1190000019300089

    demo:
    fio中的代码 https://github.com/lnsyyj/Codes/blob/master/iouring/io_uring-test.c

    相关文章

      网友评论

          本文标题:liburing API

          本文链接:https://www.haomeiwen.com/subject/ogsebktx.html