+
+
+
+
+
+
+
+
+
+
+
+
+ 在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);
+
+
+
+
+
+
+
+
+ results matching ""
+
+
+
+