Skip to content

Commit c26fbb4

Browse files
io uring recv;
1 parent f5094df commit c26fbb4

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
* [io_uring介绍](io_uring/io_uring.md)
99
* [io_uring,Memory以及Procator的Socket IO](io_uring/io_uringAndMemory.md)
10+
* [io_uring_recv是怎么实现的](io_uring/io_uring_recv_impl.md)
1011

1112
## reactive
1213

@@ -46,4 +47,4 @@
4647
## CPP
4748

4849
* [C++20协程入门](cpp_coroutine/first.md)
49-
* [async scope和通用回调转协程](cpp_coroutine/async_scope.md)
50+
* [async scope和通用回调转协程](cpp_coroutine/async_scope.md)

io_uring/io_uring_recv_impl.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
### 在io_uring中设置block的socket是否有意义?
2+
3+
先看IORING_OP_RECVMSG pdef 其支持pollin
4+
5+
```C++
6+
[IORING_OP_RECVMSG] = {
7+
.needs_file = 1,
8+
.unbound_nonreg_file = 1,
9+
.pollin = 1,
10+
.buffer_select = 1,
11+
.ioprio = 1,
12+
.manual_alloc = 1,
13+
.name = "RECVMSG",
14+
#if defined(CONFIG_NET)
15+
.async_size = sizeof(struct io_async_msghdr),
16+
.prep = io_recvmsg_prep,
17+
.issue = io_recvmsg,
18+
.prep_async = io_recvmsg_prep_async,
19+
.cleanup = io_sendmsg_recvmsg_cleanup,
20+
.fail = io_sendrecv_fail,
21+
```
22+
23+
在第一次处理sqe的时候会强制使用IO_URING_F_NONBLOCK调用io_recvmsg
24+
25+
```C++
26+
static inline void io_queue_sqe(struct io_kiocb *req)
27+
__must_hold(&req->ctx->uring_lock)
28+
{
29+
int ret;
30+
31+
ret = io_issue_sqe(req, IO_URING_F_NONBLOCK|IO_URING_F_COMPLETE_DEFER);
32+
33+
/*
34+
* We async punt it if the file wasn't marked NOWAIT, or if the file
35+
* doesn't support non-blocking read/write attempts
36+
*/
37+
if (likely(!ret))
38+
io_arm_ltimeout(req);
39+
else
40+
io_queue_async(req, ret);
41+
}
42+
```
43+
44+
对于recv的实现 如果传入了IO_URING_F_NONBLOCK默认就会走MSG_DONTWAIT放进flag里面,对于recvmsg系统调用这个flag会非阻塞尝试下看看有没有数据
45+
46+
所以第一次的非阻塞尝试与是不是block的**socket没关系**
47+
48+
```C++
49+
int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
50+
{
51+
//....
52+
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
53+
//....
54+
flags = sr->msg_flags;
55+
if (force_nonblock)
56+
flags |= MSG_DONTWAIT;
57+
58+
//....
59+
ret = __sys_recvmsg_sock(sock, &kmsg->msg, sr->umsg,
60+
kmsg->uaddr, flags);
61+
//....
62+
}
63+
```
64+
65+
若取不到数据直接走了io_queue_async -> io_arm_poll_handler -> __io_arm_poll_handler
66+
67+
```C++
68+
if (def->pollin) {
69+
//这里的recv op是支持 poll in的
70+
//最后会直接挂载到vfs的poll上去
71+
mask |= EPOLLIN | EPOLLRDNORM;
72+
73+
/* If reading from MSG_ERRQUEUE using recvmsg, ignore POLLIN */
74+
if (req->flags & REQ_F_CLEAR_POLLIN)
75+
mask &= ~EPOLLIN;
76+
} else {
77+
mask |= EPOLLOUT | EPOLLWRNORM;
78+
}
79+
if (def->poll_exclusive)
80+
mask |= EPOLLEXCLUSIVE;
81+
82+
apoll = io_req_alloc_apoll(req, issue_flags);
83+
if (!apoll)
84+
return IO_APOLL_ABORTED;
85+
req->flags &= ~(REQ_F_SINGLE_POLL | REQ_F_DOUBLE_POLL);
86+
req->flags |= REQ_F_POLLED;
87+
ipt.pt._qproc = io_async_queue_proc;
88+
89+
io_kbuf_recycle(req, issue_flags);
90+
//简单来说就是 mask = vfs_poll(req->file, &ipt->pt) & poll->events;
91+
ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask, issue_flags);
92+
```

0 commit comments

Comments
 (0)