I/O模型 ================================================================================================================================================ Linx I/O模型 I/O类型: 网络I/O:socket的读取 磁盘I/O:从磁盘加载数据到用户空间 1、Linux中的I/O模型有五种:阻塞式(blocking)IO、非阻塞式(nonblocking)IO、多路复用式(multiplexing)IO、事件驱动(signal driven)IO、异步(asynchronous)IO。 要理解这几种模型,以及web服务器使用不同I/O模型的区别,必须理解下面相关的概念及术语。下面,将对相关概念及术语进行介绍。 2、相关概念理解 进程在向内核发起系统调用,一个完整请求I/O操作包括: 1、数据从磁盘到内核内存 2、数据从内核内存到进程内存 1、同步/异步 同步:进程发起一个调用后,再没得到结果之前,被调用者不会给调用者返回结果。调用者要一直等待被调用者返回最终结果, 才能执行后续的操作。 异步:进程发起一个调用后,即便调用者不能立即得到结果,该被调用者也会返回信息,但返回的是未完成状态信息,当调用 完成后,内核会自行通知 调用者取结果或者由调用者通过轮询的方式查看被调用者是否准备就绪。 Note: 同步和异步是站在被调用者如何响应调用者请求的角度理解。异步是被调用者立即返回信息,而同步则是调用者发起 调用后,被挂起。关注被调用者的消息通知机制。 2、阻塞/非阻塞 阻塞:进程发起调用后,在I/O操作未完成之前,调用者进程进程会被挂起,进入阻塞态,调用者在得到返回结果之后才能继续 运行。 非阻塞:进程发起调用后,[被调用函数]完成之前进程不会阻塞,而是立即返回结果。非阻塞但需要忙等待,查看调用是否完成。 Note: 调用者等待被调用者返回调用结果时的状态,即调用者在等待返回结果时的行为状态。 3、组合模型 1、同步阻塞 2、同步非阻塞 调用者需要"轮询",查看数据准备情况。但不断轮询会造成到CPU资源浪费。 4、五种I/O模型 1、阻塞 blocking IO 进程发起调用之后,被阻塞挂起,不能再处理其他事情。 2、非阻塞 nonblocking IO 进程发起调用之后,被调用者立即返回信息,但没有返回最终结果,尽管此时发起调用的进程可以处理其他事情,但需要忙等待,即进程需要 不断的询问被调用者是否准备好,可以返回最终结果,所以效率事实上也并不高。 3、多路复用 multiplexing IO 实现了单个进程处理多个IO请求,单个线程通过监控追踪每一个I/O请求的状态。阻塞到select函数上。(类似异步阻塞IO模型),达到了一个线程 可以处理多个I/O请求的目的。{prefork(worker)就是基于多路IO模型实现的}。数据从内核空间到用户空间依然是阻塞状态。 select 最多能够接受1024个请求 poll { 实现方法: 1.多线程模型:一个进程生成N个线程,每线程响应一个连接请求 2.事件驱动:一个进程处理N个请求 } 启动一个进程,同时响应N个连接请求 单个线程通过记录跟踪每一个Sock(I/O流)的状态 多个I/O可以复用一个进程 理解:单个进程监控多个连接的状态,如果某个连接需要操作时,进程就操作某个连接。 引入代理机制,代理可以监控连接状态。 { 实现: 1983年左右 在BSD里面实现 select 1997年 实现了 poll 2002年 epoll {当连接有I/O流事件产生的时候,epoll就会去告诉进程哪个连接有I/O流事件产生} select与poll原理是一样的,只不过select只能观察1024个连接,epoll可以观察无限个连接且 具有信号驱动I/O模型 的某些特性 Kqueue:FreeBSD实现,对应I/O复用模型,具有信号驱动 I/O模型的某些特性 /dev/poll:SUN的Solaris实现,对应I/O复用模型,具有信号驱动I/O模型的某些特性 Iocp:Windows实现,对应第5种(异步I/O)模型 } select同步阻塞 {Apache} 1、每次调用select都会将fd集合从用户态拷贝到内核态 2、需要在内核遍历传递进来的所有fd 3、select支持的文件描述符数量最多为1024 epool {Nginx} 1、支持一个进程打开大数目的socket描述符 2、I/O效率不随fd数目增加而线性下降 3、使用mmap加速内核与用户空间的消息传递 4、支持边缘触发和水平触发 4、事件(信号)驱动 signal driven IO 进程发起调用之后,被调用者立即返回调用者信息,告知接收到请求,之后调用者能够去处理其他事情,等调用者加载完相关数据之后,会通知 调用者。此种模型不需要调用者忙等待,当数据从磁盘加载到内核内存后,进程复制数据到进程空间的过程依然是阻塞状态(第二个阶段依然是 阻塞状态)。 此处进程接收到被调用的信息后,没有被阻塞挂起,所以进程还可以接收其他请求。 {Apache event模型,一个进程处理多个请求} 通知机制: 水平触发:多次通知 边缘触发:一次通知 (Nginx) 5、异步 asynchronous IO 两个阶段都没有阻塞。异步IO与信号驱动IO最主要的区别是信号驱动IO是由内核 通知何时可以进行IO操作,而异步IO则是由内核告诉我们 IO操作 何时完成了。具体来说就是,信号驱动IO当内核通知 触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓 冲区这个阶段,而异步IO直接是在第二个阶段完成后内核直接通知可以进行后续操作了。 Nginx 4、Select/poll/epoll select 单个进程监视的文件描述符被限制,最大为 1024 /proc/sys/fs/file-max 对socket线性扫描,轮询,效率低 采用内存拷贝方法实现,复制开销大 poll 内存拷贝 监听的连接没有限制 poll特点是“水平触发”,如果报告了fd后,没有被处理, 那么下次poll时会再次报告该fd epoll 支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉 进程哪些fd刚刚变为就绪态,并且只会通知一次 fd就绪内核采用回调机制激活fd 监听连接没有限制 使用MMAP()机制 ================================================================================================================================================