Skip to content

Latest commit

 

History

History
92 lines (77 loc) · 2.72 KB

io_uring_recv_impl.md

File metadata and controls

92 lines (77 loc) · 2.72 KB

在io_uring中设置block的socket是否有意义?

先看IORING_OP_RECVMSG pdef 其支持pollin

    [IORING_OP_RECVMSG] = {
        .needs_file     = 1,
        .unbound_nonreg_file    = 1,
        .pollin         = 1,
        .buffer_select      = 1,
        .ioprio         = 1,
        .manual_alloc       = 1,
        .name           = "RECVMSG",
#if defined(CONFIG_NET)
        .async_size     = sizeof(struct io_async_msghdr),
        .prep           = io_recvmsg_prep,
        .issue          = io_recvmsg,
        .prep_async     = io_recvmsg_prep_async,
        .cleanup        = io_sendmsg_recvmsg_cleanup,
        .fail           = io_sendrecv_fail,

在第一次处理sqe的时候会强制使用IO_URING_F_NONBLOCK调用io_recvmsg

static inline void io_queue_sqe(struct io_kiocb *req)
    __must_hold(&req->ctx->uring_lock)
{
    int ret;

    ret = io_issue_sqe(req, IO_URING_F_NONBLOCK|IO_URING_F_COMPLETE_DEFER);

    /*
     * We async punt it if the file wasn't marked NOWAIT, or if the file
     * doesn't support non-blocking read/write attempts
     */
    if (likely(!ret))
        io_arm_ltimeout(req);
    else
        io_queue_async(req, ret);
}

对于recv的实现 如果传入了IO_URING_F_NONBLOCK默认就会走MSG_DONTWAIT放进flag里面,对于recvmsg系统调用这个flag会非阻塞尝试下看看有没有数据

所以第一次的非阻塞尝试与是不是block的socket没关系

int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
{
   //....
    bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
   //....
    flags = sr->msg_flags;
    if (force_nonblock)
        flags |= MSG_DONTWAIT;
        
    //....
    ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
                     kmsg->uaddr, flags);
    //....                     
 }

若取不到数据直接走了io_queue_async -> io_arm_poll_handler -> __io_arm_poll_handler

if (def->pollin) {
//这里的recv op是支持 poll in的
//最后会直接挂载到vfs的poll上去
        mask |= EPOLLIN | EPOLLRDNORM;

        /* If reading from MSG_ERRQUEUE using recvmsg, ignore POLLIN */
        if (req->flags & REQ_F_CLEAR_POLLIN)
            mask &= ~EPOLLIN;
    } else {
        mask |= EPOLLOUT | EPOLLWRNORM;
    }
    if (def->poll_exclusive)
        mask |= EPOLLEXCLUSIVE;

    apoll = io_req_alloc_apoll(req, issue_flags);
    if (!apoll)
        return IO_APOLL_ABORTED;
    req->flags &= ~(REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL);
    req->flags |= REQ_F_POLLED;
    ipt.pt._qproc = io_async_queue_proc;

    io_kbuf_recycle(req, issue_flags);
//简单来说就是 mask = vfs_poll(req->file, &ipt->pt) & poll->events;
    ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask, issue_flags);