【】网络io模型
bio每次一个进程专门为了等一个 socket 上的数据就得被从 CPU 上拿下来。然后再换上另一个进程。等到数据 ready 了,睡眠的进程又会被唤醒。总共两次进程上下文切换开销
1.进程在 recv 的时候大概率会被阻塞掉,导致一次进程切换
2.当连接上数据就绪的时候进程又会被唤醒,又是一次进程切换
3.一个进程同时只能等待一条连接,如果有很多并发,则需要很多进程
若要支持超大 fd,需手动修改 FD_SETSIZE 并重新编译,select可以突破1024上限https://elixir.bootlin.com/linux/v3.13.11/source/fs/select.c#L547
select、poll遍历开销 就绪检查、挂载、清理、重新检查(、再次挂载)
https://www.cnblogs.com/tomato0906/articles/7590746.html
https://elixir.bootlin.com/linux/v3.13.11/source/net/ipv4/tcp.c#L434
io_uring 是 Linux 5.1+ 引入的新一代异步 IO 框架,其事件通知支持 “被动唤醒”,用户进程无需主动调用系统调用查询:
核心机制:
io_uring 有两个核心的共享内存队列(用户态 / 内核态直接映射,无需拷贝):
提交队列(SQ):用户态向内核提交 IO 请求;
完成队列(CQ):内核将完成事件主动写入该队列,用户态直接读取。
被动通知流程:
用户进程通过 io_uring_setup 创建 io_uring 实例,映射 SQ/CQ 队列到用户态内存;
通过 io_uring_enter 提交异步请求(或直接写 SQ 队列,无需系统调用);
内核自动完成数据准备 + 拷贝,完成后主动将事件写入 CQ 队列;
用户进程可以通过两种方式获取事件:
被动唤醒:调用 io_uring_wait_cqe 阻塞等待事件(内核有事件时主动唤醒线程,本质是 “内核推送给用户”);
主动查询:直接轮询 CQ 队列的 head/tail 指针(无需系统调用,直接读共享内存)。
核心特点:
无需主动调用类似 io_getevents 的系统调用 ——内核主动将事件写入用户态共享内存的 CQ 队列;
共享内存队列的设计,让事件通知的开销几乎为 0(无系统调用、无数据拷贝);
io_uring_wait_cqe 是阻塞等待,但属于 “被动唤醒”,而非 “主动查询”。
https://mp.weixin.qq.com/s/tr_Jn1Ct2PIzQOnhPG1_EA
https://mp.weixin.qq.com/s/OmRdUgO1guMX76EdZn11UQ
https://zhuanlan.zhihu.com/p/147549069
浙公网安备 33010602011771号