- I/O复用模型
-
传统阻塞I/O模型
串行化处理,就是要等,假如进行到accept操作,cpu需要等待客户端发送的数据到tcp接收缓冲区才能进行read操作,而在此期间cpu不能执行任何操作。
-
I/O复用
用一个进程监听大量连接,当某个连接可读/可写的时候,系统就发送事件通知进程处理该连接的数据。即进程不会当某个连接还没准备好的时候,进程不会等它准备好,而是去处理其它任务。
-
-
epoll网络编程
epoll是linux提供的I/O复用API,是一种事件驱动的I/O模型,它可以用于高效地处理大量的并发连接。其中,'e’代表"event"(事件),意味着epoll可以监测并响应特定的事件,如文件描述符上的读写事件、错误事件等。这种事件驱动的模型可以有效地管理和处理大规模的并发连接,提高系统的性能和效率。
epoll触发条件:
- 条件触发
- 缓冲区可读/写(缓冲里有东西就一直触发)
- 边缘触发
- 只有在缓冲区从不可写切换到可写才触发一次
- 只有收到客户端数据时才触发一次(即使读取数据后还有数据也不会再触发)
- 条件触发
-
redis的epoll
redis事件api
- aeApiCreate:初始化I/O复用机制上下文环境
- aeApiAddEvent、aeApiDelEvent:增加或删除一个监听对象
- aeApiPoll:阻塞进程,等待事件就绪或给定事件到期
- aeEventLoop:redis事件循环器,负责管理事件
- aeFileEvent:存储一个文件描述符已注册的文件事件
- aeTimeEvent:存储一个时间事件的信息
redis中会有一个专门的结构体来存放epoll数据(aeApiState)
aeApiCreate负责初始化I/O复用机制的上下文环境:
- 创建aeApiState结构体,为aeApiState.events申请空间,用于存放后续已就绪事件
- 调用epoll_create创建epoll实例
- 将aeApiState结构赋值给eventLoop.apidata
- eventLoop轮询apidata中的events的文件描述符(fd),如果该fd已经存在监听对象就修改监听对象,否则添加监听对象。
- 将AE(redis定义的读/写)抽象事件转换为epoll事件类型,AE_READABLE(可读)转换为epoll的EPOLLIN事件(缓冲区可读),AE_WRITE对应epoll的EPOLLOUT事件(缓冲区可写),由此可见redis用的是epoll的条件触发。
- 调用epoll_ctl函数,往epoll实例中添加或修改监听对象
- aeApiPoll在aeEventLoop每次被调用,负责阻塞进程等待事件发生或者等待时间过期:
- 调用epoll_wait函数,阻塞事件发生或给定时间到期
- 如果I/O复用机制中有事件就绪,则将已就绪事件装载到eventLoop.fired中
- epoll中的事件要转换为redis事件,如EPOLLIN要转换为AE_READABLE