1,常用的I/O模型
1)阻塞I/O(
blocking I/O
)
recvfrom:从socket上获取数据,并捕获发送源的地址。
1.应用发起recvfrom系统调用,应用被阻塞。user -> kernel
2.kernel等待数据。处于内核态。
3.数据就绪, kernel复制data到应用的buffer。处于内核态。
4.应用从阻塞里恢复,处理数据。kernel -> user
2)非阻塞I/O(non-blocking I/O
)
1.应用重复发起recvfrom轮询(polling)内核,看下数据是否就绪。
2.某次轮询发现数据备好,再直接发起recvfrom系统调用阻塞取数据。
3.kernel复制data到应用的buffer。
4.应用处理数据。
3)I/O多路复用(I/O multiplexing
)
1.调用select,阻塞等待可读的fd。
2.发起recvfrom系统调用,阻塞获取数据。
3.kernel复制data到应用的buffer。
4.应用处理数据。
2,select/poll/epoll模型
1)select
select:早期I/O多路复用的实现。最多1024个fd;需要内核/用户空间拷贝fd_set;应用需要遍历fd_set。
2)poll
改进select,取消1024个fd的限制,理论上可以监控无限个fd。但仍需copy和遍历pollfd。
3)epoll
linux I/O多路复用最新的实现。mmap共享部分内核/用户空间,避免copy;基于事件驱动,避免轮询。
epoll_create:创建红黑树管理epoll事件表。
epoll_ctl:加入socket读写事件。
epoll_wait:阻塞等待返回可读、可写的fd,只返回发生变化的事件,避免轮询。
3,应用场景
1)基本知识
阻塞和非阻塞:应用程序等待结果时是否挂起。
同步和异步:关注的是通信。同步一直等待结果并返回;异步直接返回等待通知或者回调。
2)BIO和NIO
BIO:方法都是同步阻塞的;一个请求启动一个线程,上下文切换严重;接受和处理请求都在一个线程里,并发受限,阻塞新连接。
NIO:基于epoll事件模型,解放线程,提高系统吞吐量。
Selector:I/O多路复用的封装,由内核来完成事件的分发和告知。
SelectionKey:代表I/O事件和绑定关系。
Channel:对非阻塞的支持,可以连接文件和socket。
Buffer:从channel中读写数据到buffer。(channel支持非阻塞,所以读出来的东西需要存起来)
3)nginx的epoll模型
master/worker:master监控进程,worker工作进程(个数通常为cpu核心数。)
异步:worker发送request到upstream,注册fd事件表中,等待异步回调。
I/O多路复用:使用epoll模型,少数worker可以处理大量并发。
处理request的过程:request到worker进程 ->worker发送request到upstream -> 注册fd事件到epoll模型中 -> worker继续干活。
网友评论