这一季主要是记录了我家瑄宝
6-7个月这段时间的生活点滴
本季集锦片段:
镜头感超级棒的瑄宝
小猪猪是瑄宝的好伙伴~
小小年纪就会弹奏《图森破》,哈哈~
这位美女,你的玉足很香吗?蛤蛤~
冷不丁地逗你一下~
这一季主要是记录了我家瑄宝
6-7个月这段时间的生活点滴
本季集锦片段:
镜头感超级棒的瑄宝
小猪猪是瑄宝的好伙伴~
小小年纪就会弹奏《图森破》,哈哈~
这位美女,你的玉足很香吗?蛤蛤~
冷不丁地逗你一下~
IO 多路复用是一种同步IO模型:
IO
:网络I/O。多路
:多个文件句柄。复用
:一个线程可以监视多个文件句柄。一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作,没有文件句柄就绪就会阻塞应用程序,交出CPU。最大优势是减少系统开销,不必创建过多的进程/线程。
IO 多路复用机制要想高效使用,一般还需要把 socket 设置成「非阻塞」模式:
socket 没有数据可读/可写时,应用层去
read/write
socket 也不会阻塞住(内核会返回指定错误,应用层可继续重试),这样应用层就可以去处理其它业务逻辑,不会阻塞影响性能。
select会阻塞住监视3类:writefds
(写)、readfds
(读)、和exceptfds
(异常)文件描述符,等有数据、可读、可写、出异常或超时、就会返回;返回后通过遍历fdset整个数组来找到就绪的描述符fd,然后进行对应的IO读写操作。
优点:
缺点:
基本原理与select一致,也是 轮询+遍历,但是它没有最大连接数的限制,原因是它的fd集合是基于链表来存储的.
通过 epoll_ctl
注册fd,一旦fd就绪就会通过 callback
回调机制来激活对应fd,进行相关的io操作。epoll之所以高性能是得益于它的三个函数:
epoll_create
: 系统启动时,在Linux内核里面申请一个 B+树 结构文件系统,返回epoll对象,也是一个fdepoll_ctl
: 每新建一个连接,都通过该函数操作epoll对象,在这个对象里面修改添加删除对应的链接fd, 绑定一个callback函数epoll_wait
: 轮训所有的callback集合,并完成对应的IO操作优点:
mmap
同一块内存实现(mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间)相同点:select,poll,epoll
本质上都是 同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的。
不同点:
select | poll | epoll | |
---|---|---|---|
操作方式 | 遍历 | 遍历 | 回调 |
数据结构 | bitmap | 数组 | 红黑树 |
最大连接数 | 1024(x86)或 2048(x64) | 无上限 | 无上限 |
最大文件描述符数 | 一般有最大值限制 | 65535 | 65535 |
fd就绪 | 从内核空间拷贝到用户空间 | 从内核空间拷贝到用户空间 | 触发回调不拷贝 |
工作模式 | LT | LT | 支持ET高效模式 |
工作效率 | 线性遍历 O(n) | 线性遍历 O(n) | 事件通知方式 O(1) |
在 Redis 事件驱动框架代码中,分别使用了 select 和 epoll 两种机制。
为什么 Redis 没有使用 poll 这一机制?
首先,select 并不是只有 Linux 才支持的,Windows 平台也支持。而 Redis 针对不同操作系统,会选择不同的 IO 多路复用机制来封装事件驱动框架。因为 epoll 性能优于 select 和 poll,所以 Linux 平台下,Redis 直接会选择 epoll。而 Windows 不支持 epoll 和 poll,所以会用 select 模型。