网络I/O模型剖析


2011/12/16 1 网络I/O模型剖析 刘楚 新浪博客系统开发组 2011/12/16 2 同步 异步 阻塞 非阻塞 select epoll poll kqueue apache nginx memcahce redis 本次分享的核心关键字 2011/12/16 3 一个数据是怎么从程序传到网络上去的? 内核读数 据 推数据到 用户态 切换到用 户态 内核打包 数据 数据推回 到内核态 应用程序 处理数据 发送数据 对方内核对 数据拆包 推数据到用 户态 2011/12/16 4 一碗面条的故事 • 这个故事将伴随我们网络I/O这个分享。 • 场景:来自《构建高性能web站点》 我在中关村地下商场逛街,逛累了,想去大食 代买一碗面条。 但是做面条是需要时间的!!! 但是你又想在这段时间内干点别的!!! 由此引发了一系列不同寻常的思考!!! 2011/12/16 5 目录 • 一、I/O模型种类 • 二、同步/异步、阻塞/非阻塞的含义 • 三、select和poll模型 • 四、epoll模型,三者之间的比较 • 五、linux平台主流网络应用I/O模型 2011/12/16 6 一、I/O模型种类 2011/12/16 7 I/O模型种类 • 1、阻塞I/O • 2、非阻塞I/O • 3、I/O复用(I/O多路复用) • 4、信号驱动I/O • 5、异步I/O 2011/12/16 8 (1)阻塞I/O 我也不知道做面条需要多久,不敢出去,只能在那里坐着等。 等做完、吃完之后再逛街。 这里吃面条便是I/O操作,需要等厨师做面条,还要等待自己把面条吃完。 2011/12/16 9 (2)非阻塞I/O 我不甘心在这里等着无聊,我想在这段时间继续逛商场。 但是又怕面条做好了,所以呢? 所以我逛一会儿就回吧台看一眼!结果来回跑了好多次!!! 坑爹啊,饭还没吃就累死了!!!!! 2011/12/16 10 (3)I/O多路复用 我同时在不同的地方点了菜,要跑来跑去的轮询几十遍,累死了。 后来,善良的管理员装了一个电子屏幕:上面写着每个菜的状态 我只需要去看屏幕,我的数据好了没有就行了。 著名的select、poll、epoll的差别就是在这里。 2011/12/16 11 (4)信号驱动 管理员装了一个短信系统,面做好了就发送短信给我。 但是,成本原因,这个短信只发一次,而且在峰值的时候短信队列会有延时! 2011/12/16 12 (5)异步I/O 管理有一个送货员,面做好了派送货员直接送货上门 2011/12/16 13 几个神奇的概念 • 1、同步 • 2、异步 • 3、阻塞 • 4、非阻塞 2011/12/16 14 同步 vs. 异步 • 同步I/O操作: • 异步I/O操作: I/O操作开始 I/O操作结束 阻塞 I/O操作开始 I/O操作结束 不阻塞 2011/12/16 15 阻塞 vs. 非阻塞 • 是否有异步阻塞? 如果数据未准 备好,请求是 否立即返回 应用进程请求I/O 操作(recv)时 阻塞 非阻塞 立即返回 不立即返回 2011/12/16 16 几种I/O模型的比较 2011/12/16 17 二、select/poll模型 2011/12/16 18 select、poll、epoll、kqueue的故事 • select:1983年于4.2BSD中首次出现 • poll:1986年诞生于System V Release 3 • epoll:在linux2.4内核中以/dev/epoll的补丁 方式存在,2003年底发布的linux2.6版本中 开始出现由内核直接支持的实现方法。 • kqueue:FreeBSD中实现了kqueue,和 epoll的特性非常接近。 2011/12/16 19 select and poll • I/O复用 • 功能相同,来源不同 • 功能:通过检验一组文件描述符来检测是 否有特定的事件将在上面发生并在一定的 时间内等待其发生。 2011/12/16 20 select和poll区别(1) 1.BSD系统 2.每次调用会 改变FD表 3.对FD数量有 限制,1024 select 1.SysV(AT&T) 系统 2.不会改变FD表, 不用在每次调用 前重新建立FD表 3.对FD数量无限 制,取决于内存 poll 2011/12/16 21 select和poll区别(2) 受到socket描 述符上的 O_NDELAY标 记和 O_NONBLOC K标记的影响, select poll() 函数不会 受到socket描述 符上的 O_NDELAY标 记和 O_NONBLOCK 标记的影响 poll 2011/12/16 22 select函数 • 定义: –#include –#include – int select (int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); 2011/12/16 23 select:I/O复用示意图 2011/12/16 24 fd_set类型操作 • void FD_ZERO(fd_set *fdset); • void FD_SET(int fd, fd_set *fdset); • void FD_CLR(int fd, fd_set *fdset); • int FD_ISSET(int fd, fd_set *fdset); 2011/12/16 25 poll函数 • 定义: –#include – int poll (struct pollfd *fdarray, unsigned long nfds, int timeout); • pollfd 指定测试某个给定描述字fd的条件 – struct pollfd { • int fd; • short events; • short revents; } 2011/12/16 26 三、epoll 2011/12/16 27 epoll • I/O多路复用 • AIO • 2003年底发布的linux2.6版本中开始出现由 内核直接支持的实现方法 2011/12/16 28 epoll优点(1) • 支持一个进程打开大数目的socket描述符 (FD) – select :一个进程所打开的FD数目有限制,由 /usr/include/bits/typesizes.h中的FD_SETSIZE 设置,默认值为1024 – poll:对于FD没有限制,取决于系统内存 – epoll: 支持的FD上限是最大可以打开文件的 数目,在1GB内存的机器上大约是10万左右, 具体数目可以从文件/proc/sys/fs/file-max察看 2011/12/16 29 epoll优点(2) • IO效率不随FD数目增加而线性下 降 –select/poll:线性扫描FD全部的集合 –epoll:只会对"活跃"的socket进行操作-- -这是因为在内核实现中epoll是根据每 个fd上面的callback函数实现的。 2011/12/16 30 epoll优点(3) • 减少了将FD表从用户空间拷入内核的 次数 –poll:每次调用都会将FD表从用户空间拷 入内存一次 –epoll:仅仅是在函数epoll_ctl调用时,将 相应的FD拷入内存,不会再每次 epoll_wait时重复拷入 2011/12/16 31 epoll触发模式 • LT(level triggered):水平触发,默认工作 方式,同时支持block和no-block socket。 • ET (edge-triggered): 边缘触发,高速工 作方式,只支持no-block socket。 2011/12/16 32 一个测试(1) 2011/12/16 33 一个测试(2) 2011/12/16 34 一个测试(3) 2011/12/16 35 一个测试(4) 2011/12/16 36 events字段(1) • EPOLLIN :表示对应的文件描述符可以读 (包括对端SOCKET正常关闭); • EPOLLOUT:表示对应的文件描述符可以 写; • EPOLLERR:表示对应的文件描述符发生 错误; 2011/12/16 37 events字段(2) • EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发 (Level Triggered)来说的。 2011/12/16 38 epoll_create() • int epoll_create(int size); 2011/12/16 39 epoll_ctl() • int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); – EPOLL_CTL_ADD:注册新的fd到epfd中 – EPOLL_CTL_MOD:修改已经注册的fd的监听 事件 – EPOLL_CTL_DEL:从epfd中删除一个fd 2011/12/16 40 epoll_wait() • int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 2011/12/16 41 示例代码(1) • epfd=epoll_create(256); • 创建监听套接字 • epoll_ctl(epfd,EPOLL_CTL_ADD, listenfd,&ev); • 准备sockaddr等参数 • bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr)); • listen(listenfd, LISTENQ); 2011/12/16 42 示例代码(2) • for( ; ; ) • { • nfds = epoll_wait(epfd,events,20,500); • for(i=0;i
还剩57页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 10 人已下载

下载pdf

pdf贡献者

darkness

贡献于2012-08-20

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf